【吴恩达老师《机器学习》】课后习题5之【偏差与方差】

在本练习中,您将实现正则化线性回归,并使用它来研究具有不同偏差-方差特性的模型。

  • 在练习的前半部分,您将实现正则化线性回归,利用水库水位的变化来预测从大坝流出的水量。
  • 在后半部分中,您将对调试学习算法进行一些诊断,并检查偏差和偏差的影响。
    这次练习将会了解如何改进机器学习算法,包括过拟合、欠拟合的状态判断以及学习曲线的绘制。

一些概念

  • 偏差Bias:
    预测值与真实值的差距,表示算法本身的拟合能力

  • 方差Variance:
    预测值的变化范围,表示数据扰动所造成的影响
    如图所示(图片来自网络偏差与方差)
    在这里插入图片描述

  • 训练集:训练模型,类似课后练习小题

  • 验证集:模型选择,模型的最终优化,类似于模拟卷

  • 测试集:利用训练好的模型测试其泛化能力,类似于高考验证
    之前的练习中,仅用到了训练集,实际开发者,一般使用训练集进行模型训练出几个模型,验证集验证哪个模型最优并进行优化,再使用测试集进行验证模型的泛化能力

  • 损失函数和梯度见下图
    在这里插入图片描述

案例

案例描述与数据集

案例:利用水库水位变化预测大坝出水量
数据集:ex5data1.mat【吴恩达老师】机器学习、深度学习课后习题所有的数据集】
在本练习中,您将实现正则化线性回归,并使用它来研究具有不同偏差-方差特性的模型。
在练习的前半部分,您将实现正则化线性回归,利用水库水位的变化来预测从大坝流出的水量。
在后半部分中,您将对调试学习算法进行一些诊断,并检查偏差和偏差的影响。

1.导包

import numpy as np
import matplotlib.pyplot as plt
from scipy.io import loadmat
from scipy.optimize import minimize

2.读取数据

# 导入数据集
data = loadmat('ex5data1.mat')# 打印data字典里的键  1. X和y训练集数据  2. Xtest和ytest是测试集数据  3.Xval和yval是验证集数据
print('打印data字典里的键:', data.keys())# 打印data字典里的键: dict_keys(['__header__', '__version__', '__globals__', 'X', 'y', 'Xtest', 'ytest', 'Xval', 'yval'])# 训练集
X_train, y_train = data['X'], data['y']
print('打印训练集维度:', X_train.shape, y_train.shape)  # (12, 1) (12, 1) 表明有12个样本,1个特征# 验证集
X_val, y_val = data['Xval'], data['yval']
print('打印验证集维度:', X_val.shape, y_val.shape)  # (21, 1) (21, 1)表明有21个样本,1个特征# 测试集
X_test, y_test = data['Xtest'], data['ytest']
print('打印测试集维度:', X_test.shape, y_test.shape)  # (21, 1) (21, 1) 表明有21个样本,1个特征

3.对训练集、验证集、测试集数据进行处理

# 添加偏置项:每行的开头插入一个值为1的列
X_train = np.insert(X_train, 0, 1, axis=1)
X_val = np.insert(y_val, 0, 1, axis=1)
X_test = np.insert(X_test, 0, 1, axis=1)

4.数据可视化

4.1先进行线性回归,看一下效果

4.1.1绘制散点图查看数据
'''绘制散点图的函数 plot_data()。
它使用训练数据集的特征和标签来创建一个散点图,以可视化特征与标签之间的关系。'''def plot_data():fig, ax = plt.subplots()  # 创建图形对象(fig)和一个坐标轴对象(ax)# 使用scatter函数绘制散点图,      X_train[:, 1]表示   使用训练数据集中第二列特征作为X轴坐标  水位的变化#                              y_train表示        使用训练数据集中的标签作为Y轴坐标      出水量# 按照每个样本的特征和标签的取值,在散点图显示它们之间的关系ax.scatter(X_train[:, 1], y_train)ax.set(xlabel='change in water level(x)',ylabel='water flowing out the dam(y)')# 调用plot_data函数,看原始数据分布散点图
plot_data()
# 显示图形
plt.show()

运行结果:
在这里插入图片描述

4.1.2构造损失函数(带正则化)和梯度

在这里插入图片描述

