pytorch 线性回归拟合sin函数

目录

1. 库文件

2. 定义超参数

3. 获取数据集

4. 加载训练集+测试集

5. 搭建线性网络

6. 实例化网络和优化器

7. 训练网络

8. 可视化

9. 结果展示

10. 完整代码


1. 库文件

os 文件是为了消除matplotlib 绘图的错误

TensorDataset、DataLoader 是类似图像分类的数据加载

torch.nn 帮助搭建神经网络

import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'

from torch.utils.data import TensorDataset,DataLoader
import torch.nn as nn
import numpy as np
import torch
import matplotlib.pyplot as plt

2. 定义超参数

超参数这里定义在一块,这样方便随时进行调试

np.random.seed(0)   # 生成的随机数据不变

# 定义超参数
NUMBER_TRAIN_DATA = 50                              # 训练样本的个数
NUMBER_TEST_DATA = NUMBER_TRAIN_DATA // 5           # 测试样本的个数 0.2倍的训练集
BATCH_SIZE = 10
LEARNING_RATE = 0.01
EPOCHS = 2000
DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'

3. 获取数据集

这里要完成的任务是用线性神经网络拟合sin函数,sin函数的生成在-2pi~2pi之间,生成样本的个数由之前的超参数(NUMBER_TRAIN_DATA)决定

random 生成 0.0-1.0之间的浮点数,这里扩大4pi倍,就是0.0~4pi,再减去2pi,就是-2pi~2pi之间

# 获取数据集
def get_dataset(num):
    data_x = np.random.random((num,1)) * np.pi * 4 - np.pi * 2  # 返回 -2pi~2pi 随机值
    data_y=np.sin(data_x).reshape(-1,1)
    return data_x,data_y

4. 加载训练集+测试集

因为本章是用pytorch的tensor实现的,因此这里数据的加载的类型要保证是tensor类型

# 加载训练集
train_x, train_y = get_dataset(NUMBER_TRAIN_DATA)
trainSet=TensorDataset(torch.tensor(train_x, dtype=torch.float32), torch.tensor(train_y, dtype=torch.float32))
trainLoader=DataLoader(trainSet,batch_size=BATCH_SIZE,shuffle=True)

# 加载测试集
test_x,test_y = get_dataset(NUMBER_TEST_DATA)
testSet=TensorDataset(torch.tensor(test_x,dtype=torch.float32),torch.tensor(test_y,dtype=torch.float32))
testLoader=DataLoader(trainSet,batch_size=BATCH_SIZE,shuffle=True)

5. 搭建线性网络

这里用torch.nn 搭建一个简单的线性神经网络

代码如下,搭建的是一个3层的包含两个隐藏层的网络,激活函数用sigmoid

因为这里是回归预测的任务,而输入的就是自变量x,输出应该是一个尽可能对应sin(x)的标量

所以网络第一层的输入是1,最后输出也为1

# 定义网络
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc=nn.Sequential(
            nn.Linear(1,10),
            nn.Sigmoid(),
            nn.Linear(10,10),
            nn.Sigmoid(),
            nn.Linear(10,1)
        )

    def forward(self, x):
        x = self.fc(x)
        return x

6. 实例化网络和优化器

这里用Adam优化器,损失函数为MSE均方误差

# 定义网络
model=Net()
model.to(DEVICE)
optim=torch.optim.Adam(model.parameters(),lr=LEARNING_RATE)
loss_fn =nn.MSELoss(reduction='sum')

7. 训练网络

网络训练的过程较为简单

# 训练
epoch_train = []  # 存放训练误差
epoch_test = []   # 存放测试误差
for epoch in range(EPOCHS):
    train_running_loss = 0.0
    for x, y in trainLoader:        # 加载训练集
        x_trainData, y_trainData = x.to(DEVICE), y.to(DEVICE)

        y_predict = model(x_trainData)             # forward
        loss = loss_fn(y_predict, y_trainData)     # loss
        optim.zero_grad()                          # gradient to zero
        loss.backward()                            # backward
        optim.step()                               # gradient descent
        train_running_loss += loss.item()

    with torch.no_grad():
        test_running_loss = 0.0
        for x,y in testLoader:
            x_testData,y_testData = x.to(DEVICE),y.to(DEVICE)
            y_predict = model(x_testData)
            loss = loss_fn(y_predict,y_testData)
            test_running_loss += loss.item()

    train_running_loss = train_running_loss / NUMBER_TRAIN_DATA
    test_running_loss = test_running_loss / NUMBER_TEST_DATA

    epoch_train.append(train_running_loss)
    epoch_test.append(test_running_loss)

    if (epoch+1) % 100 == 0:
        print("epoch:%d,train loss:%.5f,test_loss:%.5f" % (epoch+1,train_running_loss,test_running_loss))

