失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > [从0开始机器学习]8.过拟合问题和正则化方法

[从0开始机器学习]8.过拟合问题和正则化方法

时间:2021-04-09 11:12:20

相关推荐

[从0开始机器学习]8.过拟合问题和正则化方法

🐺本博主博客:ζั͡ ั͡雾 ั͡狼 ั͡✾的博客

🎀专栏:机器学习

🎀专栏:爬虫

🎀专栏:OpenCV图像识别处理

🎀专栏:Unity2D

⭐本节课理论视频:P39-P42.过拟合和正则化

⭐本节课推荐其他人笔记:

过拟合问题_XHHP的博客

🐺机器学习通过文字描述是难以教学学会的,每一节课我会推荐这个理论的网课,一定要看上面的理论视频!一定要看上面的理论视频!一定要看上面的理论视频!所以我只是通过代码实现,并通过注释形式来详细讲述每一步的原因,最后通过画图对比的新式来看结果比较。

⭐机器学习推荐博主:GoAI的博客_CSDN博客-深度学习,机器学习,大数据笔记领域博主

😊如果你什么都不懂机器学习,那我推荐GoAI的入门文章:机器学习知识点全面总结_GoAI的博客-CSDN博客_机器学习笔记

过拟合问题是由于你拟合的变量阶次太高,回归问题表现在俩点直接抖动的情况,分类问题表现在分割每一个局部特殊点。解决方法就是给代价函数加上正则化项用来惩罚系数矩阵过大,对常数项不惩罚的情况:

注意seita0也就是常数项还是原来的规则

以一元n次回归的过拟合情况举例:

以下面代码为例子:

import numpy as npimport matplotlib.pyplot as plt# 全局变量# 生成数据# k0代表常数,x0恒为1x = np.array(range(4))# 随机生成一些系数ranK = np.random.random((1, 5)).ravel() * 50# 随机生成Y中的数据Y =np.array([1,5,3,6])X = np.array([x]).T # 将x变成矩阵并转置,构成第一个元# 根据要拟合的次方构建X矩阵power = eval(input("请输入你要拟合函数的最高次方:"))for i in range(2, power + 1): # 第一列数据就是原来的数据不需要插入X = np.insert(X, i - 1, values=np.power(x, i), axis=1)print(X, X[0], len(X[0]))# 进行归一化操作# 获取每列平均值u = np.average(X, axis=0)# 获取没列的标准差s = np.std(X, axis=0)# 按行复制,构成X同形状矩阵U = np.repeat([u], len(X), axis=0)print(U)S = np.repeat([s], len(X), axis=0)# 归一化,注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并X = (X - U) / S# 开始# 学习率,在代价函数斜率线上移动的距离步子大小A = 0.01# 迭代次数time = 100000# X矩阵中第一列加入x0=1参数X = np.insert(X, 0, np.ones((1, len(X))), axis=1)# 数据个数m = len(X)# 参数个数n = len(X[0])# 输出print(f"有{n}个参数,就是X列数算上常数项所乘的单位1")print(f"有{m}条数据,就是加常数后X行数")# 系数变量K矩阵就是多元参数的系数,就是我们要递归的重点变量,先给这个矩阵的每个值都赋予初始值1K = np.ones(n)# 假设函数,假设是个多元线性函数,每个参数的系数和常数不知道,是要回归算的变量# 返回系数矩阵乘参数矩阵# 下面的变量Xi代表一条数据,既X矩阵的一行def H(Xi):global Kreturn np.dot(K, Xi.T) # xi需要转置,才能得到内积和# 代价函数L=求和((H(x)-y(x))^2),其中H是关于K矩阵中所有系数参数的函数# 代价函数就是你估算的值与实际值的差的大小,使得代价函数最小,这样就能不断逼近结果# 使得代价函数最小,就要使得初始点在斜率线上不断往低处移动,呈现出系数的不断微小移动# 注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并# 固定公式格式,推导原理看吴恩达P11def dL_K(): # 代价函数对矩阵中系数参数k求导global X, Y, K, m, ndL_Karr = np.empty(n) # 数组用来存放L对每个k求导后的结果for j in range(n):ans = 0for i in range(m):ans += ((H(X[i]) - Y[i]) * X[i][j]) # 由于k的系数是x,所以求导后还要乘xdL_Karr[j] = ansreturn dL_Karrdef itreation(time): # 迭代,使O1,O2的代价函数趋于最低点global Kfor i in range(time + 1):# 一次迭代过程中代价函数对系数k的导数数组dL_Karr = dL_K()# 同时变化,减法原因是正斜率使得O更小,负斜率使得O更大,不断往低处移动即代价函数最小K = K - A * dL_Karrif (i % 10000 == 0): # 每100次输出一次print(f"迭代了{i}次,变量的系数矩阵K为{K}")if __name__ == "__main__":print('归一化X', X)itreation(time)print('归一化系数(第一个是常数)', K, )# 注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并# 忽略前一位常数,计算真正系数K[1:] = K[1:] / s# 利用真正系数,计算真正常数K[0] = K[0] - np.sum(K[1:] * u)linex=np.linspace(min(x),max(x),1000)print('真正系数矩阵', K)# 绘图Y1 = np.zeros(len(linex), dtype="float64")for i in range(len(K)):Y1 += (K[i] * np.power(linex, i))fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 5))axes[0].scatter(x, Y, s=3)axes[1].plot(linex, Y1)axes[1].scatter(x, Y, s=3, color="red")axes[1].set_title(str(power) + "power")plt.show()

