欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[Pytorch --- 11] 简单线性回归的实现

程序员文章站 2022-05-26 20:46:05
...

一. 定义

1. 单变量线性回归

定义一个简单的线性回归函数,y = 2x+0,我们希望模型能够预测出正确的输出。

模型仅采用一个Linear层,损失函数采用均方差MSE。

import torch
import numpy as np
import torch.nn as nn
from torch.nn.functional import mse_loss
from torch.nn.functional import sigmoid

criterion = nn.MSELoss(reduction="mean")
# criterion = nn.MSELoss(reduction="sum")
# criterion = nn.BCELoss(reduction='mean')
# criterion = nn.BCELoss(reduction='sum')


class NN(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(1, 1)

    def forward(self, x, y):
        x = self.linear(x)
        print("self.linear.weight = ", self.linear.weight.item())
        print("self.linear.bias = ",   self.linear.bias.item())
        loss = criterion(x, y)
        return loss


def train(x_data, y_data):
    epochs = 1000
    learning_rate = 0.01
    model = NN()
    model.train()
    optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

    for epoch in range(epochs):
        global_loss = 0
        global_step = 0
        for x, y in zip(x_data, y_data):
            x = torch.FloatTensor(x)
            y = torch.FloatTensor(y)
            loss = model(x, y)

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            global_loss += loss.item()
            global_step += 1
        if epoch % 10 == 0:
            avg_loss = global_loss / global_step
            print("Epoch %d: loss: %.3f" % (epoch, avg_loss))

x_data = np.array([[1.0], [2.0], [3.0], [4.0], [5.0]], dtype=np.float32)
y_data = np.array([[2.0], [4.0], [6.0], [8.0], [10.0]], dtype=np.float32)
train(x_data, y_data)

我们输出模型的最终的参数,可发现与我们最终的参数 y = 2x+0非常接近:

self.linear.weight =  2.000000476837158
self.linear.bias =  -1.4234631180443102e-06

同时,训练过程中模型最终的loss也会无限接近于0。

如果稍微改变以下原始的输入,我们发现模型参数仍然非常接近于我们的结果。

x_data = np.array([[1.0], [2.0], [3.0], [4.0], [5.0]],  dtype=np.float32)
y_data = np.array([[2.0], [4.0], [5.8], [8.1], [10.0]], dtype=np.float32)

最终的参数输出为:

self.linear.weight =  2.0142741203308105
self.linear.bias =  -0.05234277620911598

 

2. 多变量线性回归

多元线性回归,我们采用波士顿房价预测数据集,测试了线性和非线性两种模型,最终结果差距不大。

import torch
import json
import random
import numpy as np
import torch.nn as nn
import sklearn.datasets as datasets

criterion = nn.MSELoss()
# criterion = nn.MSELoss(reduction="mean")
# criterion = nn.MSELoss(reduction="sum")
# criterion = nn.BCELoss(reduction='mean')
# criterion = nn.BCELoss(reduction='sum')


# class NN(nn.Module):
#     def __init__(self):
#         super().__init__()
#         self.linear1 = nn.Linear(13, 14)
#         self.relu = nn.ReLU()
#         self.linear2 = nn.Linear(14, 1)
#         self.sigmoid = nn.Sigmoid()
#
#     def forward(self, x, y=None):
#         x = self.linear1(x)
#         x = self.relu(x)
#         x = self.linear2(x)
#         x = self.sigmoid(x)
#         if y is not None:
#             loss = criterion(x, y)
#             return loss
#         else:
#             return x

class NN(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(13, 1)

    def forward(self, x, y=None):
        x = self.linear(x)
        if y is not None:
            loss = criterion(x, y)
            return loss
        else:
            return x

# 设置随机种子
seed = 5233
torch.manual_seed(seed)
# torch.cuda.manual_seed_all(seed)
np.random.seed(seed)
random.seed(seed)

epochs = 500
learning_rate = 0.01
model = NN()
model.train()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# optimizer = torch.optim.RMSprop(model.parameters(), lr=learning_rate)

def train(x_data, y_data):
    for epoch in range(epochs):
        global_loss = 0
        global_step = 0
        for x, y in zip(x_data, y_data):
            x = torch.FloatTensor(x)
            y = torch.FloatTensor([y])
            loss = model(x, y)

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            global_loss += loss.item()
            global_step += 1
        if epoch % 10 == 0:
            avg_loss = global_loss / global_step
            print("Epoch %d: loss: %.3f" % (epoch, avg_loss))


def test(x_data, y_data):
    model.eval()
    res = []
    for x, y in zip(x_data, y_data):
        x = torch.FloatTensor(x)
        with torch.no_grad():
            output = model(x)
        res.append({"ground_truth": y[0], "prediction": output.item()})
    with open("result.json", "w", encoding="utf-8") as writer:
        json.dump(res, writer, ensure_ascii=False, indent=4)

# 载入数据集
Boston = datasets.load_boston()

# 数据预处理: 特征缩放,均值归一化
from sklearn.preprocessing import MinMaxScaler
ss_input = MinMaxScaler()
ss_output = MinMaxScaler()
data_set_input  = ss_input.fit_transform(Boston['data'])
data_set_output = ss_output.fit_transform(Boston['target'][:, np.newaxis])
# train(x_data, y_data)

# 划分数据集
train_set_input  = data_set_input[ 0:350, :]
train_set_output = data_set_output[0:350, :]
test_set_input   = data_set_input[ 351:506, :]
test_set_output  = data_set_output[351:506, :]
train(train_set_input, train_set_output)
test(test_set_input, test_set_output)



其余情况下,我们也可以导入糖尿病数据集,完成简单的分类任务

import torch
import json
import random
import numpy as np
import torch.nn as nn
import sklearn.datasets as datasets

criterion = nn.MSELoss()
# criterion = nn.MSELoss(reduction="mean")
# criterion = nn.MSELoss(reduction="sum")
# criterion = nn.BCELoss(reduction='mean')
# criterion = nn.BCELoss(reduction='sum')


class NN(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear1 = nn.Linear(10, 12)
        self.relu = nn.ReLU()
        self.linear2 = nn.Linear(12, 1)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x, y=None):
        x = self.linear1(x)
        x = self.relu(x)
        x = self.linear2(x)
        x = self.sigmoid(x)
        if y is not None:
            loss = criterion(x, y)
            return loss
        else:
            return x

# class NN(nn.Module):
#     def __init__(self):
#         super().__init__()
#         self.linear = nn.Linear(10, 1)
#
#     def forward(self, x, y=None):
#         x = self.linear(x)
#         if y is not None:
#             loss = criterion(x, y)
#             return loss
#         else:
#             return x

# 设置随机种子
seed = 5233
torch.manual_seed(seed)
# torch.cuda.manual_seed_all(seed)
np.random.seed(seed)
random.seed(seed)

epochs = 500
learning_rate = 0.01
model = NN()
model.train()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# optimizer = torch.optim.RMSprop(model.parameters(), lr=learning_rate)

def train(x_data, y_data):
    for epoch in range(epochs):
        global_loss = 0
        global_step = 0
        for x, y in zip(x_data, y_data):
            x = torch.FloatTensor(x)
            y = torch.FloatTensor(y)
            loss = model(x, y)

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            global_loss += loss.item()
            global_step += 1
        if epoch % 10 == 0:
            avg_loss = global_loss / global_step
            print("Epoch %d: loss: %.3f" % (epoch, avg_loss))


def test(x_data, y_data):
    model.eval()
    res = []
    for x, y in zip(x_data, y_data):
        x = torch.FloatTensor(x)
        with torch.no_grad():
            output = model(x)
        res.append({"ground_truth": y[0], "prediction": output.item()})
    with open("result.json", "w", encoding="utf-8") as writer:
        json.dump(res, writer, ensure_ascii=False, indent=4)

# 载入数据集
diabetes = datasets.load_diabetes()

# 数据预处理: 特征缩放,均值归一化
from sklearn.preprocessing import MinMaxScaler
ss_input = MinMaxScaler()
ss_output = MinMaxScaler()
data_set_input  = ss_input.fit_transform(diabetes['data'])
data_set_output = ss_output.fit_transform(diabetes['target'][:, np.newaxis])
# train(x_data, y_data)

# 划分数据集
train_set_input  = data_set_input[ :380, :]
train_set_output = data_set_output[:380, :]
test_set_input   = data_set_input[ 380:, :]
test_set_output  = data_set_output[380:, :]
train(train_set_input, train_set_output)
test(test_set_input, test_set_output)



 

相关标签: Pytorch