第二周周报

摘要

  本周在深度学习方面,学习梯度、自动求导以及实现人造数据集进行线性回归的实验;在组合数学方面,对第一章(除了排序生成算法)进行复习。
  This week, I were conducted on linear regression experiments with artificial datasets and learning gradients, automatic differentiation in terms of deep learning. In combinatorial mathematics, I also review Chapter 1 (except for sorting generation algorithms).

组合数学

加法原理:集合S的划分,|s| = |s1|+|s2|+|s3|。。。。,各个集合之间是没有交集的。
乘法原理:使用时,单个步骤不能完成目标,只能所有步骤使用完成才能完成,因此用乘法。
在这里插入图片描述
任何一个数都能化成素数幂的形式;整数的唯一分解定理。
比如 n =45 求能整除n 的数 2*3= 6
在这里插入图片描述
在这里插入图片描述

一一对应:将一个问题转化成另一个问题11对应,在处理组和技术问题时,常常通过问题11对应实现模型的转换。
Cayley定理:n个有标号的顶点的树的 数目等于
n n − 2 {{\rm{n}}^{n - 2}} nn2

在这里插入图片描述
选择顺序对乘法原理的使用:一个任务若分为若干个子任务,若完成某个子任务的途径影响整个任务的完成,那么就不能使用乘法原理。
在这里插入图片描述
组合和排列相关习题
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

循环排列

组合

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个例题与上题不同的是,没有顺序,因此在最后需要除以3!

多重集的排列和组合

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
有限多重集S的r-组合这个问题可以转化成求解x1+x2+x3+。。。xk=r的非负整数解的个数。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

深度学习

标量导数

导数是切线的斜率
y a x n exp ⁡ ( x ) log ⁡ ( x ) sin ⁡ ( x ) d y d x 0 n x n − 1 exp ⁡ ( x ) 1 x cos ⁡ ( x ) \begin{array}{c|ccccc} y & a & x^n & \exp (x) & \log (x) & \sin (x) \\ \hline \frac{d y}{d x} & 0 & n x^{n-1} & \exp (x) & \frac{1}{x} & \cos (x) \end{array} ydxdya0xnnxn1exp(x)exp(x)log(x)x1sin(x)cos(x)
y u + v u v y = f ( u ) , u = g ( x ) d y d x d u d x + d v d x d u d x v + d v d x u d y d u d u d x \begin{array}{c|ccc} y & u+v & u v & y=f(u), u=g(x) \\ \hline \frac{d y}{d x} & \frac{d u}{d x}+\frac{d v}{d x} & \frac{d u}{d x} v+\frac{d v}{d x} u & \frac{d y}{d u} \frac{d u}{d x} \end{array} ydxdyu+vdxdu+dxdvuvdxduv+dxdvuy=f(u),u=g(x)dudydxdu

亚导数

将导数拓展到不可微的函数

在这里插入图片描述
∂ ∣ x ∣ ∂ x = { 1  if  x > 0 − 1  if  x < 0 a  if  x = 0 , a ∈ [ − 1 , 1 ] \frac{\partial|x|}{\partial x}= \begin{cases}1 & \text { if } x>0 \\ -1 & \text { if } x<0 \\ a & \text { if } x=0, \quad a \in[-1,1]\end{cases} xx= 11a if x>0 if x<0 if x=0,a[1,1]
例如在x=0这一点时,当x>0,导数值取1,x<0导数值取-1;当x=0时,导数值可以取 [ − 1 , 1 ] [-1,1] [11]之间的任何值

梯度

导数在几何上可看作某一函数上在某一点的切线的斜率
1)对于单个自变量的函数,导数就是该点的梯度。
2)对于多个自变量的函数,我们对每个自变量都进行求导,
梯度就是每个导数所组成的向量。
梯度方向是某一函数在某一点上的变化率最大的方向,由此进行迭代计算可找到函数的最值。

          标量和向量构成的求导表格

x x x X X X
y y y ∂ y ∂ x \frac{{\partial {\rm{y}}}}{{\partial x}} xy ∂ y ∂ X \frac{{\partial y}}{{\partial X}} Xy
Y Y Y ∂ Y ∂ x \frac{{\partial Y}}{{\partial x}} xY ∂ Y ∂ X \frac{{\partial Y}}{{\partial X}} XY

小写字母表示标量,大写字母表示向量

  • ∂ y ∂ x \frac{{\partial {\rm{y}}}}{{\partial x}} xy
    标量对标量的求导,结果还是标量
  • ∂ y ∂ X \frac{{\partial y}}{{\partial X}} Xy
    [n,1]向量对标量的求导,结果是得到一个[1,n]横向量