8. 可视化

可视化的过程也较为简单

需要注意的是,这里用了GPU训练,所以数据是不能之间numpy的,因为numpy不能在GPU上面运行

# 可视化结果
with torch.no_grad():
    axis_x = np.linspace(-2*np.pi,2*np.pi,200).reshape(-1,1)
    axis_x = torch.from_numpy(axis_x).type(torch.float32)
    axis_x = axis_x.to(DEVICE)

    y_predict = model(axis_x)

    plt.figure(figsize=(12,8))

    plt.subplot(1,2,1),plt.title('loss curve')
    plt.plot(epoch_train,label = 'train loss',color='r')    # 训练损失
    plt.plot(epoch_test,label = 'test loss',color = 'b')    # 测试损失
    plt.legend()

    plt.subplot(1,2,2),plt.title('performance')
    plt.scatter(train_x,train_y,label='trainSet',color='r')     # 训练样本
    plt.scatter(test_x,test_y,label='testSet',color='g')        # 测试样本
    plt.plot(axis_x.cpu().numpy(),y_predict.detach().cpu().numpy(),label='predict',color = 'b')
    plt.legend()

    plt.show()

9. 结果展示

训练过程:

 

展示的结果:

观察可知,拟合的结果还是很好的

10. 完整代码

import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'

from torch.utils.data import TensorDataset,DataLoader
import torch.nn as nn
import numpy as np
import torch
import matplotlib.pyplot as plt


np.random.seed(0)   # 生成的随机数据不变

# 定义超参数
NUMBER_TRAIN_DATA = 50                              # 训练样本的个数
NUMBER_TEST_DATA = NUMBER_TRAIN_DATA // 5           # 测试样本的个数 0.2倍的训练集
BATCH_SIZE = 10
LEARNING_RATE = 0.01
EPOCHS = 2000
DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'


# 获取数据集
def get_dataset(num):
    data_x = np.random.random((num,1)) * np.pi * 4 - np.pi * 2  # 返回 -2pi~2pi 随机值
    data_y=np.sin(data_x).reshape(-1,1)
    return data_x,data_y


# 加载训练集
train_x, train_y = get_dataset(NUMBER_TRAIN_DATA)
trainSet=TensorDataset(torch.tensor(train_x, dtype=torch.float32), torch.tensor(train_y, dtype=torch.float32))
trainLoader=DataLoader(trainSet,batch_size=BATCH_SIZE,shuffle=True)

# 加载测试集
test_x,test_y = get_dataset(NUMBER_TEST_DATA)
testSet=TensorDataset(torch.tensor(test_x,dtype=torch.float32),torch.tensor(test_y,dtype=torch.float32))
testLoader=DataLoader(trainSet,batch_size=BATCH_SIZE,shuffle=True)


# 定义网络
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc=nn.Sequential(
            nn.Linear(1,10),
            nn.Sigmoid(),
            nn.Linear(10,10),
            nn.Sigmoid(),
            nn.Linear(10,1)
        )

    def forward(self, x):
        x = self.fc(x)
        return x


# 定义网络
model=Net()
model.to(DEVICE)
optim=torch.optim.Adam(model.parameters(),lr=LEARNING_RATE)
loss_fn =nn.MSELoss(reduction='sum')

# 训练
epoch_train = []  # 存放训练误差
epoch_test = []   # 存放测试误差
for epoch in range(EPOCHS):
    train_running_loss = 0.0
    for x, y in trainLoader:        # 加载训练集
        x_trainData, y_trainData = x.to(DEVICE), y.to(DEVICE)

        y_predict = model(x_trainData)             # forward
        loss = loss_fn(y_predict, y_trainData)     # loss
        optim.zero_grad()                          # gradient to zero
        loss.backward()                            # backward
        optim.step()                               # gradient descent
        train_running_loss += loss.item()

    with torch.no_grad():
        test_running_loss = 0.0
        for x,y in testLoader:
            x_testData,y_testData = x.to(DEVICE),y.to(DEVICE)
            y_predict = model(x_testData)
            loss = loss_fn(y_predict,y_testData)
            test_running_loss += loss.item()

    train_running_loss = train_running_loss / NUMBER_TRAIN_DATA
    test_running_loss = test_running_loss / NUMBER_TEST_DATA

    epoch_train.append(train_running_loss)
    epoch_test.append(test_running_loss)

    if (epoch+1) % 100 == 0:
        print("epoch:%d,train loss:%.5f,test_loss:%.5f" % (epoch+1,train_running_loss,test_running_loss))

