数学原理
线性回归试图学得:
使得:
其中,是样本特征值,是样本标签值,是模型预测值。
如何学得w和b呢?均方差(MSE - mean squared error)是回归任务中常用的手段:
称为损失函数。实际上就是试图找到一条直线,使所有样本到直线上的残差的平方和最小。
梯度下降
损失函数(Loss Function)
为均方差函数:
与最小二乘法比较可以看到,梯度下降法和最小二乘法的模型及损失函数是相同的,都是一个线性模型加均方差损失函数,模型用于拟合,损失函数用于评估效果。
区别在于,最小二乘法从损失函数求导,直接求得数学解析解,而梯度下降以及后面的神经网络,都是利用导数传递误差,再通过迭代方式一步一步(用近似解)逼近真实解。
计算z的梯度
根据公式2:
计算w的梯度
我们用loss的值作为误差衡量标准,通过求w对它的影响,也就是loss对w的偏导数,来得到w的梯度。由于loss是通过公式2->公式1间接地联系到w的,所以我们使用链式求导法则,通过单个样本来求导。
根据公式1和公式3:
计算b的梯度
定义模型
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
# Define model and Loss
class Model(object):
def __init__(self):
self.W = tf.Variable(10.0)
self.b = tf.Variable(-5.0)
def __call__(self, inputs):
return self.W * inputs + self.b
def compute_loss(y_true, y_pred):
return tf.reduce_mean(tf.square(y_true-y_pred))
model = Model()
模拟一些数据
TRUE_W = 3.0
TRUE_b = 2.0
NUM_EXAMPLES = 1000
inputs = tf.random.normal(shape=[NUM_EXAMPLES])
noise = tf.random.normal(shape=[NUM_EXAMPLES])
outputs = inputs * TRUE_W + TRUE_b + noise
梯度计算
learning_rate = 0.1
for epoch in range(30):
with tf.GradientTape() as tape:
loss = compute_loss(outputs, model(inputs))
dW, db = tape.gradient(loss, [model.W, model.b])
model.W.assign_sub(learning_rate * dW)
model.b.assign_sub(learning_rate * db)
print("=> epoch %2d: w_true= %.2f, w_pred= %.2f; b_true= %.2f, b_pred= %.2f, loss= %.2f" %(
epoch+1, TRUE_W, model.W.numpy(), TRUE_b, model.b.numpy(), loss.numpy()))
# => epoch 30: w_true= 3.00, w_pred= 2.97; b_true= 2.00, b_pred= 2.04, loss= 0.96
也可以使用API
model2 = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(1),
])
model2.compile(optimizer="sgd",
loss='mse')
model2.fit(inputs, outputs, epochs=10)
model2.weights
# [<tf.Variable 'sequential/dense/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[2.9936187]], dtype=float32)>,
<tf.Variable 'sequential/dense/bias:0' shape=(1,) dtype=float32, numpy=array([1.9848138], dtype=float32)>]
网友评论