Ошибка Python RuntimeError: ожидаемый скалярный тип Long, но найден Double

#python #numpy #pytorch

#python #numpy #pytorch

Вопрос:

Во-первых, я довольно новичок в python / ML в целом. Я пытаюсь использовать модель, изображенную в stackabuse, поверх моего собственного набора данных.

Все проходит гладко, пока я не буду готов к запуску эпох.

При отладке я вижу, что он не работает с функцией CrossEntropyLoss, и я получаю ожидаемую ошибку long found double. Набор данных, в котором, по-видимому, происходит сбой, — это столбец my tdiff, который я вычислил, но, похоже, я не могу понять, как преобразовать его в long .

Есть ли что-то, чего мне не хватает, пытаясь разобраться в этом?

Чтобы было ясно, это то, что я ДУМАЮ, что это основано на моих крайне ограниченных знаниях о функции:

 import pandas as pd
import sqlite3 as sq
import numpy as np 
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import seaborn as sns 






con = sq.connect("filepath")
df = pd.read_sql_query("SELECT b.actcod,"  
         "a.trnqty, "  
          "b.dlytrn_id, "  
              "a.usr_id, "  
 " b.oprcod, "  
 "b.usr_id as usrid,"  
 " b.tostol as frstol,"  
 " a.tostol, "  
 " b.trndte as bdte,"  
 " a.trndte as adte,"  
 " '' as tdiff"  
 " FROM"  
 " (SELECT  row_number() over(PARTITION by usr_id order by trndte) AS rown,"  
 " trndte,"  
 " dlytrn_id,"  
 " trnqty, "  
 " oprcod,"  
 " actcod,"  
 " frstol,"  
 " tostol,"  
 " usr_id"  
 " FROM Master_File"  
 " WHERE actcod = 'PALPCK') a "  
 " JOIN " 
 " (SELECT  row_number() over(PARTITION by usr_id order by trndte) AS rown,"  
 " trndte,dlytrn_id, trnqty, oprcod,actcod, frstol, tostol, usr_id"  
 " FROM Master_File"  
 " WHERE actcod = 'PALPCK' ) b"  
 " ON b.rown = (a.rown -1)"  
 " and b.usr_id = a.usr_id" # 
 #" LIMIT 10"
,con)


# Create record Count
record_count = df['dlytrn_id'].count()
test_records = int(record_count * .2)
print(record_count)
print(test_records)

#Calculate time delta between scans

df['tdiff'] = pd.TimedeltaIndex.total_seconds(pd.to_datetime(df['adte'].values) - pd.to_datetime(df['bdte'].values))



# Establish column types

cat_column = ['usrid','actcod','tostol','frstol']
num_column = ['trnqty']
dte_column = ['bdte','adte']
op_column = ['tdiff']




#convert column datatypes
for category in cat_column:
    df[category] = df[category].astype('category')
for category in num_column:
    df[category] = df[category].astype('float64')
for category in dte_column:
    df[category] = df[category].astype('datetime64')   
    


#create categorical tensor

usr = df['usrid'].cat.codes.values
act = df['actcod'].cat.codes.values
to = df['tostol'].cat.codes.values
fr = df['frstol'].cat.codes.values

cat_data = np.stack([usr,act,to,fr], 1)
cat_data = torch.tensor(cat_data, dtype=torch.int64)

#Create Numerical Tensor

num_data = np.stack([df[col].values for col in num_column], 1)
num_data = torch.tensor(num_data, dtype=torch.float)



#convert output array

op_data = torch.tensor(df[op_column].values).flatten()

print(df.shape)
print(cat_data.shape)
print(num_data.shape)
print(op_data.shape)


#convert categorical data into an N-Dimensional vector,
#this will allow better ML analysis on relationships

