【随机梯度下降法】X特征量对R2score的影响
来源:6-9 有关梯度下降法的更多深入讨论

黄义舜
2022-08-23
老师对不起(>人<;),又要麻烦您了。
在上一次您给我指出数据未进行归一化,进行计算导致程序准确率低,我进行改正就愉快地进行测试了。
在调整m(X的训练量)和n(X的特征数量)参数测试效率的过程中,我惊讶地发现在n越来越大的情况下,准确率会极速下降,而sklearn算法则不会影响,我在想我们实现随机梯度下降法的方式是不是有些许问题,我的代码在n大于60左和从bobo老师那复制的代码在n变大了之后,准确率也都会急速下降,而sklearn则没影响,这个问题我解决不了,也不知道这个问题是否适合我这个阶段研究,不适合我就果断跳过先,
python代码
代码有点多
写出来冗杂,和上一个问题用的是一样的
https://coding.imooc.com/learn/questiondetail/274363.html
jupyter Notebook代码
准备工作
import numpy as np
import matplotlib.pyplot as plt
#这个是我写的线性回归的代码
from nike.LinearRegression import LinearRegression
#这个是从bobo老师哪里复制的线性回归的代码
from nike.LinearRegression import LinearRegression2
定义数据初始化函数
def init(m,n):
#初始化数据
np.random.seed(666)
X = np.random.random(size=(m,n))
true_theta = np.arange(X.shape[1]+1,dtype=float)
X_b = np.concatenate([np.ones((len(X),1)),X],axis=1)
#对y不加噪点,我觉得数据量可能有点大算的有点慢
y = X_b.dot(true_theta)
#归一化+分割数据
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y)
standard = StandardScaler()
standard.fit(X_train)
X_train_standard = standard.transform(X_train)
X_test_standard = standard.transform(X_test)
return X_train_standard, X_test_standard, y_train, y_test
绘制n与socre的曲线
#我自己写的代码
score_history=[]
reg1 = LinearRegression()
#将数据从1-100逐级递增,计算代码准确率并记录,用于绘制n与socre的图形
for i in range(1,120):
X_train_standard, X_test_standard, y_train, y_test=init(1000,i)
reg1.fit_sgd(X_train_standard, y_train)
score_history.append(reg3.score(X_test_standard, y_test))
#绘制图形
plt.plot([i for i in range(len(score_history))],score_history)
plt.axis([0,100, -3,1.2])
plt.xlabel('n')
plt.ylabel('R2-Score value')
plt.show()
#从bobo老师那里复制的代码
score_history=[]
reg2 = LinearRegression2()
#将数据从1-120逐级递增,计算代码准确率并记录,用于绘制n与socre的图形
for i in range(1,120):
X_train_standard, X_test_standard, y_train, y_test=init(1000,i)
reg2.fit_sgd(X_train_standard, y_train)
score_history.append(reg2.score(X_test_standard, y_test))
#绘制图形
plt.plot([i for i in range(len(score_history))],score_history)
plt.axis([0,100, -3,1.2])
plt.xlabel('n')
plt.ylabel('R2-Score value')
plt.show()
#机器学习sklearn
from sklearn.linear_model import SGDRegressor
score_history=[]
reg3 = SGDRegressor()
#将数据从1-120逐级递增,计算代码准确率并记录,用于绘制n与socre的图形
for i in range(1,120):
X_train_standard, X_test_standard, y_train, y_test=init(1000,i)
reg3.fit(X_train_standard, y_train)
score_history.append(reg3.score(X_test_standard, y_test))
#绘制图形
plt.plot([i for i in range(len(score_history))],score_history)
plt.axis([0,100, -3,1.2])
plt.xlabel('n')
plt.ylabel('R2-Score value')
plt.show()
1回答
-
更准确地说,不是我们的实现“有问题”,而是我们的实现可以更好。但是继续优化这个 SGD 的过程已经不是这个课程的目标了。
sklearn 中的 SGD 的原理和我们课程介绍的原理是一致的。但是在细节上,无论是“随机梯度方向的计算”,还是“学习率的自适应变换”,都更加复杂。可以参考这里的公式:https://scikit-learn.org/stable/modules/sgd.html#id5
其中 R 函数和 L 函数的定义参考这里:https://scikit-learn.org/stable/modules/sgd.html#mathematical-formulation
整体,sklearn 中的实现,是在使用一个复杂的公式,去更准确的使用一个数据点,去“估计”梯度最有可能的方向,而非像我们的实现中,简单地直接用这个点去计算梯度。
==========
至于为什么这个公式估计出的梯度更准确,虽然这个问题确实更多出现在机器学习领域,但整体,我倾向于认为这不是一个机器学习的问题,而更多的是一个数值分析的问题。
简单地说,我们要做的事情就是求解让某个公式最大化(或者最小化)对应的参数解。这个问题本身是脱离机器学习领域,而是一个纯粹的“数学问题”。但是解决这个数学问题要依靠计算机(因为可能没有公式解),所以这类问题在计算机领域都可以归入到“数值分析”的篮子里。
最简单的例子,sqrt(1234567),计算机是怎么求解出来的?这就是一个数值分析问题。但通常我们不会考虑这个问题。可是假设你现在遇到的问题,对 sqrt 的精度要求非常高,要求精确到小数点后 100 位,那么标准库中提供的 sqrt 就不能满足你的要求了。你就需要自己写一个算法计算 sqrt 了。大概就是这个意思。
至少在学习机器学习的初期,你可以不去管这些具体的计算过程,而更多的去关注模型的原理。如果以后继续深入机器学习,尤其是要改进机器学习的底层原理的时候(而非仅仅应用的话),可能会去关注这类“数值问题”(但要注意,机器学习算法的改进不仅仅包括这类数值的改进,原理的改进也很重要甚至在机器学习这个领域中,是更重要的。)。届时,可能你需要专门去学习一门课程(或者一个领域),叫“最优化”(Mathematical Optimization),这个领域会更多的去探讨如何能更快更好地去求解一个最优化的式子的解。(最优化其实也是一个大的领域,大多数人工智能专业的硕士生或者博士生一定要学的是“凸优化”。)
如果你想粗糙地了解一下这个领域,可以先看看这个 wiki 词条:https://en.wikipedia.org/wiki/Mathematical_optimization
但整体,在入门阶段,不需要特别深究这些具体的底层计算原理,更多的去掌握整个模型的作用原理。我们在课程汇总实现的代码,主要还是为了让大家了解模型原理的。但是在实践中,还是应该去使用专业的团队经过多年的积累实现的这些库的,这些库的实现通常都是现阶段最优解了(就像如果不出意外,我们应该调用标准库的 sqrt 函数,而非自己实现一个。但我们在学习的时候,要了解 sqrt 是什么意思,做了一件什么事儿。)
继续加油!:)
112022-08-26
相似问题