PyTorch
PyTorch 是一个开源的机器学习框架,目前最主流的深度学习框架之一。
张量创建的方式
torch.tensor(data)
从数据创建,推断类型,复制数据
# 标量 / 张量
t1 = torch.tensor(10)
print(t1)
print('*'*30)
# 二维列表转换张量
data = [[1,2,3],[4,5,6],[7,8,9]]
t2 = torch.tensor(data)
print(t2)
print('*'*30)
# numpy nd数组转换张量
nd_data = np.array([1,2,3])
t3 = torch.tensor(nd_data)
print(t3)
print('*'*30 + '\n')
# 尝试直接创建 指定的维度(2行3列)
# t4 = torch.tensor(2,3) # 这样创建会报错
# print(t4)
torch.Tensor(data)
根据形状创建张量
# 创建一维10个数的 标量 / 张量
t1 = torch.Tensor(10)
print(t1)
print('*'*30)
# 二维列表转换张量
data = [[1,2,3],[4,5,6],[7,8,9]]
t2 = torch.Tensor(data)
print(t2)
print('*'*30)
# numpy nd数组转换张量
nd_data = np.array([1,2,3])
t3 = torch.Tensor(nd_data)
print(t3)
print('*'*30)
# 尝试直接创建 指定的维度(2行3列)
t4 = torch.Tensor(2,3)
print(t4)
torch指定类型
# 创建指定类型的形状
def demo03():
t1 = torch.FloatTensor(5)
print(t1)
print('*'*30)
t2 = torch.FloatTensor([1,2,3,4,5])
print(t2)
print('*'*30)
t3 = torch.FloatTensor(2,3)
print(t3)
print('*'*30)
t4 = torch.IntTensor([1,2,3,4,5])
print(t4)
常见数据类型:
| 数据类型 | dtype | 说明 |
|---|---|---|
| 32位浮点 | torch.float32 / torch.float | 默认浮点类型,深度学习最常用 |
| 64位浮点 | torch.float64 / torch.double | 高精度科学计算 |
| 16位浮点 | torch.float16 / torch.half | 半精度,节省显存,需 GPU 支持 |
| Brain Float16 | torch.bfloat16 | 范围与 float32 相同,精度降低,训练加速 |
| 8位浮点 | torch.float8_e4m3fn / torch.float8_e5m2 | 最新硬件支持(H100等),量化推理 |
| 8位整型 | torch.int8 | 量化推理常用 |
| 16位整型 | torch.int16 / torch.short | |
| 32位整型 | torch.int32 / torch.int | 默认整型 |
| 64位整型 | torch.int64 / torch.long | 索引、标签常用 |
| 布尔型 | torch.bool | True/False |
| 复数32位 | torch.complex32 | |
| 复数64位 | torch.complex64 / torch.cfloat | |
| 复数128位 | torch.complex128 / torch.cdouble |
创建全部 0 / 1 / 指定值
# 创建全部为1的三行五列
t1 = torch.ones(3,5)
print(t1)
# 创建全部为1的两行三列,torch.ones_like() 参数为torch.Tensor()
t2 = torch.ones_like(torch.Tensor(2,3))
print(t2)
print('*' * 30)
# 创建全部为0的三行四列
t3 = torch.zeros(3,5)
print(t3)
# 创建全部为0的两行三列
t4 = torch.zeros_like(torch.Tensor(2,3))
print(t4)
print('*' * 30)
# 创建全部是5的两行三列
t5 = torch.full((2,3),5)
print(t5)
t6 = torch.fill(torch.Tensor(2,3), 5)
print(t6)
t7 = torch.full_like(torch.Tensor(2,3), 5)
print(t7)
创建线性和随机张量
# 创建线性张量
t1 = torch.arange(1,10)
print(t1)
print('*'*30)
t2 = torch.linspace(1,10,10)
print(t2)
print('*'*30)
# 设置随机数种子
torch.random.manual_seed(32)
# 返回种子数 默认值为系统时间
seed = torch.random.initial_seed()
print(seed)
# 创建均匀分布(0,1)随机张量
t3 = torch.rand((2,3))
print(t3)
# 创建正态分布随机张量
t4 = torch.randn((2,3))
print(t4)
# 创建随机整数张量
# 生成1到10的2行三列
t5 = torch.randint(1,10,(2,3))
print(t5)
张量元素类型转换
# 创建时选择类型
t1 = torch.tensor([1,2,3,4,5],dtype=torch.float32)
print(t1)
# 第一种转换方式type:类型转换为int32
t2 = t1.type(torch.int32)
print(t2)
# 第二种转换方式为:.类型
t3 = t2.long()
print(t3,type(t3))
张量与numpy相互转换
张量转换numpy
# 创建张量
t1 = torch.tensor([1,2,3,4,5])
t2 = t1.numpy() # 此时内存是与t1共享的
t3 = t1.numpy().copy() # 复制一个,重新赋值地址
# 修改t2的数据后,t1会变,t3不变
t2[0] = 100
print(t1) # tensor([100, 2, 3, 4, 5])
print(t2) # [100 2 3 4 5]
print(t3) # [1 2 3 4 5]
numpy转换张量
# 创建numpy数组
t1 = np.array([1,2,3,4,5])
# 将numpy数组转换为张量
t2 = torch.from_numpy(t1) # 内存是共享的
print(t1) #[1 2 3 4 5]
print(t2) #tensor([1, 2, 3, 4, 5])
张量的基本运算
a = torch.tensor([[1, 2], [3, 4]])
b = torch.tensor([[5, 6], [7, 8]])
# 加减乘除(形状必须相同或广播兼容)
print(a + b) # 逐元素相加
print(a - b) # 逐元素相减
print(a * b) # 逐元素相乘(Hadamard积,不是矩阵乘法!)
print(a / b) # 逐元素相除
print(a ** 2) # 逐元素平方
# 等价函数形式
torch.add(a, b) # a + b
torch.sub(a, b) # a - b
torch.mul(a, b) # a * b
torch.div(a, b) # a / b
矩阵乘法运算
t1 = torch.tensor([[1,2],[3,4],[5,6]])
t2 = torch.tensor([[1,2,3],[4,5,6]])
# 矩阵运算
t3 = t1 @ t2
# 效果同上
t4 = t1.matmul(t2)
print(t3)
print(t4)
A数据:
| 1 | 2 |
|---|---|
| 3 | 4 |
| 5 | 6 |
B数据:
| 1 | 2 | 3 |
|---|---|---|
| 4 | 5 | 6 |
矩阵相乘要求:A列 等于 B行
结果为:A行B列
计算过程:
第一行第一列:1 * 1 + 2 * 4 = 9
第一行第二列:1 * 2 + 2 * 5 = 12
第一行第二列:1 * 3 + 2 * 6 = 15
第二行第一列:3 * 1 + 4 * 4 = 19
第二行第二列:3 * 2 + 4 * 5 = 26
第二行第三列:3 * 3 + 4 * 6 = 33
第三行第一列:5 * 1 + 6 * 4 = 29
第三行第二列:5 * 2 + 6 * 5 = 40
第三行第三列:5 * 3 + 6 * 6 = 51
最终结果:
9 12 15
19 26 33
29 40 51
张量运算函数
# 创建张量
t1 = torch.tensor([[1,2,3],[4,5,6]],dtype=torch.float32)
# 求和
# dim参数就是填写行(1)或列(0)
t2 = t1.sum(dim=0) # 列求和
t3 = t1.sum(dim=1) # 行求和
t4 = t1.sum() # 整体求和
print(t2)
print(t3)
print(t4)
# 最大值
t2 = t1.max(dim=0) # 列找最大值
t3 = t1.max(dim=1) # 行找最大值
t4 = t1.max() # 整体找最大值
print(t2)
print(t3)
print(t4)
# 最小值
t2 = t1.min(dim=0) # 列找最大值
t3 = t1.min(dim=1) # 行找最大值
t4 = t1.min() # 整体找最大值
print(t2)
print(t3)
print(t4)
# 平均值
t2 = t1.mean(dim=0) # 列找最大值
t3 = t1.mean(dim=1) # 行找最大值
t4 = t1.mean() # 整体找最大值
print(t2)
print(t3)
print(t4)
# n的幂次方
t2 = t1.pow(2) # 列找最大值
# 效果同上
t3 = t1 ** 2
print(t2)
print(t3)
# 开平方
t2 = t1.sqrt()
print(t2)
# e的n次方
t2 = t1.exp()
print(t2)
# 对数
t2 = t1.log() #以e为底的底数
t3 = t1.log2() #以2为底的
t4 = t1.log10() #以10为底的
print(t2)
print(t3)
print(t4)
张量的索引
行列索引
torch.random.manual_seed(42)
t1 = torch.randint(1,9,(4,4))
print(t1)
# tensor([[7, 4, 5, 7],
# [3, 8, 5, 5],
# [7, 2, 3, 7],
# [3, 3, 8, 5]])
print('-'* 50)
# 获取第一行所有列
t2 = t1[0,:]
print(t2) # tensor([7, 4, 5, 7])
# 获取所有行第二列
t3 = t1[:,1]
print(t3) # tensor([4, 8, 2, 3])
列表索引
torch.random.manual_seed(42)
t1 = torch.randint(1,9,(4,4))
#tensor([[7, 4, 5, 7],
# [3, 8, 5, 5],
# [7, 2, 3, 7],
# [3, 3, 8, 5]])
print(t1)
print('-'* 50)
# 获取第二行第三列和第三行和第四列,第二行第四列
# 前面中括号为行,后面中括号为列,一一对应,组合成行列
print(t1[[1,2,1],[2,3,3]]) # tensor([5, 7, 5])
# 获取2,3行的2,3列所有交集数据
# 参数中数组用括号表示那一行或那一列所有数据
print(t1[[[1],[2]],[1,2]])
#tensor([[8, 5],
# [2, 3]])
范围索引
torch.random.manual_seed(42)
t1 = torch.randint(1,9,(4,4))
#tensor([[7, 4, 5, 7],
# [3, 8, 5, 5],
# [7, 2, 3, 7],
# [3, 3, 8, 5]])
print(t1)
print('-'* 50)
# 获取行为2之后,列为2之前的所有数据
t2 = t1[2:,:2]
print(t2)
# tensor([[7, 2],
# [3, 3]])
# 获取行的所有奇数,列的所有偶数
t3 = t1[0::2,1::2]
print(t3)
# tensor([[4, 7],
# [2, 7]])
布尔索引
torch.random.manual_seed(42)
t1 = torch.randint(1,9,(4,4))
#tensor([[7, 4, 5, 7],
# [3, 8, 5, 5],
# [7, 2, 3, 7],
# [3, 3, 8, 5]])
print(t1)
print('-'* 50)
# 直接拿布尔列表进行对比
print( t1[0,[True,False,True,False]] ) # tensor([7, 5])
# 找到所有大于5的
print(t1[t1 > 5]) # tensor([7, 7, 8, 7, 7, 8])
# 找到第二行所有大于5的
print(t1[1,t1[1]>5]) # tensor([8])
# 找到第3行大于5 索引的所有列
print(t1[:, t1[2] > 5])
# tensor([[7, 7],
# [3, 5],
# [7, 7],
# [3, 5]])
多维索引
0轴就是1维,1轴就是2维,2轴就是3维
torch.random.manual_seed(42)
# 创建2个3行4列的多维
t1 = torch.randint(1,9,(2,3,4))
print(t1)
print('-'* 50)
# 获取0轴数据
print(t1[0,:,:])
# tensor([[7, 4, 5, 7],
# [3, 8, 5, 5],
# [7, 2, 3, 7]])
# 获取1轴数据
print(t1[:,0,:])
# tensor([[7, 4, 5, 7],
# [3, 3, 8, 5]])
# 获取2轴数据
print(t1[:,:,0])
# tensor([[7, 3, 7],
# [3, 4, 6]])
张量的形状操作
t1 = torch.tensor([[1,2,3],
[4,5,6],
[7,8,9],
[10,11,12]])
print(f'{t1} :\n 整体: {t1.shape} 获取行数:{t1.shape[0]} 获取列数:{t1.shape[1]} / {t1.shape[-1]}')
# tensor([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9],
# [10, 11, 12]]):
# 整体: torch.Size([4, 3])
# 获取行数:4
# 获取列数:3 / 3
print('*' * 50)
# 转换不是真的转换了,只是改变了显示方式
# 转换为1行10列
t2 = t1.reshape(1,12)
print(t2) # tensor([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]])
# 转换为3行4列
t3 = t2.reshape(3,4)
print(t3)
# tensor([[1, 2, 3, 4],
# [5, 6, 7, 8],
# [9, 10, 11, 12]])
t4 = t3.reshape(4,3)
print(t4)
# tensor([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9],
# [10, 11, 12]])
升维和降维操作
# 源数据
t1 = torch.tensor([1,2,3,4,5,6,7,8,9])
print(t1)
print(t1.shape)
print('*' * 50)
# 升维操作
# 在指定位置插入大小为1的维度
# 在位置0增加维度
t2= t1.unsqueeze(0)
print(t2)
# tensor([[1, 2, 3, 4, 5, 6, 7, 8, 9]])
print(t2.shape) # 1行9列
# torch.Size([1, 9])
# 在位置1增加维度
t3= t1.unsqueeze(1)
print(t3) # 9行1列
# tensor([[1],
# [2],
# [3],
# [4],
# [5],
# [6],
# [7],
# [8],
# [9]])
print(t3.shape)
# torch.Size([9, 1])
# 降维操作
# 移除大小为1的维度
t4 = t2.squeeze()
print(t4.shape) # torch.Size([9])
t5 = t3.squeeze()
print(t5.shape) # torch.Size([9])
维度交换操作
t1 = torch.rand(2,3,4)
print(t1.shape) # torch.Size([2, 3, 4])
# 两个维转换
# 将维度 2, 3, 4 --> 4, 3, 2
t2 = t1.transpose(0,2)
t3 = t1.transpose(0, -1) # 效果同上,-1指向最后一位
print(t2.shape) # torch.Size([4, 3, 2])
print(t3.shape) # torch.Size([4, 3, 2])
# 多个维转换
# 将维度 2, 3, 4 --> 3, 4, 2
t4 = t1.permute(1,2,0)
print(t4.shape) # torch.Size([3, 4, 2])
张量的另类形状操作
t1 = torch.tensor([[1,2,3],
[4,5,6,]])
print(t1)
# tensor([[1, 2, 3],
# [4, 5, 6]])
print(t1.shape) # torch.Size([2, 3])
# 判断张量是否连续
print(t1.is_contiguous()) # True
# view必须连续才能使用
t2 = t1.view(3,2)
print(t2)
# tensor([[1, 2],
# [3, 4],
# [5, 6]])
print(t2.shape) # torch.Size([3, 2])
# 破坏张量连续性
t3 = t1.transpose(0,1)
# 现在已经不连续了
print(t3.is_contiguous()) # False
# 下面这个会报错,因为不连续了
# t4 = t3.view(2,3)
# print(t4)
# 先将不连续的变为连续的再查看
t4 = t3.contiguous().view(2,3)
print(t4.is_contiguous()) # True
print(t4)
# tensor([[1, 4, 2],
# [5, 3, 6]])
print(t4.shape)
# torch.Size([2, 3])
张量的拼接操作
# cat 不改变维度数,拼接张量,除了拼接的那个维度外,其它维度数必须保持一致
# stack 会改变维度数,拼接张量,所有的维度都必须保持一致
t1 = torch.tensor([[1,2,3],
[4,5,6,]])
t2 = torch.tensor([[6,5,4],
[3,2,1,]])
t3 = torch.cat((t1,t2),dim=0)
print(t3)
# tensor([[1, 2, 3],
# [4, 5, 6],
# [6, 5, 4],
# [3, 2, 1]])
print(t3.shape)
# torch.Size([4, 3])
t4 = torch.cat((t1, t2), dim=1)
print(t4)
# tensor([[1, 2, 3, 6, 5, 4],
# [4, 5, 6, 3, 2, 1]])
print(t4.shape)
# torch.Size([2, 6])
# 这样操作是越界的,因为这是一个二维,不能跨维度操作
# t5 = torch.cat((t1, t2), dim=2)
# print(t5)
# print(t5.shape)
t6 = torch.tensor([[1,2,3]])
print(t6) # tensor([[1, 2, 3]])
print(t6.shape) # torch.Size([1, 3])
t7 = torch.cat((t1,t6),dim=0)
print(t7)
# tensor([[1, 2, 3],
# [4, 5, 6],
# [1, 2, 3]])
print(t7.shape) # torch.Size([3, 3])
t8 = torch.tensor([[1,2],[3,4]])
t9 = torch.cat((t1,t8),dim= 1)
print(t9)
# tensor([[1, 2, 3, 1, 2],
# [4, 5, 6, 3, 4]])
print(t9.shape) # torch.Size([2, 5])
# stack -------------------------------------------
t10 = torch.stack([t1,t2],dim=0)
print(t10)
# tensor([[[1, 2, 3],
# [4, 5, 6]],
#
# [[6, 5, 4],
# [3, 2, 1]]])
print(t10.shape) # torch.Size([2, 2, 3])
# 效果同上,但是实际含义不一样
t11 = torch.stack([t1,t2],dim=1)
print(t11)
# tensor([[[1, 2, 3],
# [6, 5, 4]],
#
# [[4, 5, 6],
# [3, 2, 1]]])
print(t11.shape) # torch.Size([2, 2, 3])
t12 = torch.stack([t1,t2],dim=2)
print(t12)
# tensor([[[1, 6],
# [2, 5],
# [3, 4]],
#
# [[4, 3],
# [5, 2],
# [6, 1]]])
print(t12.shape) # torch.Size([2, 3, 2])
# 下面会报错,已经越界了,因为跨维度了
# t13 = torch.stack([t1,t2],dim=3)
# print(t13)
# print(t13.shape)
自动微分
前向传播:构建图 反向传播:遍历图求导
# 定义变量,设置初始值(旧权重W)
# 参数1:初始值;参数2:是否自动微分;参数3:设置类型
w = torch.tensor(10,requires_grad = True,dtype=torch.float)
print(w)
# 定义loss变量,表示损失函数(这只是一种演示算法,不是真实情况公式)
loss = 2 * w ** 2
# loss.backward() # 进行求导 2w^2 -> 4w
loss.sum().backward(retain_graph = True) # 效果同上,sum函数能确保只有1个标量,因为求导只能对标量求导,否则报错
print(w.grad) # 求导算出的梯度(损失函数)
print(w.data) # 权重数据
# 模拟 权重更新公式:新权重 = 旧权重 - 学习率 * 梯度(损失函数)
learning_rate = 0.001 # 定义学习率
# 10 - 0.001 * (4 * 10)
w.data = w.data - learning_rate * w.grad
print(w.data) # 新权重结果
# 再计算一轮
w.grad.zero_() # 解决梯度累计问题,清除上一轮的梯度数据
# 进行求导 4 * 9.96 = 39.84
loss.sum().backward()
# 9.96 - 0.001 * 39.84
w.data = w.data - learning_rate * w.grad
print(w.grad) # tensor(39.8400)
print(w.data) # tensor(9.9202)
自动微分例子演示:
# 演示自动微分模块,循环实现计算梯度,并更新参数
# 求 y = x^2 + 20 的极小值点,并打印y是最小值时w的值(梯度)
# 定义参数
x = torch.tensor(10,requires_grad = True,dtype=torch.float)
# 定义函数(正向传播)
y = x ** 2 + 20 # 求导 2x
# 定义学习率
learning_rate = 0.01
# 利用梯度下降法,进行1000次迭代,求最优解
for i in range(1,101):
y.backward(retain_graph = True) # 求导(反向传播),参数:保留计算图,不需要清除
x.data = x.data - learning_rate * x.grad
print(f"第{i}次:数据:{x.data},梯度:{x.grad}")
x.grad.zero_() # 清除
# 打印结果:
# 第1次:数据:9.800000190734863,梯度:20.0
# 第2次:数据:9.604000091552734,梯度:19.600000381469727
# 第3次:数据:9.411920547485352,梯度:19.20800018310547
# ...
# 第99次:数据:1.3532609939575195,梯度:2.7617571353912354
# 第100次:数据:1.3261957168579102,梯度:2.706521987915039
拷贝自动微分数据
# 创建初始值列表,自动微分
x = torch.tensor([10,20],requires_grad = True,dtype=torch.float)
print(x) # tensor([10., 20.], requires_grad=True)
# arr = x.numpy() # 这行代码会报错,因为启用了自动微分
arr = x.detach().numpy() # 如果要拷贝需要使用detach()
# 修改x值
x.data[0] = 100
# 修改了x值,arr的值也变了,说明内存是共享的
print(x) # tensor([100., 20.], requires_grad=True)
print(arr) # [100. 20.]
例子:
源数据集
X:
| x1 | x2 | y |
|---|---|---|
| 1 | 2 | 3 |
| 3 | 4 | 5 |
偏置
b:0.62b: 0.62b:0.62
前置知识:
无激活函数 (纯线性运算):
y^=xTw+b=∑i=1nxiwi+b\hat{y} = x^T w + b = \sum_{i=1}^{n} x_i w_i + by^=xTw+b=i=1∑nxiwi+b
在数学和统计学中,xxx向量默认是列向量(column vector),也就是说实际数据以以下的列形式展示:
X=[x1(1)x2(1)⋯xn(1)x1(2)x2(2)⋯xn(2)⋮⋮⋱⋮x1(m)x2(m)⋯xn(m)]m×n,w=[w1w2⋮wn]X = \begin{bmatrix} x_1^{(1)} & x_2^{(1)} & \cdots & x_n^{(1)} \\ x_1^{(2)} & x_2^{(2)} & \cdots & x_n^{(2)} \\ \vdots & \vdots & \ddots & \vdots \\ x_1^{(m)} & x_2^{(m)} & \cdots & x_n^{(m)} \end{bmatrix}_{m \times n}, \quad w = \begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ w_n \end{bmatrix}X=x1(1)x1(2)⋮x1(m)x2(1)x2(2)⋮x2(m)⋯⋯⋱⋯xn(1)xn(2)⋮xn(m)m×n,w=w1w2⋮wn
所以x是列形式,矩阵计算必须满足A列等于B行,需要转置才能进行矩阵计算
正规方程(求最优参数)
w~=(X~TX~)−1X~Ty\tilde{w} = (\tilde{X}^T \tilde{X})^{-1} \tilde{X}^T yw~=(X~TX~)−1X~Ty
w~\tilde{w}w~是一个向量
第一步移偏置,求 y′y′y′
3−0.62=2.383 - 0.62 = 2.383−0.62=2.38
3−0.62=4.383 - 0.62 = 4.383−0.62=4.38
第二步构建矩阵
X=[1234]2×2,y′=[2.384.38]X = \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}_{2 \times 2}, \quad y' = \begin{bmatrix} 2.38 \\ 4.38 \end{bmatrix}X=[1324]2×2,y′=[2.384.38]
XT=[1324]X^T = \begin{bmatrix} 1 & 3 \\ 2 & 4 \end{bmatrix}XT=[1234]
第三步计算XTXX^T XXTX
XTX=[10141420]X^T X = \begin{bmatrix} 10 & 14 \\ 14 & 20 \end{bmatrix}XTX=[10141420]
第四步计算行列式
det(XTX)=10×20−14×14=200−196=4\det(X^T X) = 10 \times 20 - 14 \times 14 = 200 - 196 = \mathbf{4}det(XTX)=10×20−14×14=200−196=4
行列式 ≠ 0,可逆
第五步求逆矩阵:(XTX)−1(X^T X)^{-1}(XTX)−1
第六步计算:XTy′X^T y'XTy′
XTy′=[15.5222.28]X^T y' = \begin{bmatrix} 15.52 \\ 22.28 \end{bmatrix}XTy′=[15.5222.28]
第七步计算:θ=(XTX)−1XTy′\theta = (X^T X)^{-1} X^T y'θ=(XTX)−1XTy′
θ=[5−3.5−3.52.5][15.5222.28]\theta = \begin{bmatrix} 5 & -3.5 \\ -3.5 & 2.5 \end{bmatrix} \begin{bmatrix} 15.52 \\ 22.28 \end{bmatrix}θ=[5−3.5−3.52.5][15.5222.28]
结果:
θ1=−0.38,θ2=1.38,b=0.62\boxed{\theta_1 = -0.38, \quad \theta_2 = 1.38, \quad b = 0.62}θ1=−0.38,θ2=1.38,b=0.62
x1x_1x1权重为:-0.38
x2x_2x2权重为:1.38
梯度下降(求最优参数)
数据集
| x1x_1x1 | x2x_2x2 | x3x_3x3 | yyy |
|---|---|---|---|
| 1 | 2 | 3 | 3 |
| 4 | 5 | 6 | 5 |
初始权重
| w1w_1w1 | w2w_2w2 | w3w_3w3 |
|---|---|---|
| 0.6614 | 0.2669 | 0.0617 |
计算均方误差公式
L(w,b)=1m∑i=1m(y^(i)−y(i))2=1m∑i=1m(x(i)Tw+b−y(i))2L(w, b) = \frac{1}{m} \sum_{i=1}^{m} \left( \hat{y}^{(i)} - y^{(i)} \right)^2 = \frac{1}{m} \sum_{i=1}^{m} \left( x^{(i)T} w + b - y^{(i)} \right)^2L(w,b)=m1i=1∑m(y^(i)−y(i))2=m1i=1∑m(x(i)Tw+b−y(i))2
计算权重公式:
新W = 旧W - 学习率 * 梯度分量的批量求和
θj:=θj−α⋅∂J∂θj\boxed{\theta_j := \theta_j - \alpha \cdot \frac{\partial J}{\partial \theta_j}}θj:=θj−α⋅∂θj∂J
θj=每个特征权重\theta_j = 每个特征权重θj=每个特征权重
α=学习率(步长)\alpha = 学习率(步长)α=学习率(步长)
∂J∂θj=损失函数对θj的偏导数\frac{\partial J}{\partial \theta_j} = 损失函数对\theta_j的偏导数∂θj∂J=损失函数对θj的偏导数
梯度计算公式:
∂J∂θj=1m∑i=1m(y^(i)−y(i))xj(i)\frac{\partial J}{\partial \theta_j} = \frac{1}{m} \sum_{i=1}^{m} (\hat{y}^{(i)} - y^{(i)}) x_j^{(i)}∂θj∂J=m1∑i=1m(y^(i)−y(i))xj(i)
初始化:
学习率:α=0.1\quad \alpha = 0.1α=0.1
第1轮
计算预测值:
x1(1)∗w1+x1(2)∗w2+x1(3)∗w3x_1^{(1)} * w_1 + x_1^{(2)} * w_2 + x_1^{(3)} * w_3x1(1)∗w1+x1(2)∗w2+x1(3)∗w3
y^′(1)=1∗0.6614+2∗0.2669+3∗0.0617+0.62=2.0003\hat{y}'^{(1)} =1 * 0.6614 + 2 * 0.2669 + 3 * 0.0617 + 0.62 = 2.0003y^′(1)=1∗0.6614+2∗0.2669+3∗0.0617+0.62=2.0003
x2(1)∗w1+x2(2)∗w2+x2(3)∗w3x_2^{(1)} * w_1 + x_2^{(2)} * w_2 + x_2^{(3)} * w_3x2(1)∗w1+x2(2)∗w2+x2(3)∗w3
y^′(2)=4∗0.6614+5∗0.2669+6∗0.0617+0.62=4.9703\hat{y}'^{(2)} = 4 * 0.6614 + 5 * 0.2669 + 6 * 0.0617 + 0.62 = 4.9703y^′(2)=4∗0.6614+5∗0.2669+6∗0.0617+0.62=4.9703
求导后,就是误差(预测值 - 真实值)
误差:
e(1)=2.0003−3=−0.9997e^{(1)} = 2.0003 - 3 = -0.9997e(1)=2.0003−3=−0.9997
e(2)=4.9703−5=−0.0297e^{(2)} = 4.9703 - 5 = -0.0297e(2)=4.9703−5=−0.0297
权重计算公式:
新权重 = 旧权重 - 学习率 * 梯度(梯度分量的批量求和)
计算w1w_1w1的新权重
e(1)∗x1(1)+e(2)∗x1(2)e^{(1)} * x_1^{(1)} + e^{(2)} * x_1^{(2)}e(1)∗x1(1)+e(2)∗x1(2)
(−0.9997)∗1+(−0.0297)∗4=−1.1185(-0.9997) * 1 + (-0.0297) * 4 = -1.1185(−0.9997)∗1+(−0.0297)∗4=−1.1185
0.6614−0.01∗(−1.1185)=0.6725850.6614 - 0.01 * (-1.1185) = 0.6725850.6614−0.01∗(−1.1185)=0.672585
计算w2w_2w2的新权重
2∗−0.9997+5∗−0.0297=−2.14792 * -0.9997 + 5 * -0.0297 = -2.14792∗−0.9997+5∗−0.0297=−2.1479
0.2669−0.01∗−2.1479=0.2883790.2669 - 0.01 * -2.1479 = 0.2883790.2669−0.01∗−2.1479=0.288379
计算w3w_3w3的新权重
3∗−0.9997+6∗−0.0297=−3.17733 * -0.9997 + 6 * -0.0297 = -3.17733∗−0.9997+6∗−0.0297=−3.1773
0.0617−0.01∗−3.1773=0.0934730.0617 - 0.01 * -3.1773 = 0.0934730.0617−0.01∗−3.1773=0.093473
第二轮,以此类推
…

4042

被折叠的 条评论
为什么被折叠?