cat_col_sizes = [len(df[column].cat.categories) for column in cat_column]
cat_embedding_sizes = [(col_size, min(50, (col_size 1)//2)) for col_size in cat_col_sizes]
print(cat_embedding_sizes)

#create test batches



cat_train_data = cat_data[:record_count-test_records]
cat_test_data = cat_data[record_count-test_records:record_count]
num_train_data = num_data[:record_count-test_records]
num_test_data = num_data[record_count-test_records:record_count]
train_op = op_data[:record_count-test_records]
test_op = op_data[record_count-test_records:record_count]


print(len(cat_train_data))
print(len(num_train_data))
print(len(train_op))

print(len(cat_test_data))
print(len(num_test_data))
print(len(test_op))



class Model(nn.Module):

    def __init__(self, embedding_size, num_numerical_cols, output_size, layers, p=0.4):
        super().__init__()
        self.all_embeddings = nn.ModuleList([nn.Embedding(ni, nf) for ni, nf in embedding_size])
        self.embedding_dropout = nn.Dropout(p)
        self.batch_norm_num = nn.BatchNorm1d(num_numerical_cols)

        all_layers = []
        num_categorical_cols = sum((nf for ni, nf in embedding_size))
        input_size = num_categorical_cols   num_numerical_cols

        for i in layers:
            all_layers.append(nn.Linear(input_size, i))
            all_layers.append(nn.ReLU(inplace=True))
            all_layers.append(nn.BatchNorm1d(i))
            all_layers.append(nn.Dropout(p))
            input_size = i

        all_layers.append(nn.Linear(layers[-1], output_size))

        self.layers = nn.Sequential(*all_layers)

    def forward(self, x_categorical, x_numerical):
        embeddings = []
        for i,e in enumerate(self.all_embeddings):
            embeddings.append(e(x_categorical[:,i]))
        x = torch.cat(embeddings, 1)
        x = self.embedding_dropout(x)

        x_numerical = self.batch_norm_num(x_numerical)
        x = torch.cat([x, x_numerical], 1)
        x = self.layers(x)
        return x
    
    
model = Model(cat_embedding_sizes, num_data.shape[1], 1, [200,100,50], p=0.4)
print(model)

loss_function = nn.CrossEntropyLoss()

optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

epochs = 300
aggregated_losses = []

for i in range(epochs):
    i  = 1
    y_pred = model(cat_train_data, num_train_data)
    single_loss = loss_function(y_pred, train_op)
    aggregated_losses.append(single_loss)

    if i%25 == 1:
        print(f'epoch: {i:3} loss: {single_loss.item():10.8f}')

    optimizer.zero_grad()
    single_loss.backward()
    optimizer.step()

print(f'epoch: {i:3} loss: {single_loss.item():10.10f}')

print(train_op)
print(type(train_op))

print(op_column)
print(type(op_column))

print(op_data)
print(type(op_data))


con.close()
 

вывод:

 51779
10355
(51779, 11)
torch.Size([51779, 4])
torch.Size([51779, 1])
torch.Size([51779])
[(185, 50), (1, 1), (302, 50), (303, 50)]
41424
41424
41424
10355
10355
10355
Model(
  (all_embeddings): ModuleList(
    (0): Embedding(185, 50)
    (1): Embedding(1, 1)
    (2): Embedding(302, 50)
    (3): Embedding(303, 50)
  )
  (embedding_dropout): Dropout(p=0.4, inplace=False)
  (batch_norm_num): BatchNorm1d(1, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (layers): Sequential(
    (0): Linear(in_features=152, out_features=200, bias=True)
    (1): ReLU(inplace=True)
    (2): BatchNorm1d(200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (3): Dropout(p=0.4, inplace=False)
    (4): Linear(in_features=200, out_features=100, bias=True)
    (5): ReLU(inplace=True)
    (6): BatchNorm1d(100, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (7): Dropout(p=0.4, inplace=False)
    (8): Linear(in_features=100, out_features=50, bias=True)
    (9): ReLU(inplace=True)
    (10): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (11): Dropout(p=0.4, inplace=False)
    (12): Linear(in_features=50, out_features=1, bias=True)
  )
)
Traceback (most recent call last):

  File  line 193, in <module>
    single_loss = loss_function(y_pred, train_op)

  File anaconda3libsite-packagestorchnnmodulesmodule.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)

  File anaconda3libsite-packagestorchnnmodulesloss.py", line 961, in forward
    return F.cross_entropy(input, target, weight=self.weight,

  File anaconda3libsite-packagestorchnnfunctional.py", line 2468, in cross_entropy
    return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)

  File anaconda3libsite-packagestorchnnfunctional.py", line 2264, in nll_loss
    ret = torch._C._nn.nll_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index)

RuntimeError: expected scalar type Long but found Double
 

Ответ №1:

nn.CrossEntropyLoss() ожидает целевые тензоры типа Long , но то, что вы передаете, имеет тип Double .

Попробуйте изменить эту строку

От: single_loss = loss_function(y_pred, train_op)

Для: single_loss = loss_function(y_pred, train_op.long())

Комментарии:

1. Спасибо @planet_pluto, это изменило ошибку, ха-ха. Ошибка индекса: цель 159 выходит за пределы. Я продолжу играть с этим и вернусь сюда с дополнительными вопросами, если не смогу разобраться. Снова. Спасибо.

2. Пожалуйста. Ваша новая ошибка означает, что существует несоответствие между количеством классов между входными метками и выводом из модели. Например: ваши входные метки могут иметь 5 классов [0, 1, 2, 3, 4] , но прогнозируемый результат модели может быть <5 классов [0, 1, 2, 3] , и в этом случае возникает ошибка.

3. Как бы мне выяснить, где находится несоответствие? Я предполагаю, что это где-то здесь all_layers = [] num_categorical_cols = sum((nf для ni, nf в embedding_size)) input_size = num_categorical_cols num_numerical_cols но я не знаю, с чего начать, чтобы изменить его.

4. Из вашей модели я мог видеть, что последний слой выводит одно значение. Можете ли вы попробовать распечатать train_op.shape и y_pred.shape непосредственно перед вычислением loss_function() и опубликовать его здесь?