我们之前介绍了几种机器学习算法,这些机器学习算法都是用来进行分类的。今天换换口味,我们来了解一下如何进行回归,回归是基于已有的数据对新的数据进行预测,比如预测产品销量。





我们来看看最简单的线性回归,基于标准的线性回归,可以扩展出更多的线性回归算法,比如基于核函数的局部加权线性回归,lasso等。希望了解的可以查阅相关的资料。下面来看看最基本的线性回归的原理。





根据线性代数,我们可以定义线性方程组Xw=y,在线性回归问题中,X是我们的样本数据矩阵,y是我们的期望值向量,也就是说,对于线性回归问题,我们的X和y是已知的,我们要解决的问题是,求取最合适的一个向量w,使得线性方程组能够尽可能的满足样本点的线性分布。之后我们就可以利用求得的w,对新的数据点进行预测。





这里我们使用平方误差来评估实际y值和预测值之间的误差:



修改为矩阵形式:



我们要使平方误差为最小,根据微积分的内容,我们可以对上面的式子相对w求导:




令上式等于0,然后求得:






等式右边都是我们的已知数据,所以可以求得w的最佳估计。





可以看到,线性回归的原理比较简单,但是,如果注意上面的式子会发现,我们需要求逆矩阵,但是如果矩阵不可逆怎么办?这里有两个思路,一个是采用岭回归的思路,引入参数lambda:




这样,按照线性代数的理论,对于lambda不为0,逆矩阵是一定存在的。下面看看代码:

def linear_regression(x_arr, y_arr, lam=0.2): x_mat = np.mat(x_arr).T y_mat =
np.mat(y_arr).T x_tx = x_mat.T * x_mat denom = x_tx +
np.eye(np.shape(x_mat)[1]) * lam # if lam == 0.0 if np.linalg.det(denom) ==
0.0: print('This matrix is singular, cannot do inverse') return ws = denom.I *
(x_mat.T * y_mat) return ws

再看一下调用的demo:
if __name__ == '__main__': x_vals = np.linspace(0, 1, 1000) y_vals = x_vals +
np.random.normal(0, 1, 1000) ws = linear_regression(x_vals, y_vals) predict =
20 * ws print(predict.A[0][0])
我们构造了x和y使其尽可能满足x=y,不过在其中加入了标准正态分布的噪声,求出ws之后,我们预测了x=20的y值。下面是我运行一次的结果,预测效果还不错:

19.690649736617942




另一种思路是我们直接使用梯度下降法求取平方误差的最小值,这里我们使用tensorflow实现。首先导入需要的包并准备数据:
import numpy as np import tensorflow as tf learning_rate = 0.05 batch_size =
50 x_vals = np.linspace(0, 1, 1000) y_vals = x_vals + np.random.normal(0, 1,
1000) x_vals.resize((x_vals.shape[0], 1)) y_vals.resize((y_vals.shape[0], 1))

然后构造模型,x_data和y_target是占位符,在训练模型时传入,w是我们训练模型希望得到的目标变量:
sess = tf.Session() x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)
y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32) w =
tf.Variable(tf.random_normal([1, 1])) model_output = tf.matmul(x_data, w)
定义均方误差,然后使用梯度下降法进行优化,求取最小值
loss = tf.reduce_mean(tf.square(y_target - model_output)) init =
tf.global_variables_initializer() sess.run(init) my_opt =
tf.train.GradientDescentOptimizer(learning_rate) train_step =
my_opt.minimize(loss)
最后,使用随机梯度下降法进行训练,并输出测试结果
for i in range(500): rand_index = np.random.choice(len(x_vals),
size=batch_size) rand_x = x_vals[rand_index] rand_y = y_vals[rand_index]
sess.run(train_step, feed_dict={x_data: rand_x, y_target: rand_y}) [k] =
sess.run(w) predict = 20 * k print(predict[0])
一次运行结果:

19.260855




至此,我们使用两种方式实现了线性回归,第一种方式比较直接,直接实现算法,第二种方法借助于tensorflow通过梯度下降算法求取了最优值。