我正在学习PyTorch,想在这个数据上进行基本的线性回归,这个数据是通过以下方式创建的:
from sklearn.datasets import make_regressionx, y = make_regression(n_samples=100, n_features=1, noise=15, random_state=42)y = y.reshape(-1, 1)print(x.shape, y.shape)plt.scatter(x, y)
我知道使用TensorFlow可以解决这个问题,代码如下:
model = tf.keras.models.Sequential()model.add(tf.keras.layers.Dense(units=1, activation='linear', input_shape=(x.shape[1], )))model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.05), loss='mse')hist = model.fit(x, y, epochs=15, verbose=0)
但我想知道PyTorch中的等效实现,我尝试这样做:
# Model Classclass Net(nn.Module): def __init__(self): super(Net, self).__init__() self.linear = nn.Linear(1,1) def forward(self, x): x = self.linear(x) return x def predict(self, x): return self.forward(x) model = Net()loss_fn = F.mse_lossopt = torch.optim.SGD(modelo.parameters(), lr=0.05)# Funcao para treinardef fit(num_epochs, model, loss_fn, opt, train_dl): # Repeat for given number of epochs for epoch in range(num_epochs): # Train with batches of data for xb, yb in train_dl: # 1. Generate predictions pred = model(xb) # 2. Calculate Loss loss = loss_fn(pred, yb) # 3. Campute gradients loss.backward() # 4. Update parameters using gradients opt.step() # 5. Reset the gradients to zero opt.zero_grad() # Print the progress if (epoch+1) % 10 == 0: print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))# Trainingfit(200, model, loss_fn, opt, data_loader)
但模型没有学习任何东西,我不知道还能做什么了。
输入/输出维度是(1/1)
回答:
数据集
首先,您应该定义 torch.utils.data.Dataset
它在__init__
中将numpy
数据转换为PyTorch的tensor
,并将数据转换为float
(numpy
默认是double
,而PyTorch默认是float
以节省内存)。
除此之外,它只会返回特征和相应回归目标的tuple
。
训练
几乎接近了,但您必须展平模型的输出(如下所述)。torch.nn.Linear
将返回形状为(batch, 1)
的张量,而您的目标形状为(batch,)
。flatten()
将移除不必要的1
维度。
# 2. Calculate Lossloss = criterion(pred.flatten(), yb)
模型
实际上,您只需要这样做:
model = torch.nn.Linear(1, 1)
任何层都可以直接调用,对于简单的模型不需要forward
和继承。
调用
其余部分几乎没问题,您只需创建 torch.utils.data.DataLoader
并传递我们数据集的实例。DataLoader
所做的就是多次调用dataset
的__getitem__
并创建指定大小的批次(还有一些其他有趣的事情,但这就是基本思想):
dataset = RegressionDataset()dataloader = torch.utils.data.DataLoader(dataset, batch_size=32)model = torch.nn.Linear(1, 1)criterion = torch.nn.MSELoss()optimizer = torch.optim.SGD(model.parameters(), lr=3e-4)fit(5000, model, criterion, optimizer, dataloader)
另外请注意,我使用了torch.nn.MSELoss()
,因为我们传递的是对象,在这种情况下看起来比函数更好。
完整代码
为了方便起见:
您应该能得到大约0.053
的损失,或者根据需要调整noise
或其他参数来增加或降低回归任务的难度。