python - 如何修复损失函数/softmax中的维度误差?
问题描述
我正在 PyTorch 中为 XOR 实现逻辑回归(我不希望它运行良好,这只是一个演示)。出于某种原因,我收到错误“IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1)”。我不清楚这起源于哪里。错误指向训练期间的 log_softmax。
import torch.nn as nn
import torch.nn.functional as F
class LogisticRegression(nn.Module):
# input_size: Dimensionality of input feature vector.
# num_classes: The number of classes in the classification problem.
def __init__(self, input_size, num_classes):
# Always call the superclass (nn.Module) constructor first!
super(LogisticRegression, self).__init__()
# Set up the linear transform
self.linear = nn.Linear(input_size, num_classes)
# Forward's sole argument is the input.
# input is of shape (batch_size, input_size)
def forward(self, x):
# Apply the linear transform.
# out is of shape (batch_size, num_classes)
out = self.linear(x)
# Softmax the out tensor to get a log-probability distribution
# over classes for each example.
out_distribution = F.softmax(out, dim=-1)
return out_distribution
# Binary classifiation
num_outputs = 1
num_input_features = 2
# Create the logistic regression model
logreg_clf = LogisticRegression(num_input_features, num_outputs)
print(logreg_clf)
lr_rate = 0.001
X = torch.Tensor([[0,0],[0,1], [1,0], [1,1]])
Y = torch.Tensor([0,1,1,0]).view(-1,1) #view is similar to numpy.reshape()
# Run the forward pass of the logistic regression model
sample_output = logreg_clf(X) #completely random at the moment
print(X)
loss_function = nn.CrossEntropyLoss() # computes softmax and then the cross entropy
optimizer = torch.optim.SGD(logreg_clf.parameters(), lr=lr_rate)
from torch.autograd import Variable
#training loop:
epochs = 201 #how many times we go through the training set
steps = X.size(0) #steps = 4; we have 4 training examples
for i in range(epochs):
for j in range(steps):
#sample from the training set:
data_point = np.random.randint(X.size(0))
x_var = Variable(X[data_point], requires_grad=False)
y_var = Variable(Y[data_point], requires_grad=False)
optimizer.zero_grad() # zero the gradient buffers
y_hat = logreg_clf(x_var) #get the output from the model
loss = loss_function.forward(y_hat, y_var) #calculate the loss
loss.backward() #backprop
optimizer.step() #does the update
if i % 500 == 0:
print ("Epoch: {0}, Loss: {1}, ".format(i, loss.data.numpy()))
解决方案
首先,您正在执行二进制分类任务。所以输出特征的数量应该是2;即,num_outputs = 1
。
其次,正如在nn.CrossEntropyLoss()
文档中声明的那样,该.forward
方法接受两个张量,如下所示:
Input: (N, C)
哪里C
是班级的数量(在你的情况下是2)。Target: (N)
N
在上面的示例中是您传递给损失函数的训练示例的数量;为简单起见,您可以将其设置为 1(即,对每个实例进行前向传递,然后更新梯度)。
注意:此外,您不需要使用.Softmax()
beforenn.CrossEntropyLoss()
模块,因为此类已nn.LogSoftmax
包含在其自身中。
我修改了您的代码,如下所示,这是您的代码段的一个工作示例:
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import torch
class LogisticRegression(nn.Module):
# input_size: Dimensionality of input feature vector.
# num_classes: The number of classes in the classification problem.
def __init__(self, input_size, num_classes):
# Always call the superclass (nn.Module) constructor first!
super(LogisticRegression, self).__init__()
# Set up the linear transform
self.linear = nn.Linear(input_size, num_classes)
# Forward's sole argument is the input.
# input is of shape (batch_size, input_size)
def forward(self, x):
# Apply the linear transform.
# out is of shape (batch_size, num_classes)
out = self.linear(x)
# Softmax the out tensor to get a log-probability distribution
# over classes for each example.
return out
# Binary classifiation
num_outputs = 2
num_input_features = 2
# Create the logistic regression model
logreg_clf = LogisticRegression(num_input_features, num_outputs)
print(logreg_clf)
lr_rate = 0.001
X = torch.Tensor([[0,0],[0,1], [1,0], [1,1]])
Y = torch.Tensor([0,1,1,0]).view(-1,1) #view is similar to numpy.reshape()
# Run the forward pass of the logistic regression model
sample_output = logreg_clf(X) #completely random at the moment
print(X)
loss_function = nn.CrossEntropyLoss() # computes softmax and then the cross entropy
optimizer = torch.optim.SGD(logreg_clf.parameters(), lr=lr_rate)
from torch.autograd import Variable
#training loop:
epochs = 201 #how many times we go through the training set
steps = X.size(0) #steps = 4; we have 4 training examples
for i in range(epochs):
for j in range(steps):
#sample from the training set:
data_point = np.random.randint(X.size(0))
x_var = Variable(X[data_point], requires_grad=False).unsqueeze(0)
y_var = Variable(Y[data_point], requires_grad=False).long()
optimizer.zero_grad() # zero the gradient buffers
y_hat = logreg_clf(x_var) #get the output from the model
loss = loss_function(y_hat, y_var) #calculate the loss
loss.backward() #backprop
optimizer.step() #does the update
if i % 500 == 0:
print ("Epoch: {0}, Loss: {1}, ".format(i, loss.data.numpy()))
更新
要获得 0 或 1 的预测类标签:
pred = np.argmax(y_hat.detach().numpy, axis=0)
至于.detach()
函数,numpy 期望张量/数组与计算图分离;即,张量不应该有require_grad=True
,而分离方法会为你解决问题。
推荐阅读
- angular - 在一个 Azure Blob 存储上托管多个 Angular 应用
- wordpress - 带有 Docker-Compose 和 AWS RDS MySQL 数据库的 AWS EC2 上的 WordPress
- airflow - 气流将 jinja 模板传递给 dag 参数
- r - ggplot:使用最小值和最大值的分类值添加 geom_rect
- windows - 无法运行 Windows docker 容器中路径中的可执行文件
- c# - 通信对象 System.ServiceModel.ChannelFactory` 不能用于通信,因为它处于故障状态
- amazon-web-services - 如何使用 serverless-offline 检测无服务器框架功能是否离线运行?
- swift - TabView 在第一次查看 SwiftUI 时不显示文本
- c# - 为什么在 for 循环的每次迭代中实例化一个新对象会覆盖以前的列表条目?
- python - 如何在熊猫的一个图形上绘制两个不同的图形?