RuntimeError: Expected object of scalar type Long but got scalar type Float when using CrossEntropyLoss

bachir: <p>I have a NN that ends with the following linear layers</p>
<pre><code class="lang-auto">dense = nn.Linear(input_size, 1)
</code></pre>
<p>if I use <code>CrossEntropyLoss</code> as loss function (as I’m <code>y</code> is supposed to be the class number) I get the following error</p>
<pre><code class="lang-auto">RuntimeError                              Traceback (most recent call last)
&lt;ipython-input-39-72a754e03ca3&gt; in &lt;module&gt;()
      1 lr = 2e-2
      2 learner = SimpleLearner([train_dl, test_dl], model, loss_func)
----&gt; 3 history = learner.fit(10)

&lt;ipython-input-37-121ec7440a76&gt; in fit(self, epochs, lr)
     26             losses = []
     27             for x,y in self.data[0]:
---&gt; 28                 losses.append(self.update(x, y , lr))
     29             history['losses'].append(np.mean(losses))
     30         return history

&lt;ipython-input-37-121ec7440a76&gt; in update(self, x, y, lr)
     10         for p in model.parameters(): w2 += (p**2).sum()
     11         # add to regular loss
---&gt; 12         loss = loss_func(y_hat, y) + w2 * self.wd
     13         loss.backward()
     14         with torch.no_grad():

/usr/local/lib/python3.6/dist-packages/torch/nn/modules/module.py in __call__(self, *input, **kwargs)
    477             result = self._slow_forward(*input, **kwargs)
    478         else:
--&gt; 479             result = self.forward(*input, **kwargs)
    480         for hook in self._forward_hooks.values():
    481             hook_result = hook(self, input, result)

/usr/local/lib/python3.6/dist-packages/torch/nn/modules/loss.py in forward(self, input, target)
    865     def forward(self, input, target):
    866         return F.cross_entropy(input, target, weight=self.weight,
--&gt; 867                                ignore_index=self.ignore_index, reduction=self.reduction)
    868 
    869 

/usr/local/lib/python3.6/dist-packages/torch/nn/functional.py in cross_entropy(input, target, weight, size_average, ignore_index, reduce, reduction)
   1778     if size_average is not None or reduce is not None:
   1779         reduction = _Reduction.legacy_get_string(size_average, reduce)
-&gt; 1780     return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
   1781 
   1782 

/usr/local/lib/python3.6/dist-packages/torch/nn/functional.py in nll_loss(input, target, weight, size_average, ignore_index, reduce, reduction)
   1623                          .format(input.size(0), target.size(0)))
   1624     if dim == 2:
-&gt; 1625         ret = torch._C._nn.nll_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
   1626     elif dim == 4:
   1627         ret = torch._C._nn.nll_loss2d(input, target, weight, _Reduction.get_enum(reduction), ignore_index)

RuntimeError: Expected object of scalar type Long but got scalar type Float for argument #2 'target'
</code></pre>
<p>What should be the loss (similarly for the accuracy) function that I should be using? if <code>CrossEntropyLoss</code> is the good one that should I do with the output of the linear layer?</p>

ptrblck: <p>The output layer should have the number of classes as <code>out_features</code>.<br>
Currently your output layer only returns one neuron, which corresponds to class0.<br>
For a binary use case, this should work:</p>
<pre><code class="lang-python">batch_size = 5
nb_classes = 2
in_features = 10

model = nn.Linear(in_features, nb_classes)
criterion = nn.CrossEntropyLoss()

x = torch.randn(batch_size, in_features)
target = torch.empty(batch_size, dtype=torch.long).random_(nb_classes)

output = model(x)
loss = criterion(output, target)
loss.backward()
</code></pre>
<p>However, this doesn’t seem to be the error you are seeing here.<br>
As you can see in my example, target should be of type <code>torch.long</code>. Try to fix the shapes and call <code>target = target.long()</code> to transform the data type.</p>
<p>Alternatively, you could return just one neuron and use <code>nn.BCEWithLogitsLoss</code> as your criterion.<br>
This would also work with a float target.</p>

bachir: <p>I figured the problem, I was creating the <code>target</code> tensor and passing float as dtype <img src="https://discuss.pytorch.org/images/emoji/apple/disappointed_relieved.png?v=6" title=":disappointed_relieved:" class="emoji" alt=":disappointed_relieved:"><br>
the following fixed the issue.</p>
<pre><code class="lang-auto">y_tensor = torch.tensor(y_train, dtype=torch.long, device=device)
</code></pre>

Rickyim: <blockquote>
<p>target should be of type  <code>torch.long</code> .</p>
</blockquote>
<p>Why does the type of target have to be <code>torch.long</code> ?<br>
Thank you!</p>

