#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()
и опубликовать его здесь?