[torch] 非线性拟合问题的训练
利用 torch 建立神经网络,模拟有限个数据的非线性拟合
本文仍然考虑 f(x)=sin(x)xf(x)=\frac{\sin(x)}{x}f(x)=xsin(x) 函数在区间 [-10,10] 上固定数据的拟合。
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt# 设置随机种子以确保结果的可重复性
torch.manual_seed(1)# 生成数据集
x_data = (np.random.rand(500) * 20 - 10).astype('float32') # 生成500个随机x值,范围在-10到10之间
y_data = np.sin(x_data) / x_data # 生成y值
y_data = y_data.reshape(-1, 1) # 将y_data转换为二维数组# 定义模型,一个具有2个隐藏层的多层感知器
class MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()self.hidden1 = nn.Linear(in_features=1, out_features=50)self.bn = nn.BatchNorm1d(num_features=50)self.hidden2 = nn.Linear(in_features=50, out_features=1)def forward(self, x):x = torch.tanh(self.hidden1(x))x = self.bn(x)x = self.hidden2(x)return xmodel = MyModel()# 定义损失函数
loss_fn = nn.MSELoss()# 设置优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)# 准备训练数据 (PyTorch通常使用DataLoader, 但简单回归也可以直接使用Tensor)
x_tensor = torch.from_numpy(x_data).unsqueeze(-1) # 转换为Tensor并增加特征维度
y_tensor = torch.from_numpy(y_data)# 训练模型
epochs = 1000
for epoch in range(1, epochs + 1):# 前向传播y_pred = model(x_tensor)loss = loss_fn(y_pred, y_tensor)# 反向传播和优化optimizer.zero_grad() # 清空梯度loss.backward() # 反向传播optimizer.step() # 更新参数if epoch % 100 == 0:print(f'Epoch {epoch}: Loss = {loss.item()}')# 使用训练好的模型进行预测
with torch.no_grad(): # 关闭梯度计算y_pred_np = model(x_tensor).numpy()# 可视化结果
plt.scatter(x_data, y_data, label='True', alpha=0.5)
x,index=torch.sort(torch.as_tensor(x_data))
plt.plot(x, y_pred_np[index],'r', label='Predicted')
plt.legend()
plt.title('Fitting of sinc function')
plt.xlabel('x')
plt.ylabel('y')
plt.show()