训练一个简单的线性回归模型,在代码实现上分成了几个部分,构建数据集,构建数据加载器,假设函数,损失函数,优化方法。对一个模型来说,损失值越小,模型就越好,也就是说训练模型的过程其实就是不断改变模型本身而减少损失值的过程,这里我们使用梯度下降法使得损失值减少
我们使用sklearn中的函数make_regression()生成回归数据 来构建一个数据集
from sklearn.datasets import make_regression
X, y, coef = make_regression(n_samples=200, n_features=1, n_informative=1, n_targets=1,
bias = 0, effective_rank=None, noise = 20,
tail_strength=0,random_state=0, coef = True)
属性 | 默认值 | 说明 |
---|---|---|
n_samples | int, optional (default=100) | 样本数量 |
n_features | int, optional (default=100) | 特征数量 |
n_informative | int, optional (default=10) | 对回归有效的特征数量 |
n_targets | int, optional (default=1) | y的维度 |
bias | float, optional (default=0.0) | 底层线性模型中的偏差项。相当于y的中位数 |
effective_rank | int or None, optional (default=None) | 有效等级 |
noise | float, optional (default=0.0) | 设置高斯噪声的标准偏差加到数据上。 |
shuffle | boolean, optional (default=True) | 是否洗牌 |
coef | boolean, optional (default=False) | 如果为真,则返回权重值 |
random_state | int, | 设置随机种子 |
使用matplotlib来绘图:
scatter函数绘制散点图
plot函数绘制折线图
import torch
from sklearn.datasets import make_regression
import matplotlib.pyplot as plt
import random
# 构建数据集
def create_data():
x, y, coef = make_regression(n_samples=100, n_features=1, noise=20, coef=True, bias=14.5, random_state=0)
x = torch.tensor(x)
y = torch.tensor(y)
return x, y, coef
# 构建数据加载器
def data_loader(x, y, size):
data_len = len(y)
data_index = list(range(data_len))
random.shuffle(data_index) # 打乱顺序
num = data_len // size
for idx in range(num):
start = idx * size
end = start + size
train_x = x[start:end]
train_y = y[start:end]
yield train_x, train_y # yield会保存循环中的值到集合里然后循环结束后一起返回
w = torch.tensor(0.1, requires_grad=True, dtype=torch.float64)
b = torch.tensor(0.0, requires_grad=True, dtype=torch.float64)
# 假设函数
def linear_regression(x):
return w * x + b
# 损失函数 模型越好损失越小
def loss_function(y_suppose, y_true):
return (y_suppose - y_true) ** 2
# 优化方法
def sgd(lr=0.01):
# 除以16是因为使用的是批次样本的平均梯度值(size是16)
w.data = w.data - lr * w.grad.data / 16
b.data = b.data - lr * b.grad.data / 16
# 训练函数
def train():
x, y, coef = create_data() # 加载数据集
epochs = 100 # 定义训练参数次数
learning_rate = 0.01 # 学习率
for _ in range(epochs):
for x_train, y_train in data_loader(x, y, size=16):
y_suppose = linear_regression(x_train) # 将样本送入模型进行训练
loss = loss_function(y_suppose, y_train.reshape(-1, 1)).sum() # 计算平方损失值
if w.grad is not None: # 梯度清0
w.grad.data.zero_()
if b.grad is not None: # 梯度清0
b.grad.data.zero_()
loss.backward() # 将loss进行自动微分是因为训练模型其实就是使得损失函数降低的过程
sgd(learning_rate)
# 绘图
plt.scatter(x, y)
x = torch.linspace(x.min(), x.max(), 1000)
y1 = torch.tensor([w * v + 14.5 for v in x])
y2 = torch.tensor([w * v + b for v in x])
plt.plot(x, y1, label='真实')
plt.plot(x, y2, label='训练')
plt.grid()
plt.show()
if __name__ == '__main__':
train()