pytorch linear regression fitting sin function

Table of contents

1. Library files

2. Define hyperparameters

3. Get the dataset

4. Load training set + test set

5. Build a linear network

6. Instantiate the network and optimizer

7. Train the network

8. Visualization

9. Result display

10. Complete code


1. Library files

os file is to eliminate matplotlib drawing errors

TensorDataset and DataLoader are data loading similar to image classification

torch.nn helps build neural networks

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. Define hyperparameters

The hyperparameters are defined here in one piece, which is convenient for debugging at any time

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. Get the dataset

The task to be done here is to fit the sin function with a linear neural network. The generation of the sin function is between -2pi~2pi, and the number of generated samples is determined by the previous hyperparameter (NUMBER_TRAIN_DATA).

random generates a floating-point number between 0.0-1.0, which is expanded by 4pi times, which is 0.0~4pi, and then subtracted by 2pi, which is between -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. Load training set + test set

Because this chapter is implemented with pytorch's tensor, the type of data loaded here must be guaranteed to be tensor type

# 加载训练集
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. Build a linear network

Here we use torch.nn to build a simple linear neural network

The code is as follows, a 3-layer network with two hidden layers is built, and the activation function uses sigmoid

Because here is the task of regression prediction, and the input is the independent variable x, the output should be a scalar corresponding to sin(x) as much as possible

So the input of the first layer of the network is 1, and the final output is also 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. Instantiate the network and optimizer

Here the Adam optimizer is used, and the loss function is the MSE mean square error

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

7. Train the network

The process of network training is relatively simple

# 训练
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. Visualization

The visualization process is also relatively simple

It should be noted that GPU training is used here, so the data cannot be transferred between numpy, because numpy cannot run on 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. Result display

Training process:

 

Displayed results:

It can be seen that the fitting results are still very good

10. Complete code

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()

Guess you like

Origin blog.csdn.net/qq_44886601/article/details/129784312