∂ y ∂ x = [ ∂ y ∂ x 1 , ∂ y ∂ x 2 , … , ∂ y ∂ x n ] \frac{\partial y}{\partial \mathbf{x}}=\left[\frac{\partial y}{\partial x_1}, \frac{\partial y}{\partial x_2}, \ldots, \frac{\partial y}{\partial x_n}\right] xy=[x1y,x2y,,xny]
在这里插入图片描述

  • ∂ Y ∂ x \frac{{\partial Y}}{{\partial x}} xY
    标量对向量的求导,结果还是列向量
    ∂ y ∂ x = [ ∂ y 1 ∂ x ∂ y 2 ∂ x ⋮ ∂ y m ∂ x ] \frac{\partial \mathbf{y}}{\partial x}=\left[\begin{array}{c} \frac{\partial y_1}{\partial x} \\ \frac{\partial y_2}{\partial x} \\ \vdots \\ \frac{\partial y_m}{\partial x} \end{array}\right] xy= xy1xy2xym
  • ∂ Y ∂ X \frac{{\partial Y}}{{\partial X}} XY
    向量关于向量的求导,生成的是一个矩阵。
    ∂ y ∂ x = [ ∂ y 1 ∂ x ∂ y 2 ∂ x ⋮ ∂ y m ∂ x ] = [ ∂ y 1 ∂ x 1 , ∂ y 1 ∂ x 2 , … , ∂ y 1 ∂ x n ∂ y 2 ∂ x 1 , ∂ y 2 ∂ x 2 , … , ∂ y 2 ∂ x n ⋮ ∂ y m ∂ x 1 , ∂ y m ∂ x 2 , … , ∂ y m ∂ x n ] \frac{\partial \mathbf{y}}{\partial \mathbf{x}}=\left[\begin{array}{c} \frac{\partial y_1}{\partial \mathbf{x}} \\ \frac{\partial y_2}{\partial \mathbf{x}} \\ \vdots \\ \frac{\partial y_m}{\partial \mathbf{x}} \end{array}\right]=\left[\begin{array}{c} \frac{\partial y_1}{\partial x_1}, \frac{\partial y_1}{\partial x_2}, \ldots, \frac{\partial y_1}{\partial x_n} \\ \frac{\partial y_2}{\partial x_1}, \frac{\partial y_2}{\partial x_2}, \ldots, \frac{\partial y_2}{\partial x_n} \\ \vdots \\ \frac{\partial y_m}{\partial x_1}, \frac{\partial y_m}{\partial x_2}, \ldots, \frac{\partial y_m}{\partial x_n} \end{array}\right] xy= xy1xy2xym = x1y1,x2y1,,xny1x1y2,x2y2,,xny2x1ym,x2ym,,xnym
    在这里插入图片描述

拓展到矩阵

在这里插入图片描述

也就是说,只要用向量或矩阵对标量、向量、矩阵进行求导,所用的向量或矩阵就需要进行转置。

自动求导

向量链式法则
∂ y ∂ x = ∂ y ∂ u ∂ u ∂ x ∂ y ∂ x = ∂ y ∂ u ∂ u ∂ x ∂ y ∂ x = ∂ y ∂ u ∂ u ∂ x \frac{\partial y}{\partial \mathbf{x}}=\frac{\partial y}{\partial u} \frac{\partial u}{\partial \mathbf{x}} \quad \frac{\partial y}{\partial \mathbf{x}}=\frac{\partial y}{\partial \mathbf{u}} \frac{\partial \mathbf{u}}{\partial \mathbf{x}} \quad \frac{\partial \mathbf{y}}{\partial \mathbf{x}}=\frac{\partial \mathbf{y}}{\partial \mathbf{u}} \frac{\partial \mathbf{u}}{\partial \mathbf{x}} xy=uyxuxy=uyxuxy=uyxu
与标量的链式法则一样
例子:
在这里插入图片描述
例子2:在这里插入图片描述

自动求导

计算图

将代码分解成操作子,将计算表示成一个无环图
在这里插入图片描述
自动求导的两种模式

链式法则:在这里插入图片描述
1)正向累积:在这里插入图片描述
先计算u1关于x的导数,再计算u2关于u1的导数,相乘后再继续一下部。
2)反向累积(反向传递):在这里插入图片描述
先计算最终的函数导数,依次计算最终函数与每一个中间值的导数,然后向前推进,最后求出最前面值的偏导。使用反向传递时,需要存放正向的所有中间结果。因此内存复杂度是 O ( n ) O(n) On,这也是为什么深度学习需要高性能大显存的GPU的原因。