ptrblck: <p>The target should be a <code>LongTensor</code> using <code>nn.CrossEntropyLoss</code> (or <code>nn.NLLLoss</code>), since it is used to index the output logit (or log probability) for the current target class as shown in <a href="https://pytorch.org/docs/stable/nn.html#torch.nn.CrossEntropyLoss" rel="nofollow noopener">this formula</a> (note the indexing in <code>x[class]</code>).</p>

Hassan_Saeed: <p>I’ve specified the dtype to be torch.long, and still the error pops out, but not in nn.CrossEntropyLoss in the prediction line, here is the error:</p>
<blockquote>
<p>RuntimeError                              Traceback (most recent call last)<br>
 in <br>
----&gt; 1 train(model,train_loader,valid_loader)</p>
<p> in train(model, train_dataloader, valid_dataloader, epochs, lr)<br>
18             <span class="hashtag-raw">#print</span>(len(target[0][‘label’]))<br>
19             optimizer.zero_grad()<br>
—&gt; 20             output = model(data,target)<br>
21             print(‘check’)<br>
22             loss = criterion(output,target)</p>
<p>/opt/conda/lib/python3.6/site-packages/torch/nn/modules/module.py in <strong>call</strong>(self, *input, **kwargs)<br>
491             result = self._slow_forward(*input, **kwargs)<br>
492         else:<br>
 → 493             result = self.forward(*input, **kwargs)<br>
494         for hook in self._forward_hooks.values():<br>
495             hook_result = hook(self, input, result)</p>
<p>/opt/conda/lib/python3.6/site-packages/torchvision/models/detection/generalized_rcnn.py in forward(self, images, targets)<br>
49         if isinstance(features, torch.Tensor):<br>
50             features = OrderedDict([(0, features)])<br>
—&gt; 51         proposals, proposal_losses = self.rpn(images, features, targets)<br>
52         detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets)<br>
53         detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes)</p>
<p>/opt/conda/lib/python3.6/site-packages/torch/nn/modules/module.py in <strong>call</strong>(self, *input, **kwargs)<br>
491             result = self._slow_forward(*input, **kwargs)<br>
492         else:<br>
 → 493             result = self.forward(*input, **kwargs)<br>
494         for hook in self._forward_hooks.values():<br>
495             hook_result = hook(self, input, result)</p>
<p>/opt/conda/lib/python3.6/site-packages/torchvision/models/detection/rpn.py in forward(self, images, features, targets)<br>
413         losses = {}<br>
414         if self.training:<br>
 → 415             labels, matched_gt_boxes = self.assign_targets_to_anchors(anchors, targets)<br>
416             regression_targets = self.box_coder.encode(matched_gt_boxes, anchors)<br>
417             loss_objectness, loss_rpn_box_reg = self.compute_loss(</p>
<p>/opt/conda/lib/python3.6/site-packages/torchvision/models/detection/rpn.py in assign_targets_to_anchors(self, anchors, targets)<br>
272         for anchors_per_image, targets_per_image in zip(anchors, targets):<br>
273             gt_boxes = targets_per_image[“boxes”]<br>
 → 274             match_quality_matrix = self.box_similarity(gt_boxes, anchors_per_image)<br>
275             matched_idxs = self.proposal_matcher(match_quality_matrix)<br>
276             # get the targets corresponding GT for each proposal</p>
<p>/opt/conda/lib/python3.6/site-packages/torchvision/ops/boxes.py in box_iou(boxes1, boxes2)<br>
130     area2 = box_area(boxes2)<br>
131<br>
 → 132     lt = torch.max(boxes1[:, None, :2], boxes2[:, :2])  # [N,M,2]<br>
133     rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:])  # [N,M,2]<br>
134</p>
<p>RuntimeError: Expected object of scalar type Long but got scalar type Float for argument <span class="hashtag-raw">#2</span> ‘other’</p>
</blockquote>

ptrblck: <p>I’m not familiar with your code, but it seems <code>boxes1</code> is passed as a LongTensor, while <code>boxes2</code> is a FloatTensor. Could this be the case?<br>
If so, you could call <code>float()</code> in the first or <code>long()</code> on the second argument, depending on your expected result.</p>

Hassan_Saeed: <p>thanks for your response, I was wondering why there is boxes 1 and boxes 2, my input is about an image with a lot of labels in it and each label have 4 values for it box, so actually each label have one box only, so what does boxes 2 is for, if you have any idea in general??</p>

damien: <aside class="quote no-group" data-username="bachir" data-post="3" data-topic="30542">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/b/e36b37/48.png" class="avatar"> bachir:</div>
<blockquote>
<p>y_tensor = torch.tensor(y_train, dtype=torch.long, device=device)</p>
</blockquote>
</aside>
<p>It is helpful for me</p>

