【每天进步一点点】机器学习基础——基于鲍鱼年龄预测的线性回归Demo
回归问题
回归分析是一种预测性的建模技术,它研究的是因变量(目标)和自变量(预测器)之间的关系。这种技术通常用于预测分析,时间序列模型以及发现变量之间的因果关系。通常使用曲线/线来拟合数据点,目标是使曲线到数据点的距离差异最小。
2. 线性回归
线性回归是回归问题中的一种,线性回归假设目标值与特征之间线性相关,即满足一个多元一次方程。通过构建损失函数,来求解损失函数最小时的参数w和b。通长我们可以表达成如下公式:
y^为预测值,自变量x和因变量y是已知的,而我们想实现的是预测新增一个x,其对应的y是多少。因此,为了构建这个函数关系,目标是通过已知数据点,求解线性模型中w和b两个参数。
3. 主要方式
线性回归主要有梯度下降,正则方程,基于kernel的线性回归等。
这里只介绍下梯度下降:
梯度下降是一种优化方法,在机器学习中被广泛使用。它的主要思想是在优化目标函数的时候,沿着负梯度方向去减小函数值,以此达到我们的优化目标。
一般来说,梯度下降算法无法避免局部极值点的产生,因此其最优点会随着初始点选择不同而不同,解决这个问题的方法是随机进行初始化,寻找多个最优点,再在这些最优点之间比较。就本题而言,本题是一个线性回归问题,他的目标函数是一个凸二次函数,只有一个极值点,因此无论初始点选在哪里最优点都相等。
除了最基本的梯度下降外,该算法还有许多的变体,如批量梯度下降,随机梯度下降等。它们的不同之处在于一次性使用多少数据来计算目标函数的梯度。也就是在参数更新准确性和参数更新花费时间两方面做出权衡。以随机梯度下降为例,当数据量较大时,每一次迭代都需要遍历全部数据,使得参数更新缓慢,为了解决这个问题,更新参数时不选取全部m个训练示例,只使用其中的一个或一部分,这样加快了迭代速度,但是可能导致不能精确收敛到最优值。
好了,上代码
# -*- coding:utf-8 -*- # Created on 2020/05/26 # @author: Tianyi_Li # Method: 基于线性回归(Linear Regression)的鲍鱼年龄预测 # Reference: https://cuijiahua.com/blog/2017/11/ml_11_regression_1.html # 导入相关的库 import matplotlib.pyplot as plt import numpy as np from sklearn import decomposition # 读取数据 def loadDataSet(fileName): """ Function specification: 设数据集为M * N 矩阵,将每行的前N - 1列数据抽成一个矩阵,将最后的一列作为另一个矩阵 Parameters: fileName - 文件名 Returns: xArr - x数据集,表示数据 yArr - y数据集,表示标签 Reference: https://www.cuijiahua.com/ https://blog.csdn.net/wzj_123123/article/details/77938565 Modify: 2020/5/26 """ # 方法一,直接调用函数 data = np.loadtxt(fileName) xArr = data[:, 0:-1] # 除最后一列外存入xArr yArr = data[:, -1] # 将最后一列存入yArr ''' 方法二:逐行读取 numFeat = len(open(fileName).readline().split('\t')) - 1 xArr = [] yArr = [] fr = open(fileName) for line in fr.readlines(): print("line:", line) lineArr = [] curLine = line.strip('\n').split(' ') for i in curLine: if i != '': lineArr.append(float(i)) xArr.append(lineArr[0:-1]) # print(curLine[-1]) yArr.append(lineArr[-1]) ''' return xArr, yArr # 线性回归 def standRegress(xArrTrain, yArrTrain): """ Function specification: Parameters: xArrTrain - x数据集,训练集 yArrTrain - y数据集,训练集 Returns: ws - 回归系数 Reference: https://blog.csdn.net/chivalrousli/article/details/52474376 Modify: 2020/5/26 """ xMat = np.mat(xArrTrain) yMat = np.mat(yArrTrain).T xTx = xMat.T * xMat # 计算回归系数 if np.linalg.det(xTx) == 0.0: print("矩阵为奇异矩阵,不能求逆") return ws = xTx.I * xMat.T * yMat # print("ws:", ws) return ws # 绘制回归线 def plotLineRegression(xArrTest, yArrTest, xArrTrain, yArrTrain): """ Function specification: 绘制回归线 Reference: https://blog.csdn.net/chivalrousli/article/details/52474376 Modify: 2020/5/26 """ ws = standRegress(xArrTrain, yArrTrain) # 计算回归系数 xMat = np.mat(xArrTest) # 创建xMat矩阵 yMat = np.mat(yArrTest) # 创建yMat矩阵 xCopy = xMat.copy() # 拷贝xMat矩阵 # xCopy.sort(0) # 排序 yHat = xCopy * ws # 计算对应的y值 fig = plt.figure() # ax = fig.add_subplot(111) m = xCopy.shape[0] xHat = np.linspace(1, m, m) plt.plot(xHat, yArrTest, c='red', label = 'yArrTest - test data') plt.plot(xHat, yHat, c='green', label = 'yHat - pridected data') plt.title('LineRegression yArrTest VS yHat') # 绘制title plt.legend(loc='upper right') plt.show() ''' # Created on 2020/5/26 # @author: AngelWings # Method: 局部加权线性回归(Locally Weighted Linear Regression,LWLR) # Reference: https://cuijiahua.com/blog/2017/11/ml_11_regression_1.html ''' # 局部加权线性回归 # 使用局部加权线性回归计算回归系数w def lwlr(testPoint, xArr, yArr, k = 1.0): """ Function specification: Parameters: testPoint - 测试样本点 xArr - x数据集,表示数据 yArr - y数据集,表示标签 k - 高斯核的k,自定义参数 Returns: ws - 回归系数 Refenence: https://blog.csdn.net/Albert_Wang_YY/article/details/54407650 Modify: 2020/5/26 """ xMat = np.mat(xArr) yMat = np.mat(yArr).T # .T表示转置矩阵 m = np.shape(xMat)[0] # 输出m为xMat行数,即M weights = np.mat(np.eye((m))) # 创建权重对角矩阵 for j in range(m): # 遍历数据集,根据高斯核函数构造权重矩阵 diffMat = testPoint - xMat[j, :] weights[j, j] = np.exp(diffMat * diffMat.T/(-2.0 * k**2)) # 更新权重值,以指数级递减 xTx = xMat.T * (weights * xMat) # if np.linalg.det(xTx) == 0.0: # print("矩阵为奇异矩阵,不能求逆") # return # ws = xTx.I * (xMat.T * (weights * yMat)) # 计算回归系数 xTx_pinv = np.linalg.pinv(xTx) ws = xTx_pinv * (xMat.T * (weights * yMat)) # 计算回归系数,这里求伪逆 return testPoint * ws # 局部加权线性回归测试 def lwlrTest(testArr, xArr, yArr, k=1.0): """ Function specification: Parameters: testArr - 测试数据集,测试集 xArr - x数据集,训练集 yArr - y数据集,训练集 k - 高斯核的k,自定义参数 Returns: ws - 回归系数 Reference: https://blog.csdn.net/chivalrousli/article/details/52474376 Modify: 2020/5/26 """ m = np.shape(testArr)[0] # 计算测试数据集大小 yHat = np.zeros(m) for i in range(m): # 对每个样本点进行预测 yHat[i] = lwlr(testArr[i], xArr, yArr, k) return yHat # 误差大小评价函数 def MeanSquareError(xArrTest, yArrTest, xArrTrain, yArrTrain): """ Function specification: 选取70%数据作为训练数据,余下30%数据作为测试数据 Returns: 均方误差大小 """ ws = standRegress(xArrTrain, yArrTrain) # 计算回归系数 xMat = np.mat(xArrTest) # 创建xMat矩阵 yMat = np.mat(yArrTest) # 创建yMat矩阵 xCopy = xMat.copy() # 深拷贝xMat矩阵 # xCopy.sort(0) # 排序 yHat = xMat * ws # 计算对应的y值 # yHat = yHat.flatten().A[0] # 将输出数据展开为一维列表 sum = 0 for i in range(len(yHat)): sum += ((yArrTest[i] - yHat[i]) ** 2) MSE = sum/2/len(yHat) return MSE def LELR_MeanSquareError(lwlrTest, yArrTest): return (((lwlrTest - yArrTest) ** 2).sum()) / 2 / len(yArrTest) # PCA Model def myPCA_Module(x, n_components): ''' x -- data n_components -- 指定希望PCA降维后的特征维度数目 # decomposition.PCA(n_components) 说明: # sklearn.decomposition.PCA(n_components=None, copy=True, whiten=False, # svd_solver=’auto’, tol=0.0, iterated_power=’auto’, random_state=None) # 主要使用参数n_components:指定希望PCA降维后的特征维度数目。用法如下: # 1. 最常用的做法是直接指定降维到的维度数目,此时n_components是一个大于等于1的整数。 # 2. 指定主成分的方差和所占的最小比例阈值,让PCA类自动根据样本特征方差来决定降维到 # 的维度数,此时n_components是一个(0,1]之间的数。 # 3. 将参数设置为"mle", 此时PCA类会用MLE算法根据特征的方差分布情况自己去选择一定数 # 量的主成分特征来降维。 # 4. 用默认值,即不输入n_components,此时n_components=min(样本数,特征数)。 ''' pca = decomposition.PCA(n_components = n_components) # fit_transform(X)说明 # 用X来训练PCA模型,同时返回降维后的数据。 # newX = pca.fit_transform(X),newX就是降维后的数据。 x_new = pca.fit_transform(x) # explained_variance_,它代表降维后的各主成分的方差值。方差值越大,则说明越是重要的主成分。 print('pca.explained_variance_:', pca.explained_variance_) # explained_variance_ratio_,它代表降维后的各主成分的方差值占总方差值的比例,这个比例越大,则越是重要的主成分。 print('pca.explained_variance_ratio_:', pca.explained_variance_ratio_) # 各个特征所占比例图绘制 plt.figure() plt.plot(pca.explained_variance_, 'r') plt.xlabel('n_components', fontsize=16) plt.ylabel('explained_variance_', fontsize=16) plt.show() return x_new if __name__ == '__main__': xArr, yArr = loadDataSet('AbaloneAge.txt') # 加载数据集 xArrTrain = xArr[0:2924] # 训练数据集0-2924行 xArrTrain = np.insert(xArrTrain, 0, 1, axis=1) # 在第一列前插入一列“1”,获取常数项 yArrTrain = yArr[0:2924] # 训练数据集0-2924行 xArrTest = xArr[2924:4178] # 测试数据集2925-4177行 xArrTest = np.insert(xArrTest, 0, 1, axis=1) # 在第一列前插入一列“1”,获取常数项 yArrTest = yArr[2924:4178] # 测试数据集2925-4177行 # 线性回归 # plotLineRegression(xArrTest, yArrTest, xArrTrain, yArrTrain) # print('Mean Square Error:', MeanSquareError(xArrTest, yArrTest, xArrTrain, yArrTrain)) # 局部加权线性回归 # yHat = lwlrTest(xArrTest, xArrTrain, yArrTrain, k = 0.003) # print('Mean Square Error:', LELR_MeanSquareError(yHat, yArrTest)) # PCA and Linear Regression ---- Mean Square Error: [[2.30770975]] xArrTrainPCA = myPCA_Module(xArrTrain, 7) xArrTrainPCA = np.insert(xArrTrainPCA, 0, 1, axis=1) # 在第一列前插入一列“1”,获取常数项 xArrTestPCA = myPCA_Module(xArrTest, 7) xArrTestPCA = np.insert(xArrTestPCA, 0, 1, axis=1) # 在第一列前插入一列“1”,获取常数项 plotLineRegression(xArrTestPCA, yArrTest, xArrTrainPCA, yArrTrain) print('Mean Square Error:', MeanSquareError(xArrTestPCA, yArrTest, xArrTrainPCA, yArrTrain))
最终结果如图:
效果还行,MSE在2.47左右。线性回归是非常基础的方法,虽然现在可能用得不多(一般都是大数据训练模型了,但基础总是要掌握的嘛)。
是不是很简单,赶快试试吧。什么,没资源,来来来,ModelArts免费AI资源给你,https://console.huaweicloud.cn/modelarts/?region=cn-north-4#/dashboard
最后附上代码和数据集,在附件哦,解压后上传.ipynb和.txt到NoteBook即可使用
- 点赞
- 收藏
- 关注作者
评论(0)