Print_value not printing anything

I’m trying to call print_value inside defn and it doesn’t seem to be working. The function call works and I am getting the expected result but it’s not outputting any value in livebook.

Here is the function:

defn gradient_descent(x, y, w_in, b_in, alpha, options) do
    loss_history = Nx.iota({options[:iterations]}, type: :f64)
    
    w = w_in
    b = b_in

    range = 0..options[:iterations]

    while {x, y, w, b, alpha, loss_history}, i <- range do
      {dj_db, dj_dw} = compute_gradient_logistic(x, y, w, b)

      w_new = w - alpha * dj_dw
      b_new = b - alpha * dj_db

      loss_history = 
        if i < 100000 do
          Nx.indexed_put(loss_history, Nx.stack([i]), compute_cost_logistic(x, y, w, b))
        end

      if rem(i, Nx.ceil(options[:iterations] / 10)) == Nx.tensor(0.0) do
        print_value(loss_history[-1], label: "Cost:")
      end


      {x, y, w_new, b_new, alpha, loss_history}
end

I’m calling it with

w_tmp = Nx.tensor([0.0, 0.0], type: :f64)
b_tmp = Nx.tensor(0.0, type: :f64)
alpha = Nx.tensor(0.1, type: :f64)
iterations = 10_000

LogisticRegression.gradient_descent(x_train, y_train, w_tmp, b_tmp, alpha, iterations: iterations)

Hey @zacksiri!

Nx builds a computation graph with all the operations, for example when you do y = Nx.sin(x), y is a node with sin operation and points to x operand as the parent node. So with that in mind, the return value of print_value must be included in the graph, so you need to assign it and return it.

print_value returns the given tensor (it effectively attached a “hook” to it), so usually you would do x = print_value(x), but since you want to print only the last element, you can pass a transform function, as in x = print_value(x, & &1[-1]).

All that said, I believe this is what you want:

loss_history =
  if rem(i, Nx.ceil(options[:iterations] / 10)) == Nx.tensor(0.0) do
    print_value(loss_history, & &1[-1], label: "Cost:")
  else
    loss_history
  end
1 Like

Got it. That makes sense now.

I adjusted your solution abit because I used Nx.iota to create a tensor with {10_000} the values are incorrect if I use -1 until I reach the last. If I wanted to print the last replaced element I had to change it to:

loss_history =
   if rem(i, Nx.ceil(options[:iterations] / 10)) == Nx.tensor(0.0) do
      print_value(loss_history, & &1[i - 1], label: "Cost:")
   else
      loss_history
   end

I have to adapt my way of thinking, working numerically with Nx is a bit different than what I’m used to with standard Elixir.

Thank you for your help!