一、实验目的和要求
通过在Python中的实例应用,分析掌握线性回归分析方法的基本原理,加深对线性回归分析算法的理解,并掌握将算法应用于实际的方法、步骤。
二、实验内容和原理
在Python中完成线性回归算法模型的数据输入、参数设置;
对Python中线性回归算法的实例数据输出结果进行分析。
三、操作方法和实验步骤
用Python语言实现线性回归分析的算法,请针对随机数据(randn_data_regression_X, randn_data_regressiony),要求完成以下内容:
方法一:解线性方程组计算得到线性回归模型的参数。
方法二:利用梯度下降法计算线性回归模型的参数。
在线性回归模型中加入正则化项λ∑(i=1)^n▒w_i^2 ,实现计算过程。
四、存在问题及可能原因
算法可能存在的问题,若有,请写出解决原因与方法。
五、附源代码以及代码相应注释
源代码(代码贴在此处,同时要求代码文件也要一起打包上传)
方法一:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#正常显示文字
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
#定义文件路径
Xpath = r"C:\Users\王凯一\Desktop\作业\数据挖掘技术\02-线性回归分析\02-回归\data\randn_data_regression_X.csv"
Xdata = pd.read_csv(Xpath)
ypath = r"C:\Users\王凯一\Desktop\作业\数据挖掘技术\02-线性回归分析\02-回归\data\randn_data_regression_y.csv"
ydata = pd.read_csv(ypath)
#在data前添加一列ones
Xdata.insert(0,'ones',1)
#读取相关数据
X = Xdata.iloc[:,:]
y = ydata.iloc[:,0]
#数据初始化
X = X.values
y = y.values
w = np.zeros((X.shape[1],1))
#定义损失函数
def compute_cost(X,y,w):
#计算损失函数
inner = np.power(X@w-y,2)
return np.sum(inner)/(2*len(X))
#使用线性方程组计算得到线性回归模型的参数
def linear_regression(X, y):
# 计算X的转置乘以X
XTX = np.dot(X.T, X)
# 计算XTX的逆矩阵
XTX_inv = np.linalg.inv(XTX)
# 将XTX的逆矩阵乘以X的转置乘以y,得到参数向量w
w = np.dot(XTX_inv, np.dot(X.T, y))
return w
print("使用正规方程组计算得到的参数:{}".format(linear_regression(X, y)))
print("使用正规方程组计算得到的损失:{}".format(compute_cost(X, y, linear_regression(X, y))))
方法二:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#正常显示文字
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
#定义文件路径
Xpath = r"C:\Users\王凯一\Desktop\作业\数据挖掘技术\02-线性回归分析\02-回归\data\randn_data_regression_X.csv"
Xdata = pd.read_csv(Xpath)
ypath = r"C:\Users\王凯一\Desktop\作业\数据挖掘技术\02-线性回归分析\02-回归\data\randn_data_regression_y.csv"
ydata = pd.read_csv(ypath)
#定义损失函数
def compute_cost(X,y,w):
#计算损失函数
inner = np.power(X@w-y,2)
return np.sum(inner)/(2*len(X))
#在data前添加一列ones
Xdata.insert(0,'ones',1)
#读取相关数据
X = Xdata.iloc[:,:]
y = ydata.iloc[:,0]
#数据初始化
X = X.values
y = y.values
w = np.zeros((X.shape[1],1))
#计算初始损失函数
print("初始损失:{}".format(compute_cost(X,y,w)))
#批量梯度下降
def batch_gradientDescent(X, y, w, alpha, count):
"""
批量梯度下降算法实现。
参数:
X -- 特征矩阵,形状为 (n_samples, n_features)
y -- 标签向量,形状为 (n_samples,1)
w -- 权重向量,形状为 (n_features,1)
alpha -- 学习率
count -- 迭代次数
返回值:
w -- 更新后的权重向量
costs -- 每次迭代的代价函数值列表
"""
# 初始化代价函数值列表
costs = []
# 对每个样本进行迭代
for i in range(count):
# 根据公式更新权重向量
w = w - (X.T @ (X @ w - y)) * alpha / len(X)
# 计算当前代损失函数值并添加到列表中
cost = compute_cost(X, y, w)
costs.append(cost)
# 每隔100次迭代输出一次当前代价函数值
if i % 10 == 0:
print("在第{}次迭代中,cost的值是:{}。".format(i, cost))
# 返回最终的权重向量和代价函数值列表
return w,costs
alpha = 0.01
iters = 100
w, costs = batch_gradientDescent(X, y, w, alpha, iters)
#使用我们拟合的参数所计算的最终损失
print("使用我们拟合的参数所计算的最终损失:{}".format(compute_cost(X,y,w)))
# 训练图像
# 创建一个大小为 (12, 8) 的画布和坐标轴对象
fig, ax = plt.subplots(figsize=(12, 8))
# 在坐标轴上绘制代价函数 cost2 随迭代次数 iters 的变化曲线,使用红色线条
ax.plot(np.arange(iters), costs, 'r')
# 设置 x 轴标签为 "迭代次数",字体大小为 18
ax.set_xlabel('迭代次数', fontsize=18)
# 设置 y 轴标签为 "代价",旋转角度为 0,字体大小为 18
ax.set_ylabel('损失', rotation=0, fontsize=18)
# 设置图表标题为 "误差和训练Epoch数",字体大小为 18
ax.set_title('损失和训练Epoch数', fontsize=18)
# 显示图表
plt.show()
方法三:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#正常显示文字
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
#定义文件路径
Xpath = r"C:\Users\王凯一\Desktop\作业\数据挖掘技术\02-线性回归分析\02-回归\data\randn_data_regression_X.csv"
Xdata = pd.read_csv(Xpath)
ypath = r"C:\Users\王凯一\Desktop\作业\数据挖掘技术\02-线性回归分析\02-回归\data\randn_data_regression_y.csv"
ydata = pd.read_csv(ypath)
#定义带正则化的损失函数
def compute_cost_reg(X,y,w,lambda_):
#计算损失函数
y_pred = X @ w
error = y_pred - y
sq_error = error ** 2
cost = (np.sum(sq_error) / len(X)) + (lambda_ * np.sum(w ** 2))
return cost
#在data前添加一列ones
Xdata.insert(0,'ones',1)
#读取相关数据
X = Xdata.iloc[:,:]
y = ydata.iloc[:,0]
#数据初始化
X = X.values
y = y.values
lambda_ = 0.01 # 正则化系数
w = np.zeros((X.shape[1],1))
#计算初始损失函数
print("初始损失:{}".format(compute_cost_reg(X,y,w,lambda_)))
#带正则化的批量梯度下降
def batch_gradientDescent_reg(X, y, w, alpha, count, lambda_):
# 初始化代价函数值列表
costs = []
# 对每个样本进行迭代
for i in range(count):
# 根据公式更新权重向量
w = w - (X.T @ (X @ w - y)) * alpha / len(X) - (2 * lambda_ * w)
# 计算当前代损失函数值并添加到列表中
cost = compute_cost_reg(X, y, w, lambda_)
costs.append(cost)
# 每隔100次迭代输出一次当前代价函数值
if i % 10 == 0:
print("在第{}次迭代中,cost的值是:{}。".format(i, cost))
# 返回最终的权重向量和代价函数值列表
return w,costs
alpha = 0.01
iters = 100
w, costs = batch_gradientDescent_reg(X, y, w, alpha, iters, lambda_)
print("使用我们带正则化拟合的参数所计算的最终损失:{}".format(compute_cost_reg(X, y, w, lambda_)))
# 生成训练图像
# 创建一个大小为 (12, 8) 的画布和坐标轴对象
fig, ax = plt.subplots(figsize=(12, 8))
# 在坐标轴上绘制代价函数 cost2 随迭代次数 iters 的变化曲线,使用红色线条
ax.plot(np.arange(iters), costs, 'r')
# 设置 x 轴标签为 "迭代次数",字体大小为 18
ax.set_xlabel('迭代次数', fontsize=18)
# 设置 y 轴标签为 "代价",旋转角度为 0,字体大小为 18
ax.set_ylabel('损失', rotation=0, fontsize=18)
# 设置图表标题为 "误差和训练Epoch数",字体大小为 18
ax.set_title('损失和训练Epoch数', fontsize=18)
# 显示图表
plt.show()
六、实验总结及建议
总结本次实验得失,是否可以有更好的建议使得题目更加有实用意义等。
学习了线性回归模型