# 损失函数
def reg_cost(theta, X, y, lamda):cost = np.sum(np.power((X @ theta - y.flatten()), 2))reg = theta[1:] @ theta[1:] * lamda  # 第一项不参与正则化return (cost + reg) / (2 * len(X))# 测试 损失函数
# X_train.shape[1]表示训练数据集X_train的列数,也就是特征的个数。
# 然后,使用np.ones()函数创建了一个元素均为1的数组,并赋值给theta变量
# 模型参数初始化或迭代优化过程中的初始点。
theta = np.ones(X_train.shape[1])
lamda = 1
result_cost = reg_cost(theta, X_train, y_train, lamda)print(result_cost)  # 303.9931922202643
# 梯度
def reg_gradient(theta, X, y, lamda):grad = (X @ theta - y.flatten()) @ Xreg = lamda * thetareg[0] = 0  # 不改变维度,直接赋值为0第一行不参与运算return (grad + reg) / (len(X))# 测试梯度
result_gradient = reg_gradient(theta, X_train, y_train, lamda)
print(result_gradient)  # [-15.30301567 598.25074417]
4.1.3绘制线性模型
# 这个训练过程可以用来训练各种不同的机器学习模型,如线性回归、逻辑回归等
'''参数特征矩阵 X、目标变量 y 和正则化参数 lambda 作为输入,并返回通过最小化代价函数得到的模型参数 theta
theta = np.ones(X.shape[1]): 初始化模型参数theta,将其设置为全1数组,X.shape[1]表示 X列数 即特征的数量
res = minimize...:使用优化算法minimize()最小化损失函数fun,并得到最优的模型参数'''def train_model(X, y, lamda):theta = np.ones(X.shape[1])res = minimize(fun=reg_cost,  # 损失函数x0=theta,  # 初始参数值args=(X, y, lamda),  # 附加参数method='TNC',  # 使用TNC算法进行优化jac=reg_gradient)  # 表示损失函数的梯度函数return res.x  # 返回通过优化算法得到的最优模型参数theta# lamda目前不使用,因为是线性模型不会过拟合
theta_final = train_model(X_train, y_train, lamda=0)# 使用线性回归拟合数据
# 调用plot_data函数
plot_data()
# x轴只取第2列
plt.plot(X_train[:, 1], X_train @ theta_final, c='r')
plt.show()  # 查看会发现,偏差非常大,处于欠拟合的状态

在这里插入图片描述

5.绘制样本个数VS误差

# 任务:训练样本从1开始递增进行训练,比较训练集和验证集上的损失函数的变化情况,观察一下误差的变化情况
# 定义一个函数展现整个学习过程,即随着样本数量的增加,巡礼那几成本和验证集成本的学习误差的曲线
def plot_learning_curve(X_train, y_train, X_val, y_val, lamda):# 使用列表x存放训练样本的个数x = range(1, len(X_train) + 1)# 再定义两个空列表分别存放:验证集和训练集损失函数training_cost = []cv_cost = []# 遍历x中的每个元素,表述不断增加训练样本的数量来计算学习曲线for i in x:# 调用train_model()函数,输入前i个训练样本和相应的目标值,以及正则化参数lamda,返回模型的参数结果res# X_train[:i, :]将返回训练数据集中的前 i 行的所有列res = train_model(X_train[:i, :], y_train[:i, :], lamda)# 调用reg_cost()函数,计算使用前i个训练样本拟合得到的模型在训练集上的损失函数值train_cost_i = reg_cost(res, X_train[:i, :], y_train[:i, :], lamda)# 调用reg_cost()函数,计算使用前i个训练样本拟合得到的模型在验证集上的损失函数值cv_cost_i = reg_cost(res, X_val, y_val, lamda)# 将训练集和验证集的损失函数值分别添加到两个列表中training_cost.append(train_cost_i)cv_cost.append(cv_cost_i)# 横轴为训练样本的数量 x,纵轴为对应的训练集和验证集的损失函数值。plt.plot(x, training_cost, label='training cost')plt.plot(x, cv_cost, label='cv cost')# 显示图例,标明不同曲线的含义plt.legend()# 设置横轴和纵轴的标签plt.xlabel('number of training examples')plt.ylabel('error')# 显示绘制的学习曲线图plt.show()# 传入相应的训练集、验证集以及正则化参数,可以绘制出学习曲线来评估模型的性能和训练集大小对模型的影响
plot_learning_curve(X_train, y_train, X_val, y_val, lamda=0)

在这里插入图片描述
由图可知,随着样本数量的增加,训练集成本的误差逐渐上升,而验证集成本误差逐渐下降。最终,训练集和验证集的误差都比较大,属于高偏差,即模型是欠拟合的,那么如何改进呢?

6.多项式特征、归一化

已经知道简单的线性模型造成了欠拟合,那么如何解决呢?
我们可以计算Jtrain(θ)和Jcv(θ)

  • 如果两者同时很大,则是存在高偏差问题,欠拟合
  • 如果Jcv(θ)比Jtrain(θ)大很多,则存在高方差问题,过拟合

高方差的解决方案
1.采集更多样本数据
2.减少特征数量,去除非主要的特征
3.增加正则化参数λ
高偏差的解决方案
1.引入更多的相关特征
2.采用多项式特征
3.减小正则化参数λ

为解决高偏差问题,由于我们未使用λ,也只有水位一个特征,所以还剩下第2个解决方案,即采取多项式特征
在这里插入图片描述

# 任务:构造多项式特征(将原本只有一列的特征x通过生成高阶次项创造多个特征),进行多项式回归
'''多项式特征生成函数
X:传入特征矩阵X和多项式阶数power
用于生成具有不同阶数多项式特征的新特征矩阵,帮助模型更好拟合非线性关系'''def poly_feature(X, power):for i in range(2, power + 1):  # 循环从2到给定的多项式阶数power+1# 在输入特征矩阵X 的最后一列插入一列# 首先使用 np.power() 函数计算原始特征矩阵 X 的第二列(索引为 1)的 i 次方。X[:, 1] 表示取出矩阵 X 的所有行的第二列。# 然后,使用 np.insert() 函数将得到的新特征插入到矩阵 X 的最后一列。具体而言,X.shape[1] 返回 X 的列数,即特征的数量,axis=1 表示按列方向插入数据。# 通过这样的操作,我们将生成新的特征矩阵 X,其中包含了原始特征的不同次幂的组合。X = np.insert(X, X.shape[1], np.power(X[:, 1], i), axis=1)return X'''计算特征矩阵 X 的每个特征的均值和方差
这些统计信息在数据处理中经常被用来进行特征缩放、归一化等操作,以提高模型训练的效果
计算均值和方差时应使用训练集的统计信息'''def get_means_stds(X):# 使用 np.mean() 函数计算特征矩阵 X 沿着轴 0(列)的均值。# 这意味着函数将对特征矩阵 X 的每列进行均值和标准差的计算,也就是计算每个特征的均值和标准差。# 返回一个包含每个特征的均值的数组 meansmeans = np.mean(X, axis=0)# 方差stds = np.std(X, axis=0)return means, stds'''
特征归一化函数,接收特征矩阵X,均值数组means、方差数组stds作为输入
并返回归一化后的特征矩阵X
注:特征归一化是一种常见的数据预处理操作,可以提高模型训练效果,并确保不同特征之间的尺度差异不会对模型产生不良影响
通常情况下,归一化处理使用训练集进行'''def feature_normalize(X, means, stds):# 第一列假设为常数项或类别信息,不需要进行归一化操作X[:, 1:] = (X[:, 1:] - means[1:]) / stds[1:]return X# 测试
power = 6
# 对训练集、验证集、测试集分别调用 多项式特征生成函数
X_train_poly = poly_feature(X_train, power)
X_val_poly = poly_feature(X_val, power)
X_test_poly = poly_feature(X_test, power)
# 获取训练集的均值和方差
train_means, train_stds = get_means_stds(X_train_poly)
# 对训练集、验证集、测试集进行归一化处理
X_train_norm = feature_normalize(X_train_poly, train_means, train_stds)
X_val_norm = feature_normalize(X_val_poly, train_means, train_stds)
X_test_norm = feature_normalize(X_test_poly, train_means, train_stds)
# 获取最优的theta参数
theta_fit = train_model(X_train_norm, y_train, lamda=0)'''绘制多项式拟合曲线的函数 plot_poly_fit()。
首先调用了之前定义的 plot_data() 函数,将训练数据集的散点图显示在图形界面中。然后使用训练得到的最优模型参数 theta_fit,在图形界面中绘制多项式拟合曲线'''def plot_poly_fit():# 调用其可以在图形界面中显示训练集的散点图,帮助我们观察特征和标签之间的关系# 对于理解数据集、探索数据、以及选择适当的模型都非常有帮助plot_data()x = np.linspace(-60, 60, 100)  # 生成一个包含100个等间距数值的数组,范围从-60到60。这个数组将作为 X 轴的取值范围xx = x.reshape(100, 1)  # 将数组 x 进行形状变换,改为一个100行1列的二维数组。这样做是为了满足多项式特征的输入格式要求xx = np.insert(xx, 0, 1, axis=1)  # 在数组 xx 的第一列插入全1的列向量。这是为了与之前的训练数据集保持一致,添加了一个截距项xx = poly_feature(xx, power)  # 将原始特征矩阵 xx 转化为多项式特征矩阵。这样可以根据多项式的阶数 power 扩展特征xx = feature_normalize(xx, train_means,train_stds)  # 对多项式特征矩阵 xx 进行归一化处理。这里使用训练数据集的均值 train_means和方差train_stds 进行归一化,保证与之前的训练数据集保持一致plt.plot(x, xx @ theta_fit,'r--')  # 绘制多项式拟合曲线,x为 X 轴,xx @ theta_fit 表示通过最优模型参数 theta_fit 对多项式特征矩阵 xx 进行预测得到的 Y 轴坐标。'r--' 表示以红色虚线的形式进行绘制plt.show()# 通过调用 plot_poly_fit() 函数,可以在图形界面中显示训练数据集的散点图,并绘制多项式拟合曲线。这有助于直观地观察拟合效果,并评估模型的性能。
plot_poly_fit()

在这里插入图片描述

7.lamda正则化参数的选取对模型的影响

7.1不使用lamda,将其设置为0

# 正则化影响 lamda设为0,因为正则化只在训练时才有
# 通过绘制学习曲线的误差函数,来看出它在训练集和验证集上表现为过拟合
plot_learning_curve(X_train_norm, y_train, X_val_norm, y_val, lamda=0)  # 高方差,过拟合

在这里插入图片描述
由上图可以看出训练集的误差几乎为0,而验证集的误差还比较高,这表示目前模型状态为高方差,表现为过拟合。

7.2将lamda设置为1

使用正则化是解决过拟合的好办法。通过使用lamda,将它从0变成1,即为开启正则化。

# 使用正则化解决过拟合,通过设置lamda参数,此处设置为1
plot_learning_curve(X_train_norm, y_train, X_val_norm, y_val, lamda=1)  # 绘制使用lamda之后的学习曲线误差图像

在这里插入图片描述
画出使用正则化之后的学习曲线误差函数。可以看出,此时训练集的误差仍然很低,但不是0了,而验证集的误差也降低到一个很低的状态

7.3将lamda设置为很大很大

# 将lamda调整为100,此时lamda过大,导致欠拟合
plot_learning_curve(X_train_norm, y_train, X_val_norm, y_val, lamda=100)  # 欠拟合

在这里插入图片描述

把lamda调整为很大时,这时训练集和验证集的误差会很接近,但是都会很大,此时是欠拟合

7.4设置一组lamda

那lamda应该要取多少合适?下面进行正则化参数lamda的选取

# 设定存储lamda参数的列表,进行正则化参数lamda的选取
lamdas = [0, 0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1, 3, 10]
training_cost = []
cv_cost = []
for lamda in lamdas:res = train_model(X_train_norm, y_train, lamda)tc = reg_cost(res, X_train_norm, y_train, lamda=0)  # lamda设置为0,因为reg_cost这一步还未进行正则化cv = reg_cost(res, X_val_norm, y_val, lamda=0)training_cost.append(tc)cv_cost.append(cv)
plt.plot(lamdas, training_cost, label='training cost')
plt.plot(lamdas, cv_cost, label='cv cost')
plt.legend()
# 设置横轴和纵轴的标签
plt.xlabel('lamdas')
plt.ylabel('cost')
plt.show()

在这里插入图片描述
从图中可以看出lamda在2~4之间时的cv cost最小

7.5找出最小的cv_cost对应的lamda

# 找出最小的cv_cost对应的lamda
# 通过执行 np.argmin(cv_cost),我们会得到最小成本值cv_cost的索引。然后,我们可以使用这个索引来访问 lamdas 列表,找到对应的正则化参数 lamda。
min_cost_cv = lamdas[np.argmin(cv_cost)]
print(min_cost_cv)  # 3

7.6将训练得到的参数应用到测试集上

res = train_model(X_train_norm, y_train, lamda=3)
test_cost = reg_cost(res, X_test_norm, y_test, lamda=0)
print(test_cost)  # 4.3976161577441975

完整代码

import numpy as np
import matplotlib.pyplot as plt
from scipy.io import loadmat
from scipy.optimize import minimize'''在本练习中,您将实现正则化线性回归,并使用它来研究具有不同偏差-方差特性的模型。
在练习的前半部分,您将实现正则化线性回归,利用水库水位的变化来预测从大坝流出的水量。
在后半部分中,您将对调试学习算法进行一些诊断,并检查偏差和偏差的影响。'''
# 导入数据集
data = loadmat('ex5data1.mat')# 打印data字典里的键  1. X和y训练集数据  2. Xtest和ytest是测试集数据  3.Xval和yval是验证集数据
# dict_keys(['__header__', '__version__', '__globals__', 'X', 'y', 'Xtest', 'ytest', 'Xval', 'yval'])
print('打印data字典里的键:',data.keys())  # 打印data字典里的键: dict_keys(['__header__', '__version__', '__globals__', 'X', 'y', 'Xtest', 'ytest', 'Xval', 'yval'])# 训练集
X_train, y_train = data['X'], data['y']
print('打印训练集维度:', X_train.shape, y_train.shape)  # (12, 1) (12, 1) 表明有12个样本,1个特征# 验证集
X_val, y_val = data['Xval'], data['yval']
print('打印验证集维度:', X_val.shape, y_val.shape)  # (21, 1) (21, 1)表明有21个样本,1个特征# 测试集
X_test, y_test = data['Xtest'], data['ytest']
print('打印测试集维度:', X_test.shape, y_test.shape)  # (21, 1) (21, 1) 表明有21个样本,1个特征# 插入一列,添加偏置项
X_train = np.insert(X_train, 0, 1, axis=1)
X_val = np.insert(X_val, 0, 1, axis=1)
X_test = np.insert(X_test, 0, 1, axis=1)'''绘制散点图的函数 plot_data()。
它使用训练数据集的特征和标签来创建一个散点图,以可视化特征与标签之间的关系。'''def plot_data():fig, ax = plt.subplots()  # 创建图形对象(fig)和一个坐标轴对象(ax)# 使用scatter函数绘制散点图,      X_train[:, 1]表示   使用训练数据集中第二列特征作为X轴坐标  水位的变化#                              y_train表示        使用训练数据集中的标签作为Y轴坐标      出水量# 按照每个样本的特征和标签的取值,在散点图显示它们之间的关系ax.scatter(X_train[:, 1], y_train)ax.set(xlabel='change in water level(x)',ylabel='water flowing out the dam(y)')# 调用plot_data函数,看原始数据分布散点图
plot_data()# 显示图形
plt.show()# 损失函数
def reg_cost(theta, X, y, lamda):cost = np.sum(np.power((X @ theta - y.flatten()), 2))reg = theta[1:] @ theta[1:] * lamda  # 第一项不参与正则化return (cost + reg) / (2 * len(X))# 测试 损失函数
# X_train.shape[1]表示训练数据集X_train的列数,也就是特征的个数。
# 然后,使用np.ones()函数创建了一个元素均为1的数组,并赋值给theta变量
# 模型参数初始化或迭代优化过程中的初始点。
theta = np.ones(X_train.shape[1])
lamda = 1
result_cost = reg_cost(theta, X_train, y_train, lamda)print(result_cost)  # 303.9931922202643# 梯度
def reg_gradient(theta, X, y, lamda):grad = (X @ theta - y.flatten()) @ Xreg = lamda * thetareg[0] = 0  # 不改变维度,直接赋值为0第一行不参与运算return (grad + reg) / (len(X))# 测试梯度
result_gradient = reg_gradient(theta, X_train, y_train, lamda)print(result_gradient)  # [-15.30301567 598.25074417]# 这个训练过程可以用来训练各种不同的机器学习模型,如线性回归、逻辑回归等
'''参数特征矩阵 X、目标变量 y 和正则化参数 lambda 作为输入,并返回通过最小化代价函数得到的模型参数 theta
theta = np.ones(X.shape[1]): 初始化模型参数theta,将其设置为全1数组,X.shape[1]表示 X列数 即特征的数量
res = minimize...:使用优化算法minimize()最小化损失函数fun,并得到最优的模型参数'''def train_model(X, y, lamda):theta = np.ones(X.shape[1])res = minimize(fun=reg_cost,  # 损失函数x0=theta,  # 初始参数值args=(X, y, lamda),  # 附加参数method='TNC',  # 使用TNC算法进行优化jac=reg_gradient)  # 表示损失函数的梯度函数return res.x  # 返回通过优化算法得到的最优模型参数theta# lamda目前不使用,因为是线性模型不会过拟合
theta_final = train_model(X_train, y_train, lamda=0)# 使用线性回归拟合数据
# 调用plot_data函数
plot_data()
# x轴只取第2列
plt.plot(X_train[:, 1], X_train @ theta_final, c='r')
plt.show()  # 查看会发现,偏差非常大,处于欠拟合的状态# 任务:训练样本从1开始递增进行训练,比较训练集和验证集上的损失函数的变化情况,观察一下误差的变化情况
# 定义一个函数展现整个学习过程,即随着样本数量的增加,巡礼那几成本和验证集成本的学习误差的曲线
def plot_learning_curve(X_train, y_train, X_val, y_val, lamda):# 使用列表x存放训练样本的个数x = range(1, len(X_train) + 1)# 再定义两个空列表分别存放:验证集和训练集损失函数training_cost = []cv_cost = []# 遍历x中的每个元素,表述不断增加训练样本的数量来计算学习曲线for i in x:# 调用train_model()函数,输入前i个训练样本和相应的目标值,以及正则化参数lamda,返回模型的参数结果res# X_train[:i, :]将返回训练数据集中的前 i 行的所有列res = train_model(X_train[:i, :], y_train[:i, :], lamda)# 调用reg_cost()函数,计算使用前i个训练样本拟合得到的模型在训练集上的损失函数值train_cost_i = reg_cost(res, X_train[:i, :], y_train[:i, :], lamda)# 调用reg_cost()函数,计算使用前i个训练样本拟合得到的模型在验证集上的损失函数值cv_cost_i = reg_cost(res, X_val, y_val, lamda)# 将训练集和验证集的损失函数值分别添加到两个列表中training_cost.append(train_cost_i)cv_cost.append(cv_cost_i)# 横轴为训练样本的数量 x,纵轴为对应的训练集和验证集的损失函数值。plt.plot(x, training_cost, label='training cost')plt.plot(x, cv_cost, label='cv cost')# 显示图例,标明不同曲线的含义plt.legend()# 设置横轴和纵轴的标签plt.xlabel('number of training examples')plt.ylabel('error')# 显示绘制的学习曲线图plt.show()# 传入相应的训练集、验证集以及正则化参数,可以绘制出学习曲线来评估模型的性能和训练集大小对模型的影响
plot_learning_curve(X_train, y_train, X_val, y_val, lamda=0)
# 由图可知,随着样本数量的增加,训练集成本的误差逐渐上升,而验证集成本误差逐渐下降。
# 目前训练集和验证集的误差都比较高,表示模型欠拟合# 上述简单的线性模型导致了欠拟合,存在高偏差如何解决?
# 任务:构造多项式特征(将原本只有一列的特征x通过生成高阶次项创造多个特征),进行多项式回归
'''多项式特征生成函数
X:传入特征矩阵X和多项式阶数power
用于生成具有不同阶数多项式特征的新特征矩阵,帮助模型更好拟合非线性关系'''def poly_feature(X, power):for i in range(2, power + 1):  # 循环从2到给定的多项式阶数power+1# 在输入特征矩阵X 的最后一列插入一列# 首先使用 np.power() 函数计算原始特征矩阵 X 的第二列(索引为 1)的 i 次方。X[:, 1] 表示取出矩阵 X 的所有行的第二列。# 然后,使用 np.insert() 函数将得到的新特征插入到矩阵 X 的最后一列。具体而言,X.shape[1] 返回 X 的列数,即特征的数量,axis=1 表示按列方向插入数据。# 通过这样的操作,我们将生成新的特征矩阵 X,其中包含了原始特征的不同次幂的组合。X = np.insert(X, X.shape[1], np.power(X[:, 1], i), axis=1)return X'''计算特征矩阵 X 的每个特征的均值和方差
这些统计信息在数据处理中经常被用来进行特征缩放、归一化等操作,以提高模型训练的效果
计算均值和方差时应使用训练集的统计信息'''def get_means_stds(X):# 使用 np.mean() 函数计算特征矩阵 X 沿着轴 0(列)的均值。# 这意味着函数将对特征矩阵 X 的每列进行均值和标准差的计算,也就是计算每个特征的均值和标准差。# 返回一个包含每个特征的均值的数组 meansmeans = np.mean(X, axis=0)# 方差stds = np.std(X, axis=0)return means, stds'''
特征归一化函数,接收特征矩阵X,均值数组means、方差数组stds作为输入
并返回归一化后的特征矩阵X
注:特征归一化是一种常见的数据预处理操作,可以提高模型训练效果,并确保不同特征之间的尺度差异不会对模型产生不良影响
通常情况下,归一化处理使用训练集进行'''def feature_normalize(X, means, stds):# 第一列假设为常数项或类别信息,不需要进行归一化操作X[:, 1:] = (X[:, 1:] - means[1:]) / stds[1:]return X# 测试
power = 6
# 对训练集、验证集、测试集分别调用 多项式特征生成函数
X_train_poly = poly_feature(X_train, power)
X_val_poly = poly_feature(X_val, power)
X_test_poly = poly_feature(X_test, power)
# 获取训练集的均值和方差
train_means, train_stds = get_means_stds(X_train_poly)
# 对训练集、验证集、测试集进行归一化处理
X_train_norm = feature_normalize(X_train_poly, train_means, train_stds)
X_val_norm = feature_normalize(X_val_poly, train_means, train_stds)
X_test_norm = feature_normalize(X_test_poly, train_means, train_stds)
# 获取最优的theta参数
theta_fit = train_model(X_train_norm, y_train, lamda=0)'''绘制多项式拟合曲线的函数 plot_poly_fit()。
首先调用了之前定义的 plot_data() 函数,将训练数据集的散点图显示在图形界面中。然后使用训练得到的最优模型参数 theta_fit,在图形界面中绘制多项式拟合曲线'''def plot_poly_fit():# 调用其可以在图形界面中显示训练集的散点图,帮助我们观察特征和标签之间的关系# 对于理解数据集、探索数据、以及选择适当的模型都非常有帮助plot_data()x = np.linspace(-60, 60, 100)  # 生成一个包含100个等间距数值的数组,范围从-60到60。这个数组将作为 X 轴的取值范围xx = x.reshape(100, 1)  # 将数组 x 进行形状变换,改为一个100行1列的二维数组。这样做是为了满足多项式特征的输入格式要求xx = np.insert(xx, 0, 1, axis=1)  # 在数组 xx 的第一列插入全1的列向量。这是为了与之前的训练数据集保持一致,添加了一个截距项xx = poly_feature(xx, power)  # 将原始特征矩阵 xx 转化为多项式特征矩阵。这样可以根据多项式的阶数 power 扩展特征xx = feature_normalize(xx, train_means,train_stds)  # 对多项式特征矩阵 xx 进行归一化处理。这里使用训练数据集的均值 train_means和方差train_stds 进行归一化,保证与之前的训练数据集保持一致plt.plot(x, xx @ theta_fit,'r--')  # 绘制多项式拟合曲线,x为 X 轴,xx @ theta_fit 表示通过最优模型参数 theta_fit 对多项式特征矩阵 xx 进行预测得到的 Y 轴坐标。'r--' 表示以红色虚线的形式进行绘制plt.show()# 通过调用 plot_poly_fit() 函数,可以在图形界面中显示训练数据集的散点图,并绘制多项式拟合曲线。这有助于直观地观察拟合效果,并评估模型的性能。
plot_poly_fit()# 正则化影响 lamda设为0,因为正则化只在训练时才有
# 通过绘制学习曲线的误差函数,来看出它在训练集和验证集上表现为过拟合
plot_learning_curve(X_train_norm, y_train, X_val_norm, y_val, lamda=0)  # 高方差,过拟合# 使用正则化解决过拟合,通过设置lamda参数,此处设置为1
plot_learning_curve(X_train_norm, y_train, X_val_norm, y_val, lamda=1)  # 绘制使用lamda之后的学习曲线误差图像# 将lamda调整为100,此时lamda过大,导致欠拟合
plot_learning_curve(X_train_norm, y_train, X_val_norm, y_val, lamda=100)  # 欠拟合# 设定存储lamda参数的列表,进行正则化参数lamda的选取
lamdas = [0, 0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1, 3, 10]
training_cost = []
cv_cost = []
for lamda in lamdas:res = train_model(X_train_norm, y_train, lamda)tc = reg_cost(res, X_train_norm, y_train, lamda=0)  # lamda设置为0,因为reg_cost这一步还未进行正则化cv = reg_cost(res, X_val_norm, y_val, lamda=0)training_cost.append(tc)cv_cost.append(cv)
plt.plot(lamdas, training_cost, label='training cost')
plt.plot(lamdas, cv_cost, label='cv cost')
plt.legend()
# 设置横轴和纵轴的标签
plt.xlabel('lamdas')
plt.ylabel('cost')
plt.show()
# 找出最小的cv_cost对应的lamda
# 通过执行 np.argmin(cv_cost),我们会得到最小成本值cv_cost的索引。然后,我们可以使用这个索引来访问 lamdas 列表,找到对应的正则化参数 lamda。
min_cost_cv = lamdas[np.argmin(cv_cost)]
print(min_cost_cv)  # 3
res = train_model(X_train_norm, y_train, lamda=3)
test_cost = reg_cost(res, X_test_norm, y_test, lamda=0)
print(test_cost)  # 4.3976161577441975

参考链接:https://www.bilibili.com/video/BV1p4411o7sq/?p=6&spm_id_from=pageDriver&vd_source=b3d1b016bccb61f5e11858b0407cc54e

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/86965.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[论文分享] How to Better Utilize Code Graphs in Semantic Code Search?

How to Better Utilize Code Graphs in Semantic Code Search? [ESEC/FSE 2022] 语义代码搜索极大地促进了软件的重用,使用户能够找到与用户指定的自然语言查询高度匹配的代码片段。由于代码图(如控制流图和程序依赖图)丰富的表达能力,两种主流的研究工…

Flutter图标

https://fluttericon.cn/ Flutter 内置了丰富的图标。 Icon(Icons.ac_unit)

【腾讯云国际站】CDN内容分发网络特性介绍

为什么使用腾讯云国际站 CDN 内容分发网络? 当用户直接访问源站中的静态内容时,可能面临的体验问题: 客户离服务器越远,访问速度越慢。客户数量越多,网络带宽费用越高。跨境用户访问体验较差。 腾讯云国际站CDN 如何改…

idea中maven项目打包成jar,报错没有主清单属性解决方法

使用idea自带的打包可能会出现一下问题 在pom.xml中引入下面的依赖&#xff0c;即可解决 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions&…

MySQL数据库的存储引擎

目录 一、存储引擎概念 二、存储引擎 2.1MyISAM 2.11MyISAM的特点 2.12MyISAM表支持3种不同的存储格式&#xff1a; 2.2 InnoDB 2.21InnoDB特点介绍 三、InnoDB与MyISAM 区别 四、怎么样选择存储引擎 五、查看存储引擎 六、查看表使用的存储引擎 七、修改存储引擎 …

Java代码审计17之fastjson反序列化漏洞(2)

文章目录 1、类加载与反射调用1.1、类加载1.2、测试代码1.3、通过类的加载和反射调用evil类 2、Fastjson TemplatesImpl链调试2.1、链路总览2.2、调试构造利用链 3、fastjson反序列化TemplatesImpl 利⽤3.1、开启 Feature.SupportNonPublicField 得作用3.2、构造利用payload3.3…

iphone的safari浏览器实现全屏的pwa模式,并修改顶部状态栏背景颜色

要想修改顶部背景颜色&#xff0c;需要用到这个属性&#xff1a;content就是你要设置的颜色 <!-- 状态栏的背景色 --><meta name"theme-color" content"#f8f8f8" /> 然后再加上下面的设置&#xff1a; <!-- 网站开启对 web app 程序的支持…

MySQL(8) 优化、MySQL8、常用命令

一、MySQL优化 从上图可以看出SQL及索引的优化效果是最好的&#xff0c;而且成本最低&#xff0c;所以工作中我们要在这块花更多时间。 服务端参数配置&#xff1b; max_connections3000 连接的创建和销毁都需要系统资源&#xff0c;比如内存、文件句柄&#xff0c;业务说的支持…

Hello World启示录:Java编程的起点

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、Java基本结构1、一个简单的Java程序2、运行Java程序3、JDK | JRE | JVM之间的关系 二、代码注释标准1、注释规则2、注释规范…

如何取消显示Notepad++每行显示的CRLF符号

新电脑中重新安装了Nodepad&#xff0c;打开记事本后发现出现了许多黑底的CR|LF标记&#xff0c;特别碍眼。 如何取消呢&#xff1f; 视图 -> 显示符号 -> 取消勾选 显示行尾符操作步骤 预期效果

010_第一代软件开发(二)

第一代软件开发(二) 文章目录 第一代软件开发(二)项目介绍界面布局功能完善快照功能获取可用串口播放按键提示音 关键字&#xff1a; Qt、 Qml、 QSerialPort、 QPixmap、 QSoundEffect 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff…

法线贴图的视线原理

在上一篇文章中详细介绍了位移贴图的相关知识&#xff0c;在本章中我们继续讲述法线贴图的相关概念&#xff0c;文章后面继续用GLTF 编辑器 来演示下法线贴图的模型渲染效果。 1、什么是法线贴图 法线贴图&#xff08;Normal Map&#xff09;是一种纹理映射技术&#xff0c;用…

【kohya】训练自己的LoRA模型

文章目录 序言准备环境准备图片处理图片下载kohya_ss代码修改pyvenv.cfg启动界面访问地址生成字幕准备训练的文件夹配置训练参数开始训练遇到的问题&#xff1a; 序言 在把玩stable diffusion的webUI和comfyUI后&#xff0c;思考着自己也微调一个个性化风格的checkpoint、LyCO…

2023 “华为杯” 中国研究生数学建模竞赛(D题)深度剖析|数学建模完整代码+建模过程全解全析

问题一&#xff1a;区域碳排放量以及经济、人口、能源消费量的现状分析 思路&#xff1a; 定义碳排放量 Prediction 模型: CO2 P * (GDP/P) * (E/GDP) * (CO2/E) 其中: CO2:碳排放量 P:人口数量 GDP/P:人均GDP E/GDP:单位GDP能耗 CO2/E:单位能耗碳排放量 2.收集并统计相关…

8应用服务与领域服务

本系列包含以下文章&#xff1a; DDD入门DDD概念大白话战略设计代码工程结构请求处理流程聚合根与资源库实体与值对象应用服务与领域服务&#xff08;本文&#xff09;领域事件CQRS 案例项目介绍 # 既然DDD是“领域”驱动&#xff0c;那么我们便不能抛开业务而只讲技术&…

ElasticSearch - 索引库和文档相关命令操作

目录 一、ElasticSearch 索引库操作 1.1、mapping 属性 1.2、索引库相关操作 1.2.1、创建索引库 1.2.2、增加和删除索引库 1.2.3、修改索引库 1.3、文档操作 1.3.1、添加文档 1.3.2、文档的查询和删除 1.3.3、修改文档 1.全量修改&#xff1a;会先删除旧文档&#xf…

基于springboot消防员招录系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

vue-cli创建项目、vue项目目录结(运行vue项目)、ES6导入导出语法、vue项目编写规范

vue-cli创建项目、vue项目目录结构、 ES6导入导出语法、vue项目编写规范 1 vue-cli创建项目 1.1 vue-cli 命令行创建项目 1.2 使用vue-cli-ui创建 2 vue项目目录结构 2.1 运行vue项目 2.2 vue项目的目录结构 3 es6导入导出语法 4 vue项目编写规范 4.1 修改项目 4.2 以后…

【深度学习推荐系统 工程篇】三、浅析FastTransFormer看 GPU推理优化 思路

前言 在搜索/推荐场景中&#xff08;一般是CTR/CVR预估&#xff09;Serving的模型一般是稀疏参数占比比较大&#xff0c;工程落地方面会遇到两方面的困难&#xff1a; 稀疏参数的存储/IO网络结构的优化 对于稀疏参数的存储/IO&#xff0c;在上一篇【深度学习推荐系统 工程篇…

电子信息工程专业课复习知识点总结:(五)通信原理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 第一章通信系统概述——通信系统的构成、各部分性质、性能指标1.通信系统的组成&#xff1f;2.通信系统的分类&#xff1f;3.调制、解调是什么&#xff1f;有什么用…