机器学习快速入门之手写体数字识别
什么是机器学习
机器学习就是让计算机来学习,学习如何识别图片、学习如何识别语音,学习的成果就是所谓的模型,学习的方式有很多种,目前主流的就是神经网络,或者叫深度学习。
一、什么是模型?
所谓模型,其实就一个函数,比如y=wx+b,在数学中,w和b是常量,x和y是变量,y会随着x的变化而变化,但是在神经网络或深度学习中,却应该反过来理解,x和y是已知的样本数据,w和b是未知的参数。
举个例子来模拟深度学习的过程,假如现在我有一批苹果的数据,x表示苹果的重量,y表示苹果的价格,那么我现在有三个苹果的数据为:
- x=1,y=10
- x=2,y=15
- x=3,y=18
首先假设w=1,b=1,那么此时的函数为y=x+1,将1号样本的x带入函数,得出的y=1+1=2,很明显和实际的y=10之间存在巨大的误差,如何缩小误差呢,调整w和b的值,这个过程其实是根据误差反向修改w和b的值,在神经网络中叫做反向传播,而修改w可以:w=w+误差,所以新的w=1+(10-2)=9。
此时,w=9,b=1,然后将2号样本的x带入函数y=9x+1,得出的y=9*2+1=19,和实际的y=15之间也存在误差,用同样的方法修改w=9+(15-19)=5。
此时,w=5,b=1,然后将3号样本的x带入函数y=5x+1,得出的y=5*3+1=16,和实际的y=18之间也存在误差,用同样的方法修改w=5+(18-16)=7。
此时,w=7,b=1,最终得到的函数为y=7x+1。
这个例子只是想表达出深度学习的过程,真实的过程复杂多了。
总结一下深度学习就是:通过样本数据,不断的修改函数的w和b的值,从而得到一个理想函数,这个理想函数能使得样本数据中x通过该函数计算后得到y与样本中的y之间的误差最小。
如果一个函数能使得对于样本数据的误差很小,那么这个函数就算是训练成功了,就可以用来预测原本不在样本集中的数据了。
而这个函数就是所谓的模型,w和b就是模型的参数,所以所谓的大模型,就是一个很复杂的函数,训练它的样本集很大、参数很多。
像图片、文字、人,其实都可以用数字来表示,从而用来计算,比如图片是由很多像素组成的,而每个像素其实就是一个RGB,比如(255,255,255),所以一张图片就是一个二维数组,而样本就可以是:
- 二维数组1,对应一个猫
- 二维数组2,对应一个人
- 二维数组3,对应一辆车
这就是图片的样本集,x是二维数组,y是对应的结果,当然结果,也就是猫、人、车也可以用数字来表示。
有了样本集,就同样可以用来进行函数计算,只不过是矩阵计算了,但原理是一样的,最终也是训练出来w和b,得到最终训练出来的函数后,就可以用它来识别图片了,只不过在识别之前也需要把图片转变为二维数组,将这个二维数组作为x输入给函数,函数最终告诉你这个图片的识别结果,所以如果你的样本中没有出现过猫,那么你训练出来的模型也不能认识猫。
如何定义模型
模型就是函数,所以定义模型就是定义函数,定义函数有哪些入参,比如假如有三个入参,那么函数为y=w1x1+w2 x2+w3x3+b,换成矩阵的形式就是Y=WX+B,W和B表示模型的参数,可以是任意维度,比如100100,1000*1000,X表示模型的入参,模型训练时就是样本的特征维度,比如一个苹果的特征有大小、颜色、地区,三个特征,也就表示三个维度,输入一个苹果给模型,就是把一个苹果的三个特征输入给模型,模型预测出苹果的价格,价格就为模型的输出。
我们看以下代码:
java
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(784, 200)
self.fc2 = nn.Linear(200, 200)
self.fc3 = nn.Linear(200, 200)
self.fc4 = nn.Linear(200, 10)
def forward(self, x):
x = x.view(-1, 784) # 展平图像为一维向量
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = torch.relu(self.fc3(x))
x = self.fc4(x)
return x
虽然是python代码,但是也可以按Java来理解,Net表示一个模型对象,__init__方法表示模型的构造方法,构造方法里表示了模型对应的函数构造,比如:
- fc1:表示一个线性层,一个线性层里可以包含多个线程函数,就是我们上面说的y=wx+b这种形式,784表示每个线性函数的入参,也就表示该模型接收的样本的特征有784个,是什么样本有这么多特征呢?是一张2828的图片,一张图片的像素个数就是特征维度,每个像素的颜色值不一样,200表示线性函数的个数,也就是说一张图片需要分别输入给200个线性函数,最终得出200个结果,为了200个结果不一样,那么每个线性函数的w参数值肯定就不一样了,另外再加上200个偏置b参数,所以fc1层就784200+200=157000个参数
- fc2:表示也表示200个线程函数,入参个数也是200个,200个偏置,总参数为40200个
- fc3:同fc2
- fc4:只有10个线性函数,入参个数为200,为什么fc4只有10个线性函数呢?因为这个模型是用来预测图片中的数字的,0-9,所以最后的10个线性函数分别对应了0-9,并且函数结果为输入图片为对应数字的概率,我们只要取概率值最大的结果作为图片最终的预测结果就可以了,所以参数个数为,10*200+10=2010
总参数个数为:157000+40200+40200+2010=239410
当然,在模型训练过程中,一开始的预测结果肯定不对,所以需要不断的进行反向传播,也就是根据误差修改各个参数的值,使得模型最终能预测正确。
如何训练模型
训练模型的核心是准备训练数据,训练数据包含问题和正确答案,比如一张图片和对应的正确数字,准备很多这种数据对,就可以将这些数据输入给模型进行训练了,而模型的训练过程就是先得到预测结果,然后和正确答案做比较,计算出误差,然后根据误差调整参数,循环往复,得到最适合的参数,模型也就训练成功了。
目前也有很多开源的数据集,比如
https://modelscope.cn/datasets
https://huggingface.co/datasets/mnist
模型训练出来之后,就是一个文件,model.pth
如何调用模型
调用模型就是加载模型文件,然后进行推理就可以了
Conda安装和使用
安装Python
建议使用Conda来安装Python,因为Conda可以管理Python版本,隔离不同的Python环境。
下载和安装
根据操作系统选择安装包
常用Conda命令
创建一个Python环境:
java
conda create -n playwright python=3.8
上面命令创建了一个python3.8的环境,名字叫做playwright,执行命令之后需要确认是否安装一些默认依赖,输入y确认即可
下载完之后
激活环境
执行以下命令激活使用某个环境,以下命令表示使用playwright环境
java
conda activate playwright
激活成功后,命令行前面会显示当前环境名
这样,在当前环境中下载的以来将只属于当前环境,如果退出环境或切换到其他环境则不再能使用到其他环境中的依赖。
退出环境
java
conda deactivate