笔者是大一(2022.12.22)零基础小白,这是一些个人理解的梳理。
线性回归(linear regression):线性回归是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,运用十分广泛。其表达形式为y = w'x+e,e为误差服从均值为0的正态分布。(摘自百度)
批注1:笔者还没有学习概率论和数理统计,这些概念也不是很懂,就是对一堆散点找到一条最好的直线,为了实现线性回归我们需要一个评价这条直线的好的程度的评价函数和一个找到这条直线的搜索函数去猜出这条最佳的直线。
批注2:搜索的函数和模拟退火算法有些类似支持,实际上可以借用模拟退火(随机化搜索)随机猜测搜索可能的直线,直到找到最佳的直线。
批注3:以上为一元线性回归,如果是高阶的线性回归,就是在超平面空间内拟合直线,本质是一样的。
批注4:线性回归是唯一存在显式解的模型,是单层的神经网络(李沐)
线型模型:
批注1:w是表示各个x的权重的列向量,x是表示各个x的列向量,[]表示的向量的内积(也可以用<>),b是偏差,y表示的在向量空间内的线。
批注2:x是自变量向量,y是因变量向量。(y其实是标量)
批注3:y是目标的标量,x是多个考虑的因素,x是列向量。
平方损失:
(某点损失)(1)
(总损失)(2)
(3)
(4)
(5)
批注1:y尖读作(y hat)表示的是估计值,就是对于每个x向量代入模型后输出的y和实际的y的差别。
批注2:除2便于求导。
批注3:补充知识,对向量求导
批注4:||||是求模, (2)中X是矩阵,w是行向量,y是行向量,b是行向量,因为取了多组数据,再求模。
批注5:目的是求出行向量w和标量b使得损失函数的值最小。
批注6:把偏差行向量b加入wX中使得以及得(3)
批注7:求导得(4)注意这里是行向量。
批注8:由于函数是在向量空间的里的凸函数,当取到导数为的时候取到优解。
梯度下降:
这是用来搜索最佳w的方法,因为直接求逆矩阵的计算量太大。有时候几乎是不可能的。
在高维度的向量空间内,想象一个下凹的类似抛物线旋转而来的东西,最佳的w是顶点处,但是我们无法知道,所以使用梯度搜索的方法(在二维平面内又可以说是牛顿切线法)
(符号看上面取的是大小还是方向,保持一致即可)(n是学习率)
来自动手深度学习,加了一些注释,python还是不太懂,慢慢学习当中。
import torch
import numpy
import random
def synthetic_data(w, b, num_examples): #@save
"""生成y=Xw+b+噪声"""#生成一个人造的数据集权重w,偏差b,数据数目
X = torch.normal(0, 1, (num_examples, len(w)))#生成张量,均值为0,标准差为1,数目x列长为w的张量
y = torch.matmul(X, w) + b#matmul矩阵乘法得到Xw+b
y += torch.normal(0, 0.01, y.shape)#噪声,y.shape返回矩阵形状,一定要加上同行的矩阵
return X, y.reshape((-1, 1))#把y转化成一列
true_w = torch.tensor([2, -3.4])#给定w张量
true_b = 4.2#给定b
features, labels = synthetic_data(true_w, true_b, 1000)#生成数据集
def data_iter(batch_size, features, labels):#读取数据
num_examples = len(features)
indices = list(range(num_examples))
# 这些样本是随机读取的,没有特定的顺序
random.shuffle(indices)#随机打乱下标
for i in range(0, num_examples, batch_size):#取某个批量的数据
batch_indices = torch.tensor(
indices[i: min(i + batch_size, num_examples)])#防止越界
yield features[batch_indices], labels[batch_indices]#递归调用?
w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)#初始化。requires_grad是否梯度信息
def linreg(X, w, b): #@save
"""线性回归模型"""
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:
param -= lr * param.grad / batch_size
param.grad.zero_()#手动设置为0
lr = 0.03#学习率
num_epochs = 3#训练次数
net = linreg
loss = squared_loss
batch_size = 1#这个是自己加的不知道为什么不加会报错。
for epoch in range(num_epochs):
for X, y in data_iter(batch_size, features, labels):
l = loss(net(X, w, b), y) # X和y的小批量损失
# 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,
# 并以此计算关于[w,b]的梯度
l.sum().backward()
sgd([w, b], lr, batch_size) # 使用参数的梯度更新参数
with torch.no_grad():
train_l = loss(net(features, w, b), labels)
print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')