自动求导代码

import torch

x = torch.arange(4.0)
x.requires_grad_(True)  # 等价于x=torch.arange(4.0,requires_grad=True)
x.grad  # 默认值是None
y = 2 * torch.dot(x, x)
y.backward()
x.grad == 4 * x

在这里插入图片描述

x.grad.zero_() #默认情况下 函数_表示重写,因为pytorch会累积梯度,因此我们需要清零
y = x.sum()
y.backward()
x.grad

非标量变量的反向传播
深度学习中非标量进行非标量求导比较少出现的情况。

# 对非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。
x.grad.zero_()
y = x * x
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad

在这里插入图片描述

将某些计算移动到记录的计算图之外

x.grad.zero_()
y = x * x
u = y.detach()  #表示将u与x脱离关系,u只是一个常量数值上等于x*x
z = u * x
z.sum().backward()
x.grad == u

在这里插入图片描述
Python控制流的梯度计算

def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c
a = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()
a.grad == d / a

在这里插入图片描述
f(a)函数它在其输入a中是分段线性的。 因此对于任何a,存在某个常量标量k,使得f(a)=k*a,其中k的值取决于输入a,因此可以用d/a验证梯度是否正确。

线性回归

在这里插入图片描述
  还是引入房价购买的例子,引出线性回归的内容。
  同样是目标(房屋价格)可以表示为特征(面积和房龄)的加权和。
1)用下列公式来表示:
p r i c e = w a r e a ⋅ a r e a + w a g e ⋅ a g e + b . \mathrm{price} = w_{\mathrm{area}} \cdot \mathrm{area} + w_{\mathrm{age}} \cdot \mathrm{age} + b. price=wareaarea+wageage+b.

2)机器学习领域表示:
y ^ = w 1 x 1 + . . . + w d x d + b . \hat{y} = w_1 x_1 + ... + w_d x_d + b. y^=w1x1+...+wdxd+b.
3)用矩阵-向量乘法表示:
y ^ = X w + b {\hat{\mathbf{y}}} = \mathbf{X} \mathbf{w} + b y^=Xw+b

线性模型可以看做是单层神经网络
在这里插入图片描述

衡量预估质量

  比较真实值和预估值,例如房屋售价和股价,假设y是真实值,
  平方损失函数: l ( y , y ^ ) = 1 2 ( y − y ^ ) 2 . l({y},\hat y) = \frac{1}{2} \left({y} -\hat y\right)^2. l(y,y^)=21(yy^)2.

训练数据

  收集一些数据点来决定参数值(权重和偏差),这些被称为训练数据,通常越多越好,假设有n个样本,记

X = [ x 1 , x 2 , . . . . . , x n ] T X = {[{x_{1,}}{x_{2,}}.....,{x_n}]^T} X=[x1,x2,.....,xn]T
Y = [ y 1 , y 2 , . . . . . , y n ] T Y = {[{y_1},{y_2},.....,{y_n}]^T} Y=[y1,y2,.....,yn]T

参数学习

     训练损失

      对于模型在每一个样本上的值求均值,就能得到损失函数。
L ( w , b ) = 1 n ∑ i = 1 n l ( i ) ( w , b ) = 1 n ∑ i = 1 n 1 2 ( w ⊤ x ( i ) + b − y ( i ) ) 2 . L(\mathbf{w}, b) =\frac{1}{n}\sum_{i=1}^n l^{(i)}(\mathbf{w}, b) =\frac{1}{n} \sum_{i=1}^n \frac{1}{2}\left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right)^2. L(w,b)=n1i=1nl(i)(w,b)=n1i=1n21(wx(i)+by(i))2.

    我们的目标是要使损失函数值最小,这样使的模型与真实值的误差最小,因   此就需要最小化损失来学习参数。  
w ∗ , b ∗ = argmin ⁡ w , b   L ( w , b ) . \mathbf{w}^*, b^* = \operatorname*{argmin}_{\mathbf{w}, b}\ L(\mathbf{w}, b). w,b=w,bargmin L(w,b).

显示解

将偏差加入权重,变成对应的X向量和W向量
ℓ ( X , y , w ) = 1 2 n ∥ y − X w ∥ 2 \ell(\mathbf{X}, \mathbf{y}, \mathbf{w})=\frac{1}{2 n}\|\mathbf{y}-\mathbf{X w}\|^2 (X,y,w)=2n1yXw2