3次拟合的已经很好

十次抖动出现,过拟合

所以需要正则化

下面是经过正则化的代码,就修改了几行

import numpy as npimport matplotlib.pyplot as plt# 全局变量# 生成数据# k0代表常数,x0恒为1x = np.array(range(4))# 随机生成一些系数ranK = np.random.random((1, 5)).ravel() * 50# 随机生成Y中的数据Y =np.array([1,5,3,6])X = np.array([x]).T # 将x变成矩阵并转置,构成第一个元# 根据要拟合的次方构建X矩阵power = eval(input("请输入你要拟合函数的最高次方:"))for i in range(2, power + 1): # 第一列数据就是原来的数据不需要插入X = np.insert(X, i - 1, values=np.power(x, i), axis=1)print(X, X[0], len(X[0]))# 进行归一化操作# 获取每列平均值u = np.average(X, axis=0)# 获取没列的标准差s = np.std(X, axis=0)# 按行复制,构成X同形状矩阵U = np.repeat([u], len(X), axis=0)print(U)S = np.repeat([s], len(X), axis=0)# 归一化,注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并X = (X - U) / S# 开始# 学习率,在代价函数斜率线上移动的距离步子大小A = 0.01# 迭代次数time = 100000#正则化系数r=0.05# X矩阵中第一列加入x0=1参数X = np.insert(X, 0, np.ones((1, len(X))), axis=1)# 数据个数m = len(X)# 参数个数n = len(X[0])# 输出print(f"有{n}个参数,就是X列数算上常数项所乘的单位1")print(f"有{m}条数据,就是加常数后X行数")# 系数变量K矩阵就是多元参数的系数,就是我们要递归的重点变量,先给这个矩阵的每个值都赋予初始值1K = np.ones(n)# 假设函数,假设是个多元线性函数,每个参数的系数和常数不知道,是要回归算的变量# 返回系数矩阵乘参数矩阵# 下面的变量Xi代表一条数据,既X矩阵的一行def H(Xi):global Kreturn np.dot(K, Xi.T) # xi需要转置,才能得到内积和# 代价函数L=求和((H(x)-y(x))^2),其中H是关于K矩阵中所有系数参数的函数# 代价函数就是你估算的值与实际值的差的大小,使得代价函数最小,这样就能不断逼近结果# 使得代价函数最小,就要使得初始点在斜率线上不断往低处移动,呈现出系数的不断微小移动# 注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并# 固定公式格式,推导原理看吴恩达P11def dL_K(): # 代价函数对矩阵中系数参数k求导global X, Y, K, m, ndL_Karr = np.empty(n) # 数组用来存放L对每个k求导后的结果for j in range(n):ans = 0for i in range(m):ans += ((H(X[i]) - Y[i]) * X[i][j]) # 由于k的系数是x,所以求导后还要乘xdL_Karr[j] = ansreturn dL_Karrdef itreation(time): # 迭代,使O1,O2的代价函数趋于最低点global Kfor i in range(time + 1):# 一次迭代过程中代价函数对系数k的导数数组dL_Karr = dL_K()# 同时变化,减法原因是正斜率使得O更小,负斜率使得O更大,不断往低处移动即代价函数最小K[0]= K[0] - A * dL_Karr[0]/mK[1:] = (1-A*r/m)*K[1:] - A * dL_Karr[1:]/mif (i % 10000 == 0): # 每100次输出一次print(f"迭代了{i}次,变量的系数矩阵K为{K}")if __name__ == "__main__":print('归一化X', X)itreation(time)print('归一化系数(第一个是常数)', K, )# 注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并# 忽略前一位常数,计算真正系数K[1:] = K[1:] / s# 利用真正系数,计算真正常数K[0] = K[0] - np.sum(K[1:] * u)linex=np.linspace(min(x),max(x),1000)print('真正系数矩阵', K)# 绘图Y1 = np.zeros(len(linex), dtype="float64")for i in range(len(K)):Y1 += (K[i] * np.power(linex, i))fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 5))axes[0].scatter(x, Y, s=3)axes[1].plot(linex, Y1)axes[1].scatter(x, Y, s=3, color="red")axes[1].set_title(str(power) + "power")plt.show()

减少了大幅度抖动

如果觉得《[从0开始机器学习]8.过拟合问题和正则化方法》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。