A_Rojas: <p>I solved my problem with:</p>
<blockquote>
<p>loss = criterion(output, target.long())</p>
</blockquote>
<p>But i don’t know yet why when i do this conversion from a list of ints to a tensor, its data became floats. I’m doing the conversion with torch.Tensor:</p>
<blockquote>
<p>target = torch.Tensor(Target_list)</p>
</blockquote>
<p>is there a way to specify the dtype of the conversion?</p>

A_Rojas: <p>Shows me this <strong>TypeError</strong></p>
<blockquote>
<p>new() received an invalid combination of arguments</p>
</blockquote>
<p>In my case <strong>y_train</strong> is a list of ints</p>

ptrblck: <p>Use <code>torch.tensor</code> with the lowercase t: <code>torch.tensor([0, 1, 2])</code>.</p>

drewkerwin: <p>Why does pytorch require the label to be of type torch.long? Keras did not have this problem. A label should be what the user says it is…</p>
<p>e.g. if I’m creating an LSTM model for the following sequence<br>
[0.08574425157113574, 0.08615396453867125, 0.08615396453867125, 0.08624176097991065, 0.08632949541005121, 0.08641732567552636, 0.08647585287810422, 0.08650518412786463, 0.08752938198611403, 0.08805613808405999]</p>
<p>And the sequence length is 3, then the label for<br>
.08574425157113574, 0.08615396453867125, 0.08615396453867125</p>
<p>is 0.08624176097991065</p>
<p>The above should not be a problem.</p>

ptrblck: <p><code>nn.CrossEntropyLoss</code> expects class indices to index the logits directly (as given in the formula in the docs).<br>
If you want to provide a contiguous target distribution, have a look at <code>nn.KLDivLoss</code>.</p>

djlamar: <p>Is it feasible to allow it to accept a char instead of a long and still index into the logits as mentioned? I’m working on a segmentation problem with around 10 classes, so my label fits comfortably into a single byte. But requiring a long means the mask has to be of type int64, using 7 extra bytes per pixel. This seems non-trivial since then each pixel requires 20 bytes (total across the image and mask) when uint8 mask pixels would mean a total of only 13 bytes, meaning for this problem int64 labels makes a batch require over 50% more memory than with uint8 labels.</p>

simiao_lai: <p>I have the same thought with you, now do you have any ideas?</p>

mathematics: <p><img src="https://discuss.pytorch.org/images/emoji/apple/smiley.png?v=9" title=":smiley:" class="emoji only-emoji" alt=":smiley:"><br>
problem was on dtype of  <code>target</code>,  for labels greater than 1,   i found we should use target of <code>LongTensor</code> not <code>FloatTensor</code> for <code>nn.Crossentropy</code></p>

baolu_pax: <p>If you see this error, you can also try using a <strong>numpy <code>ndarray</code> but with <code>int64</code> types</strong> instead of float types.</p>
<p>In my code, the float part was causing problems. I fix it with:<br>
<code>y = data['outcome'].values.astype('int')</code></p>
<p>Numpy arrays seem to be supported. See PyTorch Lightning Bolts Scikit-Learn example:<br>
</p><aside class="onebox allowlistedgeneric">
  <header class="source">
      <img src="https://pytorch-lightning-bolts.readthedocs.io/en/latest/classic_ml.html/_static/lightning_icon.svg" class="site-icon" width="" height="">
      <a href="https://pytorch-lightning-bolts.readthedocs.io/en/latest/classic_ml.html#logistic-regression" target="_blank" rel="noopener nofollow ugc">pytorch-lightning-bolts.readthedocs.io</a>
  </header>
  <article class="onebox-body">
    <img src="" class="thumbnail" width="" height="">

<h3><a href="https://pytorch-lightning-bolts.readthedocs.io/en/latest/classic_ml.html#logistic-regression" target="_blank" rel="noopener nofollow ugc">Classic ML Models — PyTorch-Lightning-Bolts 0.2.5rc1 documentation</a></h3>



  </article>
  <div class="onebox-metadata">
    
    
  </div>
  <div style="clear: both"></div>
</aside>


Ajmcking: <p>All right, this worked for me whenever I got error on similar lines (I am gonna keep it here for reference):</p>
<ol>
<li>When calling your model on input ensure that your x is float.</li>
<li>However keep your target as long.</li>
<li>Call loss on model output and y without any typecasting.</li>
</ol>
<pre><code class="lang-python">from torch import nn
net = nn.Linear(input, out_classes)
loss_criterion = nn.CrossEntropyLoss()

net = net.to(device)
X = X.to(device).float()
y = y.to(device).long()

y_hat = net(X)
l = loss_criterion(y_hat, y)
</code></pre>

