1.环境搭建以及前置条件
-
1.前置环境:
-
1.mac
-
2.pycharm
-
3.python3
-
4.Anaconda
-
2.环境搭建:
-
1.官网下载并安装Anaconda
-
2.官网下载并安装pycharm
-
3.在pycharm中使用Anaconda
-
1.preference-->project-->project interpreter
-
2.将Anaconda的解释器当做一个project interpreter添加
-
4.下载assignment1作业项目并导入pycharm中,
作业下载
。
-
5.下载数据集并解压到assignment1作业项目的 assignment1/cs231n/datasets/中。
数据集下载
-
6.执行数据集中的.sh文件使得数据集可用
-
3.前置知识:numpy、python、SciPy基础学习,
教程
2.SVM知识了解
假设我们有一个训练图片集
10000*3072
,也就是10000张像素为3072的图片,有一个测试图片集的图片
100*3072
,测试和训练图片集总共的图片类型有10种(这里图片类型指的是图片内容的类型,如:图片内容为猫、狗等)。我们将某一张训练图片命名为
Tn
,将一张测试图片命名为
Cm
,将一个图片的类型命名为
La
。
1.SVM是什么
-
1.我们定义一个函数为
f(Cm,W)=W*Cm
,在这里W为一个
3072*10
的矩阵。最终这个函数的结果是一个大小为10的数组,这里数组中的每个数字就是
Cm
这张图片在每个
La
下的得分,分数最高的
La
就表示我们预测这张测试图片是这种图片类型。
-
2.从1中我们可以知道要让我们的预测准确率高,那么
W
就需要找准。我们有很多方法来寻找一个好的
W
-
1.随机法:不断随机生成W,然后计算准确率,最终试出符合要求的
W
,但是很明显这种方式效率很低
-
2.SVM:我们可以先随机初始化一个
W
,此时可以算出准确率为
z1
。此时我们可以尝试小幅度修改(整体加一个数或者减一个数)
W
中的某一行数据,然后再计算准确率
z2
。如果
z1
小于
z2
,那么表示我们修改对了,可以继续这样修改,否则我们需要往反方向修改。以上就是SVM的基本思想。
如果把寻找一个最佳的W比作在一座山中寻找最低点的话,那么SVM就是不断尝试沿着下降的路向前走,一直走到山谷最低点。
2.SVM具体实现
我们在1中说了SVM算法的基本思想,但是我们也可以从中发现一些问题。1.每次要通过计算最终的准确率才能知道当前的
W
是否变好了,这样效率太低了。2.修改
W
的时候我们只是在尝试,如果能知道当前具体的下降趋势是不是速度就更快了呢?接下来的一节我们就会解决上面的问题。
-
1.损失函数:为了解决上面说到的第一个问题,我们就定义了一个损失函数来评价当前的
W
的好坏。
-
1.公式:
-
2.解释:
-
1.我们都知道
f(Cm,W)
的结果会是一个大小为10的数组,这个数组的下标表示的是
La
数组中某个图片类型的下标,那么我们就可以将这个数组比作:
在W下Tm这张训练图片,在每个图片类型下面的得分
。我们这里讲这个得分数组设为
S[10]
-
2.我们都知道每个
Tn
都会有一个正确的图片类型
La
我们设为
LaM
,那么此时对于
Tn
我们就有衡量这个
W
是否标准的方法了,用每个
S
减去
LaM
(除了
LaM
本身)再加上一个
x
(这里的
x
是一个自定义的数字,可以是1,2等等,这个
x
是一个阈值,表示
LaM
的分数到底超过其他
S
多少才算可以接受),最后将每个的结果求和这样就可以得出一个数字
Ls
。
这里的Ls就是Tn对于W的评价,Ls越大就表示,对于Tn来说这个W越不好,还有一个限制是0<=Ls,当Ls小于0的时候表示这个W对Tn来说已经够好了,所以小于0的Ls都算作0
,到这里就是图片中公式
Li的解释
-
3.我们在上面算出了一个
Tn
对于
W
的评价
Ls
,但是光有这一个样本太少了,我们需要让很多的
Tn
对
W
进行评价得出大量的
Ls
,然后去平均值,此时就能得出当前图片训练集对于这个
W
的评价,到这就是图片中公式
L
的解释。
-
4.我们能看见公式中最后还有一个直接定义的项,这个一项被称为
正则项
。大家可以想想,我们前面获取的评价
LsM
是基于训练图片集的,但是我们正在需要进行预测的是测试图片集。那么此时就会有个问题
我们的W只对训练图片集的预测正确率高,对测试图片集的预测正确率很低,这个现象就被称为————过拟合
,那么我们如何解决这个问题呢?这就要
正则项
出马了
,这几个公式就是常用的
正则项
,我们直接拿来使用就好了。
-
2.优化函数:为了解决上面提出的第二个问题,我们可以定义一个优化函数,来不断的根据趋势优化我们的
W
-
1.我们首先需要获取到当前
W
朝着好的方向前进的趋势,这里就要用上前面定义的
损失函数了
,因为损失函数是关于
Wj和Wi的函数
,也就是说这两个参数影响着
损失函数
的走向,而
损失函数
的结果就表示当前
W
的好坏程度。如果你知道
偏导数
的话就可以知道算出
损失函数对于Wj和Wi的偏导数dW
就是的
W
当前的趋势。所以便有了这个公式:
-
2.我们得到了
dW
之后,优化的公式就出来了,我们需要不断更改
W
使得
损失函数
的结果向0靠近,所以优化函数是这样的:
,注意这里还有一个参数
learning_rate
被称为
学习率
,这个
学习率就表示我们在通往山谷的路上迈的步子有多的大,如果太大的话就越过山谷到另一边山坡去了,如果太小我们下降的又太慢,所以这是一个超参数,需要我们多试试找到最优结果
。
-
3.随机梯度下降法:我们现在已经有了
优化函数
和
损失函数
,但是我们会发现每一次进行
W
优化的时候,都要遍历一整个图片训练集,这样效率就会很低,所以我们可以每次训练取一小部分,图片训练集,然后进行训练,这样的话效率就会比较高。
一般来说,取的数字都是2的幂
2.SVM代码实现
1.我的项目
-
1.先上一个github吧,会持续更新直到把cs231n课程学习完:
cs231n
-
2.我的项目目录:
2.代码分析
-
1.
建议结合github代码食用
,前面6行就不说了,我在上一篇博客中分析过,就是导入模块,然后从文件中读取数据:
cs231n之KNN算法
,只要看里面的第二节代码解析的前两个小结就行了。
-
2.定义了:
-
1.
num_training
:全体训练集数量(
num_dev
会从其中抽取一定数量的图片用于训练,减少训练时间)
-
2.
num_validation
:验证集数量(在不同的
学习率和正则参数
下使用该验证集获取最高的正确率,最终找到最好的
学习率和正则参数
)
-
3.
num_test
:测试集数量(在获取到最好的
学习率和正则参数
之后,测试最终的正确率)
-
4.
num_dev
:随机训练集数量(用于实现
随机化梯度下降的
)。
-
3.接下来三行是从训练数据
x_train和y_train
中获取
验证集数据
-
4.接下来三行是从训练数据
x_train和y_train
中获取
全体训练集数据
-
5.接下来三行是从
num_training
中随机选取
随机训练集数据
-
6.接下来四行表示:将
x_train,x_val,x_test,x_dev
这些
n*32*32*3
的图片集,转化成
n*3072
的矩阵。简单来说就是将每张图片拉伸成一维的矩阵,方便后面进行数据处理。
-
7.接下来五行表示:将
x_train,x_val,x_test,x_dev
这些图片集进行
去均值处理
,简单来说就是计算出
x_train
全体图片的均值,然后让其他图片集的每张图片邱减去这个均值。
这样的好处是统一量纲,和归一化操作类似,只是没有再除以方差而已
-
8.接下来两行定义了一系列
学习率和正则参数
,在后面会使用两层循环找到最高正确率下的
学习率和正则参数
。
-
9.接下来三行定义了:每个
学习率和正则参数
下的正确率键值对
results
,最高的正确率
best_val
,最高正确率下的
SVM对象
后面可以之间对测试集进行预测。
-
10.进入了两层循环,被循环测参数分别是
学习率和正则参数
-
1.在某个
学习率和正则参数
下,我们创建了一个
SVM对象
,然后将
学习率和正则参数
、训练集
x_train和y_train
、W需要迭代的次数
num_iters
,传入训练方法中。
-
1.我们进入了训练
W
的代码中,先是获取了训练集图片数量
num_train
,图片种类数量
num_classes
。然后随机初始化了
W
。
-
2.定义一个
loss_history
用于储存每次迭代的损失值
-
3.进入一个循环,被循环的参数是
num_iters
,也就是前面说的
W
需要迭代的次数
-
1.从训练集
x_train和y_train
中再取出
batch_size
数量的数据集,再次减少训练时间。
-
2.将再次减少的训练集
X_batch和y_batch
还有
正则参数reg
传入
loss()
方法中以获取损失值
loss
和
W
的趋势
grad,也就是dW
。
-
1.有两种方式来计算损失值
loss
和
W
的趋势
dW
,我这里选择简单的方式。
-
2.先定义了一个与
W
同矩阵大小的
dW
,获取了训练集图片数量和图片种类数量
num_train和num_classes
-
3.初始化
loss为0
-
4.进入循环,循环参数是训练集图片数量
num_train
-
1.计算当前
W
和当前训练图片
X[i]
在各个图片种类下的分数
scores
-
2.获得当前训练图片
X[i]
真实图片种类的分数
correct_class_score
-
3.进入循环,循环参数是图片种类数量
num_classes
-
1.如果当前的图片种类
j
,就是当前训练图片
X[i]
真实的图片种类
y[i]
,那么由前面损失函数的定义可知,我们不需要继续执行
-
2.如果1不成立,我们就能计算出对于当前训练图片
X[i]
,在图片种类
j
下的损失分量
margin
。
-
3.由前面损失函数的定义可知
loss
只需要大于0的
margin
,所以如果
margin
小于0,那么就当0处理,接下来就没必要继续了。
-
4.如果
margin
大于0,那么为
loss
加上
margin
,并且给
dW[,j]和dw[,y[i]]
都加上公式:
对
Wj和Wyi
求过偏导数之后的
X[i]和-X[i]
-
5.退出两层循环,此时计算出了全部训练图片的
dW和loss
之和,所以
dW和loss
需要除以
num_train
,再为
loss和dW
加上正则项。
-
6.返回
dW和loss
-
3.获得了
loss
和
W
的趋势
grad,也就是dW
之后,将本次
loss
储存在了
loss_history
中
-
4.根据公式:
,对
W
进行优化
-
5.这样一直循环直至迭代次数
num_iters
完成
-
4.
W
的循环迭代结束之后,返回上一层
-
2.在当前
学习率和正则参数
下,将
W
训练完毕之后,分别使用
x_train和x_val
来进行预测并算出准确率
train_accuracy和val_accuracy
。
-
3.一直循环上面的操作,直至找到最大的正确率下的
best_svm和best_val
,并将历次的
train_accuracy,val_accuracy
储存在
results
中。
-
4.结束两层循环
-
11.输出10中历次循环的
train_accuracy,val_accuracy
与
学习率和正则参数
-
12.使用上面找到的最佳的
best_svm
来预测
测试集x_test
得到了
测试集
的准确率
test_accuracy
并输出
-
13.获取最佳的
best_svm
中的
W
,将其重新转化为
n*32*32*3
,然后以图片形式输出。
3.结果
-
1.训练过程中在不同
学习率和正则参数
下训练好模型后,
验证集和训练集
进行预测的准确率:
-
2.最终
测试集
的准确率:
-
3.
W
最终学习成的图片:可以看出车子的图片还是有一点大概的模型存在的。
4.不同损失函数的SoftMax算法
我们前面做的了
Svm
算法就是不断根据损失函数对于
Wi
和
Wj
这两个分量的偏导数来优化
W
的算法。这里的损失函数定义了
W
的好坏,如果我们换一个损失函数的定义方式,会不会有不一样的结果呢?我们接下来要讲的就是另一种损失函数的算法
SoftMax
-
1.损失函数:
-
1.解释:这里的
Li
公式我们只要看
Log
里面的东西就好了,这里的
j
表示某一个图片种类,
yi
表示该训练图片的真实种类,所以里面的东西就很好理解了,
即该训练图片真实种类的分数在总的分数中的占比
。最后Log内部算出的会是一个百分比,所以使用
Log
将其转化一下。
-
2.当然最终的
损失函数L
,还需要算所有
Li
的均值
-
2.损失函数的梯度,这里就是对
Wj
和
Wyi
算偏导:
-
3.以上就是
SoftMax和Svm
的全部不同,所以只需要更换一下公式的代码就可以了。
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:
https://cloud.tencent.com/developer/support-plan?invite_code=pe24xbp4axut