课程主页http://cs231n.stanford.edu/index.html
图像分类中的任务是预测给定图像的单个标签(或此处显示的标签分布以指示我们的置信度)。图像是从 0 到 255 的整数的 3 维数组,大小为 Width x Height x 3。3 代表红、绿、蓝三个颜色通道。
图像分类的过程

Nearest Neighbor Classifier 最近邻算法
使用的数据集CIFAR-10 链接:https://www.cs.toronto.edu/~kriz/cifar.html
10类数据 60000张图(32*32) 50000张训练集 10000张测试集

省略了训练的过程,直接开始进行分类预测,所以是惰性算法
步骤:将test的图片与训练集中每一张图进行比较,寻找最相似的图,那么认定test的label就和这张图一致
具体比较方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wo9hJAkw-1661612359098)(https://myblogimgbed.oss-cn-shenzhen.aliyuncs.com/img/7028e365700d8a06aa7b42dc50d3b9c2.svg)]

将test image与training image的每一个像素(pixel 32323)进行相减取绝对值,然后把所有结果求和,最终结果越小表明越相似

KNN是在NN基础上,寻找最相似的k个图片的标签,然后进行投票,把票数最高的标签作为测试图片的预测。
更高的k值可以使分类效果更平滑,使得分类器对于异常值更有抵抗力。

超参数 Hyperparameter:在机器学习的上下文中,超参数是在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据。 通常情况下,需要对超参数进行优化,给学习机选择一组最优超参数,以提高学习的性能和效果。
过拟合:模型对于训练集表现特别好,但是对测试集表现很差
测试数据集只使用一次,即在训练完成后评价最终的模型时使用。
在训练时是不可以使用测试集进行训练的,否则很可能发生过拟合,因此引出验证集(validation set)
两种设置验证集的方法
选择:一般直接把训练集按照50%-90%的比例分成训练集和验证集。但这也是根据具体情况来定的:如果超参数数量多,你可能就想用更大的验证集,而验证集的数量不够,那么最好还是用交叉验证吧。至于分成几份比较好,一般都是分成3、5和10份。



重要:一般是神经网络的第一个处理模块
线性分类器本质上是高效使用KNN
与KNN的本质区别:在评估的过程中其实也是将test image与训练集进行比较,但线性分类器不是把所有训练集一一比较一遍,而是事先得到K类的模板原型image,比较这K类的评分高低,来判断属于哪一类。

(10类原型)
评分函数(score function),它是原始图像数据到类别分值的映射。
损失函数(loss function),它是用来量化预测分类标签的得分与真实标签之间一致性的。该方法可转化为一个最优化问题,在最优化过程中,将通过更新评分函数的参数来最小化损失函数值。

线性分类器:线性映射

训练过程的实质就是训练出最优的W和b使得损失函数最小


W的每一行都是一个分类类别的分类器。对于这些数字的几何解释是:如果改变其中一行的数字,会看见分类器在空间中对应的直线开始向着不同方向旋转。而偏差b,则允许分类器对应的直线平移。需要注意的是,如果没有偏差,无论权重如何,在[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传xi=0时分类分值始终为0。这样所有分类器的线都不得不穿过原点。
一般常用的方法是把两个参数放到同一个矩阵中,同时x向量就要增加一个维度,这个维度的数值是常量1,这就是默认的偏差维度。这样新的公式就简化成下面这样:


有时也叫代价函数Cost Function或目标函数Objective

多类支持向量机损失 Multiclass Support Vector Machine Loss

计算实例:
yi = 青蛙
s [cat,car,frog] = [2.2 2.5 -3.1]

折叶损失(铰链损失)


平方折叶损失SVM(即L2-SVM)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ei8BjnaR-1661612359118)(https://myblogimgbed.oss-cn-shenzhen.aliyuncs.com/img/1658320996936-2adb9d55-3c17-4e4e-91cd-fc13f2ed46a8.svg)]
一个SVM的交互式demohttp://vision.stanford.edu/teaching/cs231n-demos/linear-classify/

使用交叉熵损失(cross-entropy loss) 替代hinge loss


取-log()的原因:
区分与SVM的不同:

最优化是寻找能使得损失函数值最小化的参数W的过程。
优化的实质是将求损失函数对每个权重的梯度,不断调整权重,使得对于该权重,梯度下降到最低。
梯度的下降指的是使得损失函数下降(往更准确的方向),
最优化的策略
在一次函数是斜率,在多维度指的是各个维度的斜率组成的向量(或导数)
当函数有多个参数的时候,我们称导数为偏导数。而梯度就是在每个维度上偏导数所形成的向量。
指明了沿梯度方向的变化幅度,更新快慢
小步长下降稳定但进度慢,大步长进展快但是风险更大。采取大步长可能导致错过最优点,让损失值上升。


其实就是高中的复合函数求导

# 设置输入值
x = -2; y = 5; z = -4
# 进行前向传播
q = x + y # q becomes 3
f = q * z # f becomes -12
# 进行反向传播:
# 首先回传到 f = q * z
dfdz = q # df/dz = q, 所以关于z的梯度是3
dfdq = z # df/dq = z, 所以关于q的梯度是-4
# 现在回传到q = x + y
dfdx = 1.0 * dfdq # dq/dx = 1. 这里的乘法是因为链式法则
dfdy = 1.0 * dfdq # dq/dy = 1



矩阵求梯度时注意转置
# 前向传播
W = np.random.randn(5, 10)
X = np.random.randn(10, 3)
D = W.dot(X)
# 假设我们得到了D的梯度
dD = np.random.randn(*D.shape) # 和D一样的尺寸
dW = dD.dot(X.T) #.T就是对矩阵进行转置
dX = W.T.dot(dD)
*要分析维度!*注意不需要去记忆dW和dX的表达,因为它们很容易通过维度推导出来。例如,权重的梯度dW的尺寸肯定和权重矩阵W的尺寸是一样的,而这又是由X和dD的矩阵乘法决定的(在上面的例子中X和W都是数字不是矩阵)。总有一个方式是能够让维度之间能够对的上的。例如,X的尺寸是[10x3],dD的尺寸是[5x3],如果你想要dW和W的尺寸是[5x10],那就要dD.dot(X.T)。

一个单独的神经元
只要在输出端有一个合适的损失函数(Softmax分类器的交叉熵损失或者二分类SVM分类器的折叶损失),就可以使一个单独的神经元变成一个二分类器
激活函数是在神经网络层间输入与输出之间的一种函数变换,目的是为了加入非线性因素,增强模型的表达能力。
作用:为神经网络带来非线性,去掉激活函数,不管有多少层网络都是线性的

最普通的层的类型是全连接层(fully-connected layer)。全连接层中的神经元与其前后两层的神经元是完全成对连接的,但是在同一个全连接层内的神经元之间没有连接。

网络尺寸:用来度量神经网络的尺寸的标准主要有两个:一个是神经元的个数,另一个是参数的个数,用上面图示的两个网络举例:
现代卷积神经网络能包含约1亿个参数,可由10-20层构成(这就是深度学习)。
根据上图右侧,可得到如下计算
# 一个3层神经网络的前向传播:
f = lambda x: 1.0/(1.0 + np.exp(-x)) # 激活函数(用的sigmoid)
x = np.random.randn(3, 1) # 含3个数字的随机输入向量(3x1)
h1 = f(np.dot(W1, x) + b1) # 计算第一个隐层的激活数据(4x1)
h2 = f(np.dot(W2, h1) + b2) # 计算第二个隐层的激活数据(4x1)
out = np.dot(W3, h2) + b3 # 神经元输出(1x1)
全连接层的前向传播一般就是先进行一个矩阵乘法,然后加上偏置并运用激活函数。
在数学证明上,无论多少隐层,都可以由一个隐层(更多神经元)表示,但是就实践经验而言,深度网络效果比单层网络好。
增加神经元可能会导致过拟合

但是不要因为怕过拟合就使用小网络
不要减少网络神经元数目的主要原因在于小网络更难使用梯度下降等局部方法来进行训练:虽然小型网络的损失函数的局部极小值更少,也比较容易收敛到这些局部极小值,但是这些最小值一般都很差,损失值很高。相反,大网络拥有更多的局部极小值,但就实际损失值来看,这些局部极小值表现更好,损失更小。
解决过拟合方法:L2正则化,dropout和输入噪音等

正则化强度增加可以使决策边界变得更加平滑。
结构:

底层特征容易解释,越到高层越复杂不可解释

感受野
卷积核:把原图中符合卷积核特征的特征提取出来

Feature map 与卷积核一一对应

补0操作:padding

步长

一个卷积核的维度必须与前一层的通道数一致

卷积后的特征图大小
(N+2P-F)/stride + 1


作用

多层感知器
进行模型的汇总





ZFnet论文



可以找到对该类别敏感的像素
从而实现了定位的功能





零对称

不消耗啥计算资源
收敛很快

死神经元
原因:初始化不良或学习率太大
优化:Leaky ReLu

三个常用的符号:数据矩阵X,假设其尺寸是[N x D](N是数据样本的数量,D是数据的维度)
对数据中每个独立特征减去平均值,从几何上可以理解为在每个维度上都将数据云的中心都迁移到原点。
在numpy中,该操作可以通过代码**X -= np.mean(X, axis=0)**实现。而对于图像,更常用的是对所有像素都减去一个值,可以用**X -= np.mean(X)**实现,也可以在3个颜色通道上分别操作。
将数据的所有维度都归一化,使其数值范围都近似相等。
零中心化(zero-centered)处理
**X /= np.std(X, axis=0)**对每个维度都做归一化,使得每个维度的最大和最小值是1和-1。

先进行零中心化处理,再计算协方差矩阵,显示了各个维度的相关性
# 假设输入数据矩阵X的尺寸为[N x D]
X -= np.mean(X, axis = 0) # 对数据进行零中心化(重要)
cov = np.dot(X.T, X) / X.shape[0] # 得到数据的协方差矩阵
协方差矩阵:
PCA主成分分析 主要用于降维
U,S,V **=** np**.**linalg**.**svd(cov)
np.linalg.svd的一个良好性质是在它的返回值U中,特征向量是按照特征值的大小排列的。可以利用这个特性进行数据降维
Xrot **=** np**.**dot(X,U) *# 对数据去相关性*
Xrot_reduced **=** np**.**dot(X, U[:,:100]) *# Xrot_reduced 变成 [N x 100]*
白化
# 对数据进行白化操作:
# 除以特征值
Xwhite = Xrot / np.sqrt(S + 1e-5)

案例:


小随机数初始化 W = 0.01 * np.random.randn(D,H)randn函数是基于零均值和标准差的一个高斯分布

越往深层 xi输出值越来越接近0 出现梯度消失

初始化幅值过大 f`接近于0
Xavier初始化
保证了网络中所有神经元起始时有近似同样的输出分布


Kaiming初始化


我们希望中间结果都变得符合标准正态分布 可以保留梯度

批归一化就是强行进行归一化

有时强行转为正态分布不好 加入


注意:测试阶段的均值和方差是训练时的全局均值和全局方差



传统:SGD 随机梯度下降方法


几种优化器


容易被困在局部最优解

每次更新不止与当前梯度有关 还与之前的惯性/速度/动量有关


NAG比Momentum更加优化 提前考虑了一步 尽早感知到疲惫



在AdaGrad上进行优化 可以快一点收敛

第一动量 和 第二动量结合

初始化为0 要经过一段时间才能预热 进行优化 使得两个动量开始就有较高的初始值

二阶优化一般不采用 计算量过大
牛顿法:可以加快收敛速度

也叫做步长

可以一开始使用大学习率 后面使用小学习率
及早发现 及早停止

多个模型共同决定

同一模型不同时刻


随机掐死不同的神经元















对大的卷积核可以起到加速的作用,小的没啥用

加速矩阵乘法的方法:

借助预训练模型,站在巨人的肩膀上


优秀案例




CPU central processing unit
GPU graphics processing unit 图像运算
TPU Tensor

im2col:用矩阵运算加速卷积


读写内存耗能高
硬件
通用
专用


剪掉部分神经元 重新训练


把0附近的权重全都剪掉





把权重和激活值用更少的bit表示

使用1*1卷积去近似原矩阵




之前介绍的计算卷积的方法
滑窗
im2col
FFT
Winograd
类似FFT
用更多加法代替乘法




cpu的摩尔定律已经到了瓶颈 不能指望单线程核心 而应该采用更多核参与计算
数据并行

模型并行


计算梯度时用FP16,然后加到原来FP32的权重上
可以节省大量芯片面积
突出相似类别之间的关系



自动求梯度
加_表示原地操作


动态计算图

TensorFlow静态计算图

序列数据 NLP

一对一:多层感知器
一对多:图像描述 decoder
多对一:文本情感分析 文本分类 encoder
多对多


语言模型
三套权值都是时间权值共享


RNN是有记忆功能的 输入两次输出是不一样的 因为隐含层是可以对历史输入产生记忆的

计算量过大
截取小片段



普通RNN会产生梯度消失或者梯度爆炸


长期记忆



短期记忆
