目录python
本章内容算法
前面的章节给你们介绍了监督学习的分类部分,接下来几章将会带领同窗们翱翔浩瀚的回归海洋,注意此回归不是 Logistic 回归(Logistic 回归之因此取名为这是由于历史遗留问题)。具体是什么,那就开始让咱们来揭秘吧!
注意: 分类的目标变量是标称型数据;回归的目标变量是连续性数据。api
# coding: 'utf-8' import os import numpy as np import matplotlib.pyplot as plt from path_settings import machine_learning_PATH data_set_path = os.path.join(machine_learning_PATH, '第八章/data-set') ex0_path = os.path.join(data_set_path, 'ex0.txt') ex1_path = os.path.join(data_set_path, 'ex1.txt') abalone_path = os.path.join(data_set_path, 'abalone.txt') def load_data_set(filename): # 文本第一行值全为0的解释:简单说是由于两个矩阵相乘一个矩阵的行和另外一个矩阵的列得相等,具体可查资料 num_feat = len(open(filename).readline().split('\t')) - 1 data_mat = [] label_mat = [] fr = open(filename) for line in fr.readlines(): line_arr = [] cur_line = line.strip().split('\t') for i in range(num_feat): line_arr.append(float(cur_line[i])) data_mat.append(line_arr) label_mat.append(float(cur_line[-1])) return data_mat, label_mat def stand_regres(x_arr, y_arr): x_mat = np.mat(x_arr) y_mat = np.mat(y_arr) x_tx = x_mat.T * x_mat # 判断矩阵是否为奇异矩阵,即矩阵是否有逆矩阵 if np.linalg.det(x_tx) == 0: print("奇异矩阵没有逆矩阵") return ws = x_tx.I * (x_mat.T * y_mat.T) # 求解未知矩阵 # ws = np.linalg.solve(x_tx,x_mat.T*y_mat.T) return x_mat, y_mat, ws def test_stand_regres(): x_arr, y_arr = load_data_set(ex0_path) _, _, ws = stand_regres(x_arr, y_arr) print(ws) if __name__ == '__main__': test_stand_regres()
def plot_stand_regres(x_mat, y_mat, ws): fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(x_mat[:, 1].flatten().A[0], y_mat.T[:, 0].flatten().A[0]) x_copy = x_mat.copy() x_copy.sort(0) y_hat = x_copy * ws ax.plot(x_copy[:, 1], y_hat) plt.show() def test_plot_stand_regres(): x_arr, y_arr = load_data_set(ex0_path) x_mat, y_mat, ws = stand_regres(x_arr, y_arr) plot_stand_regres(x_mat, y_mat, ws) # 判断拟合效果 print(np.corrcoef((x_mat * ws).T, y_mat)) ''' [[1. 0.98647356] [0.98647356 1. ]] ''' if __name__ == '__main__': # test_stand_regres() test_plot_stand_regres()
局部加权线性回归求回归系数公式:\(\hat{w}=(X^TWX)^{-1}X^TWy\)
app
最经常使用的核——高斯核:\(w(i,i)=exp\left({\frac{|x^{(i)}-x|}{-2k^2}}\right)\)
机器学习
点 x 与 x(i)越近,w(i,i)将会越大,参数 k 决定了对附近的点赋予多大的权重。函数
def lwlr(test_point, x_arr, y_arr, k=1): """给样本点增长权重,参数 k 控制衰减的速度""" x_mat = np.mat(x_arr) y_mat = np.mat(y_arr) m = np.shape(x_mat)[0] # 建立对角权重矩阵。该矩阵对角线元素全为1,其他元素全为0 weights = np.mat(np.eye(m)) for j in range(m): diff_mat = test_point - x_mat[j, :] weights[j, j] = np.exp(diff_mat * diff_mat.T / (-2 * k ** 2)) x_tx = x_mat.T * (weights * x_mat) if np.linalg.det(x_tx) == 0: print("奇异矩阵没有逆矩阵") return ws = x_tx.I * (x_mat.T * (weights * y_mat.T)) return test_point * ws def lwlr_test(test_arr, x_arr, y_arr, k=1): """使数据集中每一个点调用 lwlr 方法""" m = np.shape(test_arr)[0] y_hat = np.zeros(m) for i in range(m): y_hat[i] = lwlr(test_arr[i], x_arr, y_arr, k) return y_hat def test_lwlr_test(): x_arr, y_arr = load_data_set(ex0_path) y_hat = lwlr_test(x_arr, x_arr, y_arr, 0.003) print(y_hat) def plot_lwlr(x_sort, y_hat, str_ind, x_mat, y_mat): fig = plt.figure() ax = fig.add_subplot(111) ax.plot(x_sort[:, 1], y_hat[str_ind]) ax.scatter(x_mat[:, 1].flatten().A[0], y_mat.T[:, 0].flatten().A[0], s=2, c='red') plt.show() def test_plot_lwlr(): x_arr, y_arr = load_data_set(ex0_path) x_mat = np.mat(x_arr) y_mat = np.mat(y_arr) y_hat = lwlr_test(x_arr, x_arr, y_arr, 0.01) str_ind = x_mat[:, 1].argsort(0) x_sort = x_mat[str_ind][:, 0, :] plot_lwlr(x_sort, y_hat, str_ind, x_mat, y_mat) if __name__ == '__main__': # test_stand_regres() # test_plot_stand_regres() # test_lwlr_test() test_plot_lwlr()
因为看完《机器学习实战》第八章中的局部加权线性回归后,敲完代码以后只是知道它是这样的,但不是很清楚内在的缘由。书中并无对其作过多解释,百度也找不到一篇很好的文章来解释 线性回归和局部加权线性回归 二者之间的区别。索性写一写本身对 线性回归和局部加权线性回归 的见解与感悟。也许仍是不那么准确,但必定是清晰易懂的。学习
其中的平方偏差是咱们的在 x=x~i~ 上预测值与实际值的差值平方,而咱们须要作的任务就是找到一个最合适的 w 使得该差值平方最小。测试
再来讲说咱们的局部加权线性回归(LWLR),它只是在线性回归的基础上加了一个权重,而LWLR一般使用“核”(相似于自持向量机中的核)来对附近的点赋予更高的权重。所以它的公式变成:google
\(\sum_{i=1}^mW_i(y_i-x^T_iw)^2\)
spa
注意:W~i~ 是赋予 x~i~ 权重的矩阵,也能够是向量。
通常咱们的 W~i~ 最经常使用的核是高斯核:\(w(i,i)=exp\left({\frac{|x^{(i)}-x|}{-2k^2}}\right)\)
注意:高斯核中的 x 为新预测样本的特征数据即新的 x,它同 w 也是一个向量,参数 k 控制了权值变化的速率。
以上介绍了局部加权线性回归的理论,如今经过图像咱们再来形象化的解释局部加权线性回归。首先看看不一样 k 下的参数 k 与权重的关系:
重点来了,我刚开始不明白的就是这里,上面 两个注意+图片解释 其实已经揭晓了答案
离 x 很近的样本,权值接近1;而离 x 很远的样本,此时权值接近于0,这样就在 x 局部构成线性回归,x 构成的线性回归依赖的事 x 周边的点,而不相似于线性回归依赖训练集中的全部数据。
上图红线是某个点 x 基于训练集中全部数据使用线性回归作的结果,黑色直线使用 LWLR 作的结果,因为在每一个数据都会重复局部加权的过程,而且不断地每一个点的回归系数也在不断的改变,所以它会很好的拟合数据集,进而消除了线性回归拟合很差的缺点。(有点相似极限或者求导或者微积分的思想,总之就是把一个大的物体切割成一大部分,而后对于每一部分进行计算)。
说到了LWLR的优势,不得不说说它的缺点,上一段讲到了训练集中的每一个数据都会重复局部加权的过程,所以他的计算量是庞大的,而且他的回归系数是基于周围的数据计算出来的,所以下次须要预测某个数据的分类时,须要再一次输入全部的数据。即线性回归算法是参数学习算法,一旦拟合出合适的回归系数,对于以后的预测,不须要再使用原始训练数据集;局部加权线性回归算法是非参数学习算法,每次进行预测都须要所有的训练数据,没法算出固定的回归系数。
最后看一看 线性回归和不一样 k 值的局部加权线性回归 对相同数据集的结果。
上图第一张图使用的是 k=1 的LWLR(相似于线性回归),第二张图使用的是 k=0.01 的LWLR,第三张图使用的 k=0.003 的 LWLR。第一张图明显欠拟合,第二张图很合适,第三张图过拟合。