tariqashar5: <p>The code runs for a certain (random) number of times every time I run it and then gives the following error.</p>
<pre><code class="lang-auto">Traceback (most recent call last):
  File "c:/Users/MY/Documents/slicing_dqn/envs/simple_dqn_torch_main.py", line 53, in &lt;module&gt;
    action = agent.choose_action(observation)
  File "c:\Users\MY\Documents\slicing_dqn\envs\simple_dqn_torch.py", line 73, in choose_action
    actions = self.Q_eval.forward(state)
  File "c:\Users\MY\Documents\slicing_dqn\envs\simple_dqn_torch.py", line 26, in forward
    x = F.relu(self.fc1(state))
  File "C:\Users\MY\anaconda3\lib\site-packages\torch\nn\modules\module.py", line 1102, in _call_impl
    return forward_call(*input, **kwargs)
  File "C:\Users\MY\anaconda3\lib\site-packages\torch\nn\modules\linear.py", line 103, in forward
    return F.linear(input, self.weight, self.bias)
  File "C:\Users\MY\anaconda3\lib\site-packages\torch\nn\functional.py", line 1848, in linear
    return torch._C._nn.linear(input, weight, bias)
RuntimeError: expected scalar type Float but found Long
</code></pre>
<p>I am using DQN model and here is the observation space from my environment:</p>
<pre><code class="lang-auto">low = np.array([1, 1, 3, 2]).astype(np.float32) 
high = np.array([10, 10, 30, 20]).astype(np.float32)
self.observation_space = spaces.Box(low, high)

</code></pre>
<p>Here is the agent and model code:</p>
<pre><code class="lang-auto">class Agent:
    def __init__(self, gamma, epsilon, lr, input_dims, batch_size, n_actions,
                 max_mem_size=100000, eps_end=0.05, eps_dec=5e-4):
        self.gamma = gamma
        self.epsilon = epsilon
        self.eps_min = eps_end
        self.eps_dec = eps_dec
        self.lr = lr
        self.action_space = [i for i in range(n_actions)]
        self.mem_size = max_mem_size
        self.batch_size = batch_size
        self.mem_cntr = 0
        self.iter_cntr = 0
        self.replace_target = 100

        self.Q_eval = DeepQNetwork(lr, n_actions=n_actions,
                                   input_dims=input_dims,
                                   fc1_dims=256, fc2_dims=256)
        self.state_memory = np.zeros((self.mem_size, *input_dims), dtype=np.float32)
        self.new_state_memory = np.zeros((self.mem_size, *input_dims), dtype=np.float32)
        self.action_memory = np.zeros(self.mem_size, dtype=np.int32)
        self.reward_memory = np.zeros(self.mem_size, dtype=np.float32)
        self.terminal_memory = np.zeros(self.mem_size, dtype=np.bool)

    def store_transition(self, state, action, reward, state_, terminal):
        index = self.mem_cntr % self.mem_size
        self.state_memory[index] = state
        self.new_state_memory[index] = state_
        self.reward_memory[index] = reward
        self.action_memory[index] = action
        self.terminal_memory[index] = terminal

        self.mem_cntr += 1

    def choose_action(self, observation):
        if np.random.random() &gt; self.epsilon:
            state = T.tensor([observation]).to(self.Q_eval.device)
            actions = self.Q_eval.forward(state)
            action = T.argmax(actions).item()
        else:
            action = np.random.choice(self.action_space)

        return action

    def learn(self):
        if self.mem_cntr &lt; self.batch_size:
            return

        self.Q_eval.optimizer.zero_grad()

        max_mem = min(self.mem_cntr, self.mem_size)

        batch = np.random.choice(max_mem, self.batch_size, replace=False)
        batch_index = np.arange(self.batch_size, dtype=np.int32)

        state_batch = T.tensor(self.state_memory[batch]).to(self.Q_eval.device)
        new_state_batch = T.tensor(
                self.new_state_memory[batch]).to(self.Q_eval.device)
        action_batch = self.action_memory[batch]
        reward_batch = T.tensor(
                self.reward_memory[batch]).to(self.Q_eval.device)
        terminal_batch = T.tensor(
                self.terminal_memory[batch]).to(self.Q_eval.device)

        q_eval = self.Q_eval.forward(state_batch)[batch_index, action_batch]
        q_next = self.Q_eval.forward(new_state_batch)
        q_next[terminal_batch] = 0.0

        q_target = reward_batch + self.gamma*T.max(q_next, dim=1)[0]

        loss = self.Q_eval.loss(q_target, q_eval).to(self.Q_eval.device)
        loss.backward()
        self.Q_eval.optimizer.step()

        self.iter_cntr += 1
        self.epsilon = self.epsilon - self.eps_dec \
            if self.epsilon &gt; self.eps_min else self.eps_min
</code></pre>
<p>I don’t understand what seems to be the issue particularly. If the issue is in the model or my observation space? If it is in obs_space then why does the code run for sometime and then crashes? If anyone can assist, it would be highly appreciated!</p>