【每天进步一点点】机器学习基础——基于鲍鱼年龄预测的线性回归Demo
【摘要】 机器学习基础——基于鲍鱼年龄预测的线性回归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.com/modelarts/?region=cn-north-4#/dashboard
最后附上代码和数据集,在附件哦,解压后上传.ipynb和.txt到NoteBook即可使用
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)