# 可视化结果
with torch.no_grad():
    axis_x = np.linspace(-2*np.pi,2*np.pi,200).reshape(-1,1)
    axis_x = torch.from_numpy(axis_x).type(torch.float32)
    axis_x = axis_x.to(DEVICE)

    y_predict = model(axis_x)

    plt.figure(figsize=(12,8))

    plt.subplot(1,2,1),plt.title('loss curve')
    plt.plot(epoch_train,label = 'train loss',color='r')    # 训练损失
    plt.plot(epoch_test,label = 'test loss',color = 'b')    # 测试损失
    plt.legend()

    plt.subplot(1,2,2),plt.title('performance')
    plt.scatter(train_x,train_y,label='trainSet',color='r')     # 训练样本
    plt.scatter(test_x,test_y,label='testSet',color='g')        # 测试样本
    plt.plot(axis_x.cpu().numpy(),y_predict.detach().cpu().numpy(),label='predict',color = 'b')
    plt.legend()

    plt.show()

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
下面是一个简单的 PyTorch 线性回归模型来拟合 sin(x) 函数的示例: ``` import torch import math import matplotlib.pyplot as plt # 生成训练数据 x = torch.linspace(-math.pi, math.pi, 2000) y = torch.sin(x) # 定义模型 class LinearRegression(torch.nn.Module): def __init__(self, input_dim, output_dim): super(LinearRegression, self).__init__() self.linear = torch.nn.Linear(input_dim, output_dim) def forward(self, x): out = self.linear(x) return out input_dim = 1 output_dim = 1 model = LinearRegression(input_dim, output_dim) # 定义损失函数和优化器 criterion = torch.nn.MSELoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # 训练模型 num_epochs = 2000 for epoch in range(num_epochs): inputs = x.reshape(-1, 1) labels = y.reshape(-1, 1) # 前向传播 outputs = model(inputs) loss = criterion(outputs, labels) # 反向传播和优化 optimizer.zero_grad() loss.backward() optimizer.step() if (epoch+1) % 100 == 0: print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item())) # 可视化结果 predicted = model(inputs).detach().numpy() plt.plot(x.numpy(), y.numpy(), 'ro', label='Original data') plt.plot(x.numpy(), predicted, label='Fitted line') plt.legend() plt.show() ``` 在上面的代码中,我们首先生成了一个包含 2000 个样本的训练数据集,这些样本在 -π 到 π 的范围内均匀分布。接着,我们定义了一个简单的线性回归模型,该模型包含一个线性层。然后,我们使用均方误差损失函数和随机梯度下降优化器来训练模型。最后,我们将训练数据集和模型的预测结果可视化,以便于观察模型的性能。 在运行上面的代码之后,我们应该可以看到类似于下面的输出: ``` Epoch [100/2000], Loss: 0.4835 Epoch [200/2000], Loss: 0.3817 Epoch [300/2000], Loss: 0.3055 Epoch [400/2000], Loss: 0.2471 Epoch [500/2000], Loss: 0.2012 Epoch [600/2000], Loss: 0.1644 Epoch [700/2000], Loss: 0.1341 Epoch [800/2000], Loss: 0.1084 Epoch [900/2000], Loss: 0.0864 Epoch [1000/2000], Loss: 0.0674 Epoch [1100/2000], Loss: 0.0511 Epoch [1200/2000], Loss: 0.0370 Epoch [1300/2000], Loss: 0.0250 Epoch [1400/2000], Loss: 0.0149 Epoch [1500/2000], Loss: 0.0067 Epoch [1600/2000], Loss: 0.0009 Epoch [1700/2000], Loss: 0.0037 Epoch [1800/2000], Loss: 0.0089 Epoch [1900/2000], Loss: 0.0156 Epoch [2000/2000], Loss: 0.0236 ``` 该输出显示了模型的平均训练损失在每个周期中的降低。最终,我们应该可以看到一个可视化图,其中红色圆圈表示原始数据,蓝色曲线表示模型的预测结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喵星人监护人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值