Class1线性回归代码

Class1线性回归从零开始实现代码

%matplotlib inline
# 可以直接显示matplotlib绘制的图表

# 导入内置随机数生成模块,用于生成随机数、随机选择元素等
import random
# 导入Pytorch库
import torch
# 导入d2l包
from d2l import torch as d2l
# 合成线性回归数据集
# w:权重张量
# b:偏置
# num_examples:样本数量
def synthetic_data(w,b,num_examples):
    """生成 y = Xw + b + 噪声"""
    # 生成均值为0,方差为1,n个个数,w长度的张量
    X = torch.normal(0,1,(num_examples,len(w)))
    # 计算XW + b
    y = torch.matmul(X,w) + b
    # 添加均值为0,标准差为0.01,与y形状相同的噪声
    y += torch.normal(0,0.01,y.shape)
    # 将形状变为二维(1000,1),符合后续模型训练格式
    return X,y.reshape((-1,1))

# 设置真实权重true_w
true_w = torch.tensor([2,-3.4])
# 设置真实偏置
true_b = 4.2
# features:特征矩阵
# labels:噪声
features,labels = synthetic_data(true_w,true_b,1000)
# features:形状为(1000,2),1000个样本,每个样本有2个特征
# features[0]:第0个样本的特征向量

# labels:形状为(1000,1),1000个样本对应的目标值
# labels[0]:第0个样本标签,形状为(1,)的张量

print('features:',features[0],'\nlabel:',labels[0])
# 调用d2l包,设置matplotlib图像的默认尺寸
d2l.set_figsize()
# features[:,1]:取出所有样本的第2个特征列
# .detach():从计算图分离张量
# .numpy():将PyTorch转换成Numpy(matplotlib需要的格式)
# scatters(x,y,s):x横坐标,y纵坐标,s每个点的大小
d2l.plt.scatter(features[:,1].detach().numpy(),
               labels.detach().numpy(),1)
# 生成器函数,每次调用时返回一个小批量数据
# batch_size:批量大小爱哦
# features:特征矩阵
# labels:标签值
def data_iter(batch_size,features,labels):
    # 获取样本总数
    num_examples = len(features)
    # 构造一个包含所有样本索引的列表
    indices = list(range(num_examples))
    # 打乱索引顺序,确保每次训练时顺序不同
    random.shuffle(indices)
    # 根据样本总数、批量大小循环i次
    for i in range(0,num_examples,batch_size):
        batch_indices = torch.tensor(
            # 截取当前batch对应的索引列表
            # min:防止最后1个batch不满时越界
            indices[i:min(i + batch_size,num_examples)])
        # 每次调用都会返回一个新批次
        yield features[batch_indices],labels[batch_indices]

# 批量大小设置为10
batch_size = 10

# for X,y in:从迭代中取出1个batch
for X,y in data_iter(batch_size,features,labels):
    # print(X,y):打印1个小批量的特征标签
    print(X,'\n',y)
    # 退出循环
    break
# 初始化线性回归模型中的权重和偏置
# w初始值为0,方差为0.01的(2,1)向量,可以进行梯度计算
w = torch.normal(0,0.01,size=(2,1),requires_grad=True)
# b初始值为0,形状为1,可以进行梯度计算
b = torch.zeros(1,requires_grad=True)
# X:特征张量
# w:权重参数
# b:偏置
def linreg(X,w,b):
    """线性回归模型"""
    # 线性回归计算
    return torch.matmul(X,w) + b
# 定义损失函数
# y_hat:模型预测值,形状为(batch_size,1)
# y:真实标签,形状为(batch_size)
def squared_loss(y_hat,y):
    """均方损失"""
    # y.reshape(y_hat.shape):y的形状与y_hat匹配
    # 损失函数计算:(y0-y)²/2
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
# 小批量随机梯度下降的核心函数
# params:包含模型中所有需要更新的参数列表[w,b]
# lr:学习率
# batch_size:批量大小
def sgd(params,lr,batch_size):
    """小批量随机梯度下降"""
    # 关闭梯度追踪(防止参数更新被记录在计算图中)
    with torch.no_grad():
        # 遍历每一个参数(w,b)
        for param in params:
            # 梯度下降公式
            param -= lr * param.grad / batch_size
            # 梯度清零
            param.grad.zero_()
# 设置学习率、训练轮数、前向计算函数和损失函数
lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss

