PyTorch-学习笔记

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 Float16torch.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.boolTrue/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数据:

12
34
56

B数据:

123
456

矩阵相乘要求: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:

x1x2y
123
345

偏置
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=1nxiwi+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=w1w2wn

所以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.3830.62=2.38
3−0.62=4.383 - 0.62 = 4.3830.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×2014×14=200196=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}θ=[53.53.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_1x1x2x_2x2x3x_3x3yyy
1233
4565

初始权重

w1w_1w1w2w_2w2w3w_3w3
0.66140.26690.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=1m(y^(i)y(i))2=m1i=1m(x(i)Tw+by(i))2

计算权重公式:
新W = 旧W - 学习率 * 梯度分量的批量求和
θj:=θj−α⋅∂J∂θj\boxed{\theta_j := \theta_j - \alpha \cdot \frac{\partial J}{\partial \theta_j}}θj:=θjαθjJ

θj=每个特征权重\theta_j = 每个特征权重θj=每个特征权重

α=学习率(步长)\alpha = 学习率(步长)α=学习率(步长)

∂J∂θj=损失函数对θj的偏导数\frac{\partial J}{\partial \theta_j} = 损失函数对\theta_j的偏导数θjJ=损失函数对θ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)}θjJ=m1i=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)=10.6614+20.2669+30.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)=40.6614+50.2669+60.0617+0.62=4.9703

求导后,就是误差(预测值 - 真实值)
误差:
e(1)=2.0003−3=−0.9997e^{(1)} = 2.0003 - 3 = -0.9997e(1)=2.00033=0.9997
e(2)=4.9703−5=−0.0297e^{(2)} = 4.9703 - 5 = -0.0297e(2)=4.97035=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.66140.01(1.1185)=0.672585

计算w2w_2w2的新权重
2∗−0.9997+5∗−0.0297=−2.14792 * -0.9997 + 5 * -0.0297 = -2.147920.9997+50.0297=2.1479
0.2669−0.01∗−2.1479=0.2883790.2669 - 0.01 * -2.1479 = 0.2883790.26690.012.1479=0.288379

计算w3w_3w3的新权重
3∗−0.9997+6∗−0.0297=−3.17733 * -0.9997 + 6 * -0.0297 = -3.177330.9997+60.0297=3.1773
0.0617−0.01∗−3.1773=0.0934730.0617 - 0.01 * -3.1773 = 0.0934730.06170.013.1773=0.093473

第二轮,以此类推

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值