从标准方程,梯度下降窥探机器学习训练原理

462 阅读3分钟

机器学习的学习不应该仅仅停留在对scikit-learn or tensorflow(deep learning)框架的调用,而应该着眼于内部的世界,学习机器学习有一段时间了,有必要回头整理一下,下面我们基于线性模型来看

  • 标准方程
  • 梯度下降 进而来看基于以上两者如何实现模型的训练,基本思想一致,不同的模型大家可以触类旁通
下面我们分布阐述

1.标准方程

2.梯度下降

3.机器学习模型训练过程

1.标准方程

标准方程:其实就是求算法模型成本函数最小,即为0的时候的\theta的闭式解

这个定义其实很好理解: 下面我们以线性回归进行进一步的论证:

  • 1.线性回归的预测模型
y = \theta  * X
  • 2.那么线性回归的成本函数就是MSE:
MSE(X,h_\theta) = 1/m  \sum_{i=0}^{m}(\theta^T * Xi  - yi)^2
  • 3.接着我们对MSE求导,并令其等于0,这样得到一个权重theta为因变量的闭式解:
\theta = (X^T * X)^{-1} * X^T  * y
  • 4.得到标准方程,模型便可以开始预测了:
y(pred) = \theta * X

2.梯度下降

梯度下降:可以成为是从初始theta开始,一步步求的成本函数最低点的过程;

\theta(next) = \theta - \eta \frac{\partial mse}{\partial \theta}
\theta:权重向量 \quad  \eta:学习率 \quad \frac{\partial mse}{\partial \theta}:梯度

其实通过上面的参数我们可以进一步理解梯度下降:

  • 梯度下降:通过上面的公式不断更新权重,不断的训练模型,当成本函数达到理想值的时候,停止更新权重,即停止训练模型
    在这里插入图片描述
2.1:梯度向量的计算:

上面就是梯度下降的图例,以线性回归为例,成本函数的梯度向量也可以通过一个闭式方程进行计算:

\frac{\partial mse}{\partial \theta} = 2/m * \sum_{i=1}^m(\theta * X^{(i)} - y^{(i)})x_j^{(i)}
\frac{\partial mse}{\partial \theta} = 2/m * X^T * (X*\theta - y)
2.2:学习率

学习率在梯度下降的过程中很关键,如果学习率很低,算法需要大量时间才可以收敛; 反之,学习率太高,则会让函数迅速发散最终找不到最优解 所以,学习率做为一个重要的超参数,我们应该通过类似网格搜索等途径获取最佳的学习率,或者可以这样,随着训练次数的提升,有规律的降低学习率: 下面看图例:(第一个是学习率太低,第二个是学习率太高)

在这里插入图片描述
在这里插入图片描述

梯度下降可以分为3种,主要式通过训练所用到的X的shape级别进行区分:

  1. 批量梯度下降:每次使用全部的数据进行梯度计算
  2. 随机梯度下降:每次使用随机的一条数据进行梯度计算
  3. 小批量梯度下降:每次从数据中随机取出一部分数据进行计算

到这里,我们可以直观的看出机器学习中,梯度下降可以用来优化模型

3.机器学习模型训练过程

下面粘贴一部分tensorflow的代码,(不了解tensorflow可以直接跳过这块代码):

m, n = housing.data.shape
n_epochs = 1000
learning_rate = 0.01
pipeline = Pipeline([
    ('std_scaler', StandardScaler())
])
scaled_housing_data_plus_bias = pipeline.fit_transform(housing_data_plus_bias)
serialize_data(scaled_housing_data_plus_bias,'scaled_housing_data_plus_bias')
X = tf.constant(scaled_housing_data_plus_bias, dtype=tf.float32, name='X')
y = tf.constant(housing.target.reshape(-1, 1), dtype=tf.float32, name='y')
# 获取初始的theta
theta = tf.Variable(tf.random_uniform([n + 1, 1], -1.0, 1.0), name='theta')
y_pred = tf.matmul(X, theta, name='predictions')
error = y_pred - y
mse = tf.reduce_mean(tf.square(error), name='mse')
gradients = 2 / m * tf.matmul(tf.transpose(X), error)
training_op = tf.assign(theta, theta - learning_rate * gradients)
# 开启会话
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for epoch in range(n_epochs):
        if epoch % 100 == 0:
            print('Epoch', epoch, 'MSE = ', mse.eval())
        sess.run(training_op)
        # training_op.eval()
    best_theta = theta.eval()

具体阐述原理:

1.初始化权重向量\theta,这里的\theta初始化需要注意,\theta的shape须为(features,)

2.接着利用\theta*X求得当前的预测值,进而求的MSE,然后利用下面公式:

\frac{\partial mse}{\partial \theta} = 2/m * X^T * (X*\theta - y)\;\;\;\;\;\;\;\theta(next) = \theta - \eta \frac{\partial mse}{\partial \theta}

更新\theta,循环往复的重复1,2步骤,直到MSE的值调节倒最优,停止更新\theta,并停止训练

如此这般,基于数据不断训练模型直至模型输出最优: 但是需要注意一点: 由于这个训练过程是基于X来进行训练的,所以我们为了提高效率,需要使用小批量的梯度下降: eg:每次从数据中取出50条数据进行训练,这样效率大大提高