# 外层控制训练轮数
for epoch in range(num_epochs):
    # 进行小批量训练
    # X:输入特征
    # y:标签值
    for X,y in data_iter(batch_size,features,labels):
        # 前向传播并计算损失
        l = loss(net(X,w,b),y)
        # 反向传播,自动计算梯度
        l.sum().backward()
        # 梯度下降更新参数
        sgd([w,b],lr,batch_size)
    # 禁用梯度计算(提高效率)
    with torch.no_grad():
        # 每轮训练结束后评估损失
        train_l = loss(net(features,w,b),labels)
        # train_l.mean():取平均损失作为本轮指标
        print(f'epoch{epoch + 1},loss{float(train_l.mean()):f}')
# 打印权重误差
# w.reshape(true_w.shape):将w变成一维向量,与true_w对齐
print(f'w的估计误差:{true_w - w.reshape(true_w.shape)}')
# 打印偏置误差
print(f'b的估计误差:{true_b - b}')
<think>好的,我需要回答用户关于AI线性回归代码示例的请求。首先,用户提到了引用中的一些内容,特别是引用[2]和引用[5]。根据引用[2],线性回归的基础知识以及最小二乘法和梯度下降法的推导已经讨论过,而引用[5]展示了Spark的线性回归示例。用户现在需要具体的代码示例,可能需要用Python实现。 首先,我应该回顾线性回归的基本原理,确保用户理解代码背后的概念。然后,提供两种常见的实现方法:最小二乘法和梯度下降法。根据引用[2]中的描述,线性回归用于拟合数据并预测连续值,例如房价预测,所以代码示例可能需要一个简单的数据集,比如房价数据。 接下来,我需要确保代码符合用户的要求,使用正确的库,比如NumPy进行数值计算,可能还需要matplotlib进行可视化。同时,根据用户提供的引用[1]中的代码示例,用户可能希望看到类似的结构,比如定义一个LinearRegression类,包含训练方法、预测方法等。 在编写代码时,要注意注释和可读性,让用户能够理解每一步的作用。例如,在梯度下降法中,需要迭代更新参数,并计算损失函数的变化。同时,要处理数据的预处理步骤,比如添加偏置项或特征缩放,但为了简化示例,可能暂时不需要这些。 然后,生成相关问题,帮助用户进一步学习。问题需要围绕线性回归的不同方面,比如损失函数的选择、梯度下降的优化、正则化的应用,以及与其他算法的比较。 最后,确保回答结构清晰,分步骤解释,并引用相关的资料。检查代码是否正确,避免语法错误,并验证示例是否能运行。例如,使用合成数据生成,确保用户可以直接运行代码看到结果。</think>### AI线性回归代码示例及解析 #### 1. 最小二乘法实现 线性回归的最小二乘法通过闭式解直接计算参数,数学形式为: $$ \theta = (X^T X)^{-1} X^T y $$ ```python import numpy as np class LinearRegressionLS: def fit(self, X, y): X_b = np.c_[np.ones((X.shape[0], 1)), X] # 添加偏置项 self.theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y) def predict(self, X): X_b = np.c_[np.ones((X.shape[0], 1)), X] return X_b.dot(self.theta) # 生成示例数据(房屋面积-价格) X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) # 使用模型 model = LinearRegressionLS() model.fit(X, y) print("参数θ:", model.theta) ``` #### 2. 梯度下降法实现 梯度下降通过迭代更新参数,更新规则为: $$ \theta_j := \theta_j - \alpha \frac{\partial J(\theta)}{\partial \theta_j} $$ ```python class LinearRegressionGD: def __init__(self): self.theta = None self.loss_history = [] def train_model(self, X, y, lr=0.01, epochs=1000): X_b = np.c_[np.ones((X.shape[0], 1)), X] self.theta = np.random.randn(X_b.shape[1], 1) for epoch in range(epochs): gradients = 2/X_b.shape[0] * X_b.T.dot(X_b.dot(self.theta) - y) self.theta -= lr * gradients loss = np.mean((X_b.dot(self.theta) - y)**2) self.loss_history.append(loss) return self.theta, self.loss_history # 使用示例 linear_reg = LinearRegressionGD() theta, loss = linear_reg.train_model(X, y, 0.1, 200) print("最终参数:", theta) ``` #### 3. 代码关键点说明 1. **数据预处理**:通过`np.c_`添加全1列实现偏置项处理[^2] 2. **矩阵运算**:使用NumPy的矩阵运算加速计算 3. **损失函数**:均方误差(MSE)作为优化目标[^4] 4. **学习率控制**:过大的学习率可能导致无法收敛 #### 4. 可视化建议 ```python import matplotlib.pyplot as plt # 绘制拟合曲线 plt.scatter(X, y) plt.plot(X, model.predict(X), 'r-') plt.title('房屋面积与价格回归分析') plt.show() # 绘制损失曲线 plt.plot(loss) plt.title('训练过程损失变化') plt.ylabel('MSE') plt.xlabel('Epoch') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值