作者:人工智能课程
https://www.bilibili.com/read/cv8935813
出处: bilibili
本节将讲解机器学习基础,这也是深度学习最基础的内容。本节我们将使用Tensorflow的tf.keras这个高阶API实现一个简单的线性回归。
线性回归与机器学习基础
什么是机器学习呢?所谓机器学习,就是让计算机从数据中学习到规律,从而做出预测。很多时候,我们很难直接编写一个算法解决问题,比如一张图片,很难编写算法直接正确预测这张图是猫还是狗。为了解决这个问题,人们想到数据驱动方法,也就是让计算机从现有的大量的带标签图片中学习规律,一旦计算机学习到了其中的规律,当我们输入一张新的图片给计算机时,它就可以准确的预测出这张图片到底是猫还是狗。
这里有两个关键的因素,一是大量的可学习数据,比如带标签的猫狗图片;二是学习的主体,我们一般称之为模型。如何理解模型呢?你可以把模型认为是一个映射函数,它包含一些参数,这些参数可以与输入进行计算得到一个输出,我们一般称之为预测结果。比如我们输入一张图片到模型中,图片与模型参数计算得到一个映射结果,也就是预测结果。所谓模型学习的过程,就是模型修正其参数、改进映射关系的过程。
可以简单的把模型的学习过程总结如下,以预测图片是猫还是狗为例:
创建模型。
输入一张带标签的图片。
使用模型对此图片做出预测。
将预测结果与实际标签比较,产生的差距一般称之为损失。
以减小损失为优化目标,根据损失优化模型参数。
重复上述第2-5步。
下面我们用一个例子来演示创建模型、优化模型的整个过程。
受教育年限与收入预测模型
现在我们有一个个人受教育年限与平均收入之间对应关系的数据集。我们希望可以创建一个模型,当给定一个人的受教育年限时,这个模型能预测其收入。
首先,读取数据集,并观察数据。数据集在我们当前目录下的datasets文件中,这里我们使用pandas的read_csv方法读取:
import pandas as pd
data = pd.read_csv(’./datasets/Income.csv’)
data.head()
教育年限与收入数据
很明显,我们的数据有两列,分别是Education和Income,可以通过 data.info() 查看数据类型和整体情况:
数据详细信息
可以看出这个数据集是一个非常小的数据集,只有30行,并且Education和Income这两列的数据类型均为float64,我们可用先使用matplotlib绘图查看它们之间的关系,以便选择一个合适的模型:
import matplotlib.pyplot as plt
plt.scatter(data.Education, data.Income)
绘图输出
通过图像可以直观的查看Education和Income之间的关系,图中可以很明显的感觉到它们之间有一种线性关系,这样的话我们很容易想到可以使用一条直线来拟合它们之间的关系,也就是说,用一条直线来抽象Education和Income之间的对应关系,所以面对这个问题,我们就需要创建一个模型,这个模型就是一条直线,而这条直线能够拟合现有数据,帮助我们对未知数据作出预测。
既然模型就是一条直线,就可以把模型公式化,我们用 Y 代表Income,用 X 代表Education,这个模型就是如下的公式:
Y = w*X + b
公式中 w 代表斜率,一般称之为权重, b代表截距,一般称之为偏置。现在我们模型已经创建好,只要通过学习,得到 w 和 b 的值,这样,当需要预测的时候,给定一个人的Education年限,也就是公式中的 X 值, 带入模型公式中,就能直接计算出 Income,也就做出了预测。 那么如何确定出 w 和 b 值呢?
确定这两个值实际就是找出最拟合的直线。直观的感觉就是这条直线应该与现有的这些点越接近越好,因此可以使用这些点到拟合直线之间的距离的平方的均值作为拟合能力评价标准,这就是回归问题的常见损失函数————平方误差。 这里说到了损失函数,所谓损失函数主要用于计算模型预测与实际结果之间的差距,损失函数的返回值就是模型的损失,显然,模型的损失越小越好!这就给出了我们计算w和b的方法,我们只需要找到能使损失最小的w和b即可。当数据是不变的时候,也就是给定了训练数据,损失函数,也就是loss值,是由w和b决定的,我们可以公式化:
loss = f(w, b)
现在的问题就变成了寻找loss极值点的问题,我们只要找到合适的w和b使得loss取得最小值,这时候的w和b就是我们要找的最拟合直线的权重和偏置。求解极值的具体过程一般交给tensorflow这样的框架来处理,具体的方法是梯度下降算法,我们会在本章最后介绍梯度下降算法的原理,本节我们先使用tensorflow框架完成受教育年限与收入预测这个模型的训练,让读者对于tensorflow有一个直观的印象。
我们使用 tf.keras 来实现这个简单的线性回归。tf.keras是tensorflow构建和训练模型的核心高阶API,tf.keras允许我们构建两种形式的模型:
Sequential 顺序模型,它是最简单的模型,由多个网络层线性堆叠。
对于更复杂的结构,比如多输入输出模型,可使用 Keras 函数式API。
这里我们使用 Sequential 顺序模型来构建线性回归模型。首先初始化模型:
model = tf.keras.Sequential() # 初始化顺序模型
然后使用add方法添加层,tf.keras内置了很多层,比如dense层所完成的,就是对输入乘以一个权重再加上偏置,正是上面我们所说的模型公式。
model.add(tf.keras.layers.Dense(1, input_shape=(1,)))
代码中第一个参数 1 代表输出的维度,这里输出的仅一个值,也就是收入,所以输出维度就是 1 ,input_shape用来指定输入数据的形状,一般,tf.keras第一层都需要指定输入数据的形状, 在输入数据只有一维的情况下,比如上面的受教育年限数据,数据就是一维的,也可以使用input_dim指定其长度,如input_dim=1。
这样就创建好了model,我们使用 model.summary() 查看模型各层的参数状况:
model.summary()
model.summery() 输出结果
summary输出显示我们的模型只有一层,也就是dense层,也叫做全连接层。Out Shape显示模型输出的形状,Param表示每个层参数的个数。
Param这里显示有两个变量,这符合我们的预期,dense所完成的正是创建了两个Param,这两个Param正是w和b,这两个参数作为可训练的变量,会与输入做运算,运算的公式便是:
w*X + b
这个公式便是dense层帮助我们实现的。这里我们要解释一下,dense对w和b这两个变量是如何处理的呢?实际上,dense在这里会使用随机初始化的方式生成w和b的值,然后与输入进行运算,用得到的结果和真实值使用损失函数计算损失,最后针对损失使用梯度下降的算法,改变w和b值,直到找到loss最小值对应的w和b。
搭建好模型的下一步是编译模型,编译模型主要是配置优化器和损失函数等。优化器是框架提供给我们用来优化训练参数(也就是w和b)的。Tensoflow框架为我们内置了很多常见的优化器,在后面章节中,我们会介绍,这里我们使用最常见的adam优化器,损失函数显示使用平方误差,也就是mse,其实就是MeanSquaredError的简写:
model.compile(optimizer=‘adam’, loss=‘mse’)
最后使用model.fit方法训练模型,这里为了简单演示keras用法,我们直接使用全部数据训练, 先明确输入值和目标值:
x = data.Education.to_numpy() # 输入值
y = data.Income.to_numpy() # 目标值
最后,使用在当前数据上进行训练, 我们使用epochs指定对全部数据的次数,我们训练20000次, 训练返回值赋值给history:
history = model.fit(x, y, epochs=20000)
训练的过程需要一些时间,你能看到类似的输出:
Train on 30 samples
Epoch 1/2000030/30 [==============================] - 1s 49ms/sample - loss: 3301.0947
Epoch 2/2000030/30 [==============================] - 0s 197us/sample - loss: 3299.1340
Epoch 3/2000030/30 [==============================] - 0s 170us/sample - loss: 3297.1746…
这些输出指示了当前的训练epoch次数、消耗时间和当前训练epoch产生的损失值。可以看到损失值随着我们的训练在不断的减小,这说明我们的训练是有效的。 训练完毕后,可以使用model.predict方法对输入做出预测,比如我们使用data的前五个数据作为输入,就可以看到模型对这前五个受教育年限给出的收入预测值,你可以与实际的收入情况进行比较,不难发现它们是很相近的:
model.predict(x[:5])
array([[28.679234],
[30.210728],
[31.895378],
[33.426872],
[34.958366]], dtype=float32)
我们使用绘图能直观的看看模型所代表的直线与现有数据分布的拟合情况。
plt.scatter(data.Education, data.Income, c=‘b’, label=‘real_data’)
plt.plot(data.Education,
model.predict(data.Education.to_numpy()),
c='r',
label='prediction')
plt.legend()
显然,我们的模型很好的拟合了输入数据!
以上就是我们使用tf.keras创建一个简单线性回归模型的整个流程,这个流程也是我们创建深度学习模型的最基础的流程。