然后对w求偏导
∂ ∂ w ℓ ( X , y , w ) = − 1 n ( y − X w ) T X \frac{\partial}{\partial \mathbf{w}} \ell(\mathbf{X}, \mathbf{y}, \mathbf{w})=-\frac{1}{n}(\mathbf{y}-\mathbf{X w})^T \mathbf{X} w(X,y,w)=n1(yXw)TX

最优解是满足以下三个条件
∂ ∂ w ℓ ( X , y , w ) = 0 \frac{\partial}{\partial \mathbf{w}} \ell(\mathbf{X}, \mathbf{y}, \mathbf{w})=0 w(X,y,w)=0
根据函数图像得,是凸函数,最优解是满足梯度等于0

1 n ( y − X w ) T X = 0 \frac{1}{n}(\mathbf{y}-\mathbf{X w})^T \mathbf{X}=0 n1(yXw)TX=0
w ∗ = ( X T X ) − 1 X y \mathbf{w}^*=\left(\mathbf{X}^T \mathbf{X}\right)^{-1} \mathbf{X} \mathbf{y} w=(XTX)1Xy

梯度下降

当没有显示解的时候,就需要用梯度下降的方法来找到对应的解,使损失函数最小化。
在这里插入图片描述
学习率 η η η不能太大也不能太小
在实际过程中,很少使用梯度下降,深度学习中,最常见的是使用小批量随机梯度下降。是因为在使用梯度下降时,要对整个训练集上的损失函数进行求导。而损失函数是对整个样本而言的平均损失。因此计算的求导的话,代价运算代价是非常高的。
因此可以随机采样B个样本来近似损失。
1 b ∑ i ∈ I b t R ( x i , y i , w ) \frac{1}{b} \sum_{i \in I_b} t^{\mathbb{R}}\left(\mathbf{x}_i, y_i, \mathbf{w}\right) b1iIbtR(xi,yi,w)
b是批量大小,又是另外一个重要超参数,和学习率一样,同样不能大小,不适合并行来最大利用计算资源。也不能太大,内存消耗太大。

%matplotlib inline  #嵌入到matplotlib里面
import random
import torch
from d2l import torch as d2l  #导入d2l,存放平常使用的函数

据带有噪声的线性模型构造一个人造数据集

def synthetic_data(w, b, num_examples):  #@save
    """生成y=Xw+b+噪声"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))
    
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

输出样本
在这里插入图片描述

d2l.set_figsize()
d2l.plt.scatter(features[:, (1)].detach().numpy(),   labels.detach().numpy(), 1); #特征第一列

样本
                                             样本散点图
接下来我们要每次读取一个小批量样本,打乱样本下标

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] #生成器,每次得到一个随机的特征值和下标
        batch_size = 10

for X, y in data_iter(batch_size, features, labels):
    print(X, '\n', y)
    break

输出结果为:
在这里插入图片描述
自此人造数据集初始化完成。

定义初始化模型参数

w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)  #偏差

要计算线性模型的输出,只需计算输入特征 X \mathbf{X} X和模型权重 w \mathbf{w} w的矩阵-向量乘法后加上偏置 b b b

def linreg(X, w, b):  #@save
    """线性回归模型"""
    return torch.matmul(X, w) + b

定义损失函数

def squared_loss(y_hat, y): 
 #均方误差
      return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
      #一个可能是行向量一个可能是列向量,因此还是同一格式

定义优化算法

def sgd(params, lr, batch_size): 
 # 小批量随机梯度下降
    with torch.no_grad():  #先不需要计算梯度
        for param in params:
            param -= lr * param.grad / batch_size #因为在损失函数定义时,没有进行除以均值,因此在梯度计算的时候除。
            param.grad.zero_()  #因为pytorch会不断累加变量的梯度,因此每更新一次参数,就要让其对应梯度清零

训练过程

lr = 0.03
num_epochs = 3   #声明超参数  学习率η和随机率b
net = linreg
loss = squared_loss
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}')

在这里插入图片描述
因此看到结果,三遍过后,损失已经非常小了。因为我们使用的是自己合成的数据集,所以我们知道真正的参数是什么。 因此,我们可以通过[比较真实参数和通过训练学到的参数来评估训练的成功程度]。 事实上,真实参数和通过训练学到的参数确实非常接近。

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

在这里插入图片描述

总结

本周在实现线性回归实验时,发现在pytorch上面存在基础问题,跟不上网课的节奏,需要下来并行学习python的内容,以及相关深度学习方面常用的库函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值