torch
torch copied to clipboard
Indexing model parameters doesn't agree with PyTorch semantics
I'm trying to constrain my solution space to the positive orthant so I'm projecting negative parameters (from nn_embedding()) to 0 at each gradient step.
I use: model$lhs_emb$weight$data()[model$lhs_emb$weight$data()<0] <- 0
and get
Error in model$lhs_emb$weight$data()[model$lhs_emb$weight$data() < 0] <- 0 : invalid (NULL) left side of assignment
In PyTorch this is totally legal.
Is this an R limitation or fixable?
This works in theory:
library(torch)
x <- torch_tensor(c(1,2,3))
x[x < 2] <- 0
x
#> torch_tensor
#> 0
#> 2
#> 3
#> [ CPUFloatType{3} ]
Created on 2020-10-19 by the reprex package (v0.3.0)
I wonder if model$lhs_emb$weight
is really a tensor in your module. Can you provide a reproducible example?
Actually it seems to be a bug with using the $data()
method. Here's an equivalent implementation:
library(torch)
m <- nn_embedding(num_embeddings = 100, embedding_dim = 50)
with_no_grad({
m$weight[m$weight < 0] <- 0
})
m$weight$min()
#> torch_tensor
#> 0
#> [ CPUFloatType{} ]
Created on 2020-10-19 by the reprex package (v0.3.0)
Minimal reprex for the error:
library(torch)
m <- nn_embedding(num_embeddings = 100, embedding_dim = 50)
m$weight$data()[m$weight$data() < 0] <- 0
#> Error in m$weight$data()[m$weight$data() < 0] <- 0: invalid (NULL) left side of assignment
Created on 2020-10-19 by the reprex package (v0.3.0)
Here is the class:
require(torch)
embedder <- nn_module(
clasname = "embedder",
initialize = function(n_lhs, n_rhs, dim=10) {
self$lhs_emb <- nn_embedding(n_lhs, dim)
self$lhs_bias <- nn_embedding(n_lhs, 1)
self$rhs_emb <- nn_embedding(n_rhs, dim)
self$rhs_bias <- nn_embedding(n_rhs, 1)
},
forward = function(lhs_indexes, rhs_indexes) {
scores <- torch_sum(self$lhs_emb(lhs_indexes) * self$rhs_emb(rhs_indexes), 2)
scores <- scores + torch_reshape(self$lhs_bias(lhs_indexes), list(-1))
scores <- scores + torch_reshape(self$rhs_bias(rhs_indexes), list(-1))
return(scores)
}
)
model <- embedder(n_lhs=3, n_rhs=3, dim=2)
Now running
model$lhs_emb$weight$data()
Yields
torch_tensor -0.9773 -0.5023 0.6282 -1.4819 -1.0336 1.5777 [ CPUFloatType{3,2} ]
Running
model$lhs_emb$weight$data()[model$lhs_emb$weight$data()<0] <- 0
Yields
Error in model$lhs_emb$weight$data()[model$lhs_emb$weight$data() < 0] <- 0 : invalid (NULL) left side of assignment
Running
with_no_grad({
m$weight[m$weight < 0] <- 0
})
Works except bugs out if you try to use an empty slice, which is another thing PyTorch allows (precisely for ease of this kind of projection).
Ok! This should be an easy fix, I'll do it as soon as possible.
Thanks!
Wait, that doesn't seem to error for me:
library(torch)
m <- nn_embedding(num_embeddings = 100, embedding_dim = 50)
m$weight$min()
#> torch_tensor
#> -3.66959
#> [ CPUFloatType{} ]
with_no_grad({
m$weight[m$weight < -100] <- 0
})
m$weight$min()
#> torch_tensor
#> -3.66959
#> [ CPUFloatType{} ]
Created on 2020-10-19 by the reprex package (v0.3.0)
Are you sure this is the cause? What exactly is an empty slice?
Oops, had a typo, was a non-existent rather than empty slice.
Ok, so IIUC the with_no_grad
solution is working as expected?
Ok, so IIUC the
with_no_grad
solution is working as expected?
Yes, though would be good to also have the data() method correct since this is copy-pasted PyTorch code and it would be great for that to just work after swapping . to $.