线性回归从零开始实现

有代码注释便于理解

思路:自己构造一个数据集,知道真实的W和b,以及feature和labels,也就是线性回归模型中的X和y,通过线性回归算法进行模型训练,可以计算出W和b的估计误差。添加了很多注释,便于自己的理解。

# 在pycharm中是用不了%matplotlib inline的。
import random
import torch
# 数据可视化中 matplotlib.pyplot模块下的plot函数用于绘制2D图形
# d2l包可以直接在conda的prompt里面输入命令 pip install -U d2l 来安装
from d2l import torch as d2l
import matplotlib.pyplot as plt

# num 生成n个样本
# 此函数用于生成特征和label  特征指的是X label指的是y
def synthetic_data(w, b, num_examples):  #@save
    """生成y=Xw+b+噪声"""
    # 均值为0 方差为1
    # normal:返回一个张量,包含了从指定均值means和标准差std的离散正态分布中抽取的一组随机数
    X = torch.normal(0, 1, (num_examples, len(w)))
    # 偏差b
    y = torch.matmul(X, w) + b
    # 增加复杂度噪音,均值为0,方差为0.01,形状和Y相同
    y += torch.normal(0, 0.01, y.shape)
    # 说明以列向量返回 x是feature y是label
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
# 创建训练样本
# label:所预测的东西实际是什么,如线性回归中的y变量
#feature:事物的固有属性,可以理解为做出某个判断的依据,是机器学习模型中的输入变量,如X变量
# 本行代码表示feature=X,labels=y
features, labels = synthetic_data(true_w, true_b, 1000)
# labels是如何生成的
print('features:', features[0],'\nlabel:', labels[0])

# features: tensor([1.4632, 0.5511])
# label: tensor([5.2498])

d2l.set_figsize()
# 样本的每一列跟labels绘制图像  X和y的图像
d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1);
plt.show()

# 读取数据集
def data_iter(batch_size, features, labels):
    num_examples = len(features)
    # indilces  标号
    indices = list(range(num_examples))
    # 这些样本是随机读取的,没有特定的顺序
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        # 每间隔batch_size随机读取一个样本
        batch_indices = torch.tensor(
            indices[i: min(i + batch_size, num_examples)])
        # 返回
        #yield就是返回一个值,并且记住这个返回的位置,下次迭代就从这个位置开始
        yield features[batch_indices], labels[batch_indices]

batch_size = 10
#  x,y 是 features labels
for X, y in data_iter(batch_size, features, labels):
    print(X, '\n', y)
    break

# 模型参数定义  随机初始化 需要计算梯度
# torch.normal是pytorch中用于生成服从正态分布的随机数的函数
w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

# X 是批量大小
# 回归算法
def linreg(X, w, b):  #@save
    """线性回归模型"""
    # def matmul(input: Tensor, other: Tensor, *, out: Optional[Tensor] = None) -> Tensor:
    # 两个张量矩阵相乘 X*w
    return torch.matmul(X, w) + b

# 损失的计算
def squared_loss(y_hat, y):  #@save
    """均方损失"""
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2

#"""小批量随机梯度下降"""
def sgd(params, lr, batch_size):  #@save

    with torch.no_grad():
        # 遍历
        for param in params:
            # l.sum().backward()这个计算出了每个参数的梯度
            param -= lr * param.grad / batch_size
            # 因为pytorch不会自动将梯度设置为0,设置为零后下次计算就不会与上次相关了
            param.grad.zero_()

# 学习率
lr = 0.03
# epochs 被定义为向前和向后传播中所有批次的单次训练迭代 简言之 训练过程中数据被轮多少次
num_epochs = 3
net = linreg
loss = squared_loss

# 训练过程
for epoch in range(num_epochs):
    # batchs 参数更新按批进行 小批的梯度下降算法
    for X, y in data_iter(batch_size, features, labels):
        # w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
        # b = torch.zeros(1, requires_grad=True)
        l = loss(net(X, w, b), y)  # X和y的小批量损失
        # 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,
        # 并以此计算关于[w,b]的梯度 求和之后算梯度,因为前面显示的声明w和b是要计算梯度的,这里backward函数就会对w和b求导。
        l.sum().backward()
        # 使用参数的梯度更新参数
        # def sgd(params, lr, batch_size):  #@save
        sgd([w, b], lr, batch_size)
    with torch.no_grad():
        # net函数 return torch.matmul(X, w) + b
        # loss函数 return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
        # def squared_loss(y_hat, y):
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')

线性回归是一种基本的机器学习模型,用于预测数值型目标变量。在PyTorch中,我们可以从头开始实现一个简单的线性回归模型。以下是步骤: 1. 导入必要的库: ```python import torch import torch.nn as nn ``` 2. 定义模型结构: ```python class LinearRegression(nn.Module): def __init__(self, input_dim): super(LinearRegression, self).__init__() self.linear = nn.Linear(input_dim, 1) # 线性层,输入维度和输出维度都是1,因为我们只有一个预测值 def forward(self, x): return self.linear(x) ``` 这里我们创建了一个包含一个线性层的模块,`nn.Linear`接受输入特征的数量(input_dim)作为参数。 3. 初始化模型: ```python model = LinearRegression(input_dim=your_input_size) ``` 替换`your_input_size`为实际的数据特征维度。 4. 创建损失函数和优化器: ```python criterion = nn.MSELoss() # Mean Squared Error (均方误差) 用于回归任务 optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # 使用随机梯度下降(SGD)算法,设置学习率 ``` 5. 训练模型: ```python for epoch in range(num_epochs): # 设置训练轮数 # 假设你已经有了训练数据 x_train 和 y_train predictions = model(x_train) # 前向传播得到预测值 loss = criterion(predictions, y_train.view(-1, 1)) # 计算损失 optimizer.zero_grad() # 清零梯度 loss.backward() # 反向传播计算梯度 optimizer.step() # 更新权重 6. 测试模型: ```python with torch.no_grad(): test_predictions = model(x_test) # 对测试集进行预测 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值