002 Machine & Deep learning¶
本文简单描述机器学习和深度学习,让读者了解机器学习和深度学习的基本概念。 进一步的理论学习,可参考以下两位教授吴恩达及李宏毅教学资料,本文图片也引用课程资料。
什么是机器学习¶
- 人类学习 $y=f(x)$
- 人类学习所解决的问题是,已知 $x$,透过一个数学计算方程式(模型) $f$, 计算未知数 $y$ 的过程。
- 机器学习 $y=f(x)$
- 机器学习所解决的问题是,已知 $x$, $y$, 透过计算机迭代一个数学模型 $f$, 使 $f(x)$ 最接近 $y$的过程。
- 机器学习所解决的问题是,已知 $x$, $y$, 透过计算机迭代一个数学模型 $f$, 使 $f(x)$ 最接近 $y$的过程。
- 简言之,人类学习过程中学习推理出来的数学模型,利用已知数和数学模型“求解未知数”。而机器学习则是透过已知输入与输出,“寻找一个数学模型”,使这个模型能处理相似的问题。
以简单的线性方程式来表示,$y=b+w*x$,其中${x,y}$分别是模型训练所需要的训练资料集中已知的输入和输出,${b,w}$则为bias(偏差)和weighting(权重),以二维线性方程式的物理意义,bias控制着直线的高度位置,weighting控制着直线的斜率,模型训练的目的,在于找出一组${b,w}$使测试资料集的$x$经过模型的计算,所得到的$\hat{y}$最接近于测试资料集中$x$所对应的$y$。
机器如何学习(找出未知的方程式)¶
综上节所述,机器学习,需要具备以下条件:
- 已知的数据,通常称为training data,为了验证训练后模型是否可靠,通常会把已知的数据分为training data和test data两部分,第一部分用来训练模型,第二部分用来验证模型。
- 训练的模型及其参数,前述简单的线性方程式$y=b+w*x$,在模拟现实世界的问题时,会加上非线性函数,成为激活函数(activate function),使模型更能贴近生活中绝大部分非线性的状况。常用的非线性activate function有Sigmoid $f(x) = \frac{1} {1 + e^{-x}}$, ReLU $f(x) = max(0, x)$等。
- 定义损失函数(L, loss function),$L{(w, b)}$用来评估模型计算结果和已知结果的差异,整个训练的过程在于缩小损失函数的差异。假设模型为$y=b+w*x$,损失函数可以定义为 $L(b,w)=\frac{1}{N} \sum_{n=1}^{N} e_n$ 其中$e$代表模型计算的结果$y$和已知的结果$\hat{y}$的差异,可以表示为: $e = |{y-\hat{y}}|$, $L$ 为MAE(Mean Absolute Error) 或 $e = ({y-\hat{y}})^2$, $L$ 为MSE(Mean Square Error)。
- 训练迭代过程(Optimization),由于我们的目标是寻找Loss function的最小值,使得模型的计算结果最接近training和test data的已知结果,训练过程是先选择一个任意起始点(给定任意的$b$和$w$),将Loss function对不同的参数($b$ & $w$)分别做偏微分,如果选定的起始点$w_0$,使用梯度下降方法迭代求Loss function的最小值。需要注意的是,迭代步进的距离$\eta$通常为经验值或是训练过程测试出来,在某些模型,有可能步伐跨大了,错过了最优解(global minima),也有可能步伐跨小了,走不出局部低点(local minima),请参考以下图解及AI解释,帮助理解。
- 机器学习的流程如下图所示:
每一轮训练更新模型参数,用更新后的参数再进行下一轮,直到迭代出满意的模型(通过训练和测试数据),如果无法收敛,则需要修改模型设计并重新训练模型。
机器学习模型(贴近实际应用)¶
前面提到,简单的线性方程式不足以模拟实际案例,对于二元连续的曲线,我们需要结合多段的曲线来拟合实际的需求。
前述的线性方程式$y = b + w*x$ 会转换成如下的矩阵方程式,其中i为用来拟合的曲线数量,j为每条曲线的特征数量,叠加后的结果更接近机器学习适用的模型。
将模型的input $x$, bias $b$, weighting $w$ 和 activate function $sigmoid$ 用图形节点表示出来如下图。
当叠加更多层时,增加模型的参数变化,模型的拓扑图会如下图。
深度学习模型 (deep learning model)¶
模型可以叠加很多层,更多的层数增加了模型的复杂度,可以模拟更多的可能性,但不是层数越多越好,更复杂的模型,在训练过程有可能更容易出现过拟合(over fitting)的状况,当你发现模型可以在训练数据得到很好的结果,但是测试数据(模型没见过的)却得不到好的结果,有可能出现过拟合。基础的深度学习模型可以表示如下。
上图中,模型有连接输入数据的input layer,中间有几层的hidden layer, 最后有output layer再对应着输出值。 我们以一个16x16 pixel的数字手写图像辨识为例子,把图像pixel拉长,则输入层input layer是$x=[1,256]$的阵列,假设有2层的hidden layer, 则${hiddenLayer1} = {[256, n]}$的阵列, ${hiddenLayer2} = {[n, m]}$的阵列, 阵列的维度必须要符合矩阵相乘的限制,其中$n, m$的维度可以根据经验或测试来调整。在输出层,由于我们要预测的是手写数字,所以输出层可以设计为${outputLayer} = {[m, 10]}$, 代表着输出的结果可能会出现0~9这十个数字。 训练过程,将大量的手写图作为输入,根据输出的数值,假设softmax后的输出${output_layer} = {[0.2, 0.3, 0.1, 0.4, 0.3, 0.7, 0.3, 0.5, 0.6, 0.2]}$ 分别对应着数字$[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]$,则我们可以按照几率大小判断这次的运算,得到的答案是几率最大的0.7对应的数字5,这个过程称为feed-forward。由于这些训练数字是带有标记的(我们知道正确答案),但结果不对时,我们就需要对模型迭代,使用Gradient descent梯度下降方式,修改hidden layer的参数,这个过程称之为back-propagation。假设我们有1000张图,每一轮的输入10张(以这个例子,输入的图片数量)称之为batch size,而一个epoch代表的是跑完所有的图一次,模型的迭代次数为$1000/10 = 100$次。
建议¶
深度学习的模型原理如上几个章节描述,想要了解数学推导过程,建议参考本章开始提到的公开教学资料。深度学习的模型在实际应用上有各式各样不同的变体或组合,复杂程度也相应增加,幸运的是这些复杂的数学公式,在深度学习常用的代码包里面已经内置,例如pytorch, tensor flow...等。如果想要自己训练模型,最好一步一步学完理论基础,但知道本章中提到的关键词,对使用深度学习代码包会有更进一步的了解,也可以透过对框架的了解使用代码包内置的功能实现自己训练模型。
以下是由AI产生一段使用tensor flow训练及测试模型的代码。里面用到了minist是一个提供大量训练资料的网站,代码先将数据分成训练和测试两部分,分别对其做前处理,再定义模型,定义梯度下降的optimizer使用adam, 定义loss fuction, 进行5个epoch的训练,再用测试资料去评估模型,储存训练好的模型,前面这部分是训练模型过程,最后这两段示范读取模型并作预测是属于模型已经训练好之后的使用。
import tensorflow as tf
# Load the MNIST dataset
(x _train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# Pre process the data
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
# Define the model architecture
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax')
])
# Compile the model
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# Train the model
model.fit(x_train, y_train, epochs=5)
# Evaluate the model
model.evaluate(x_test, y_test)
# Save the model
model.save('my_model.h5')
# Load the model
new_model = tf.keras.models.load_model('my_model.h5')
# Make predictions
predictions = new_model.predict(x_test)