Lesson 10,2024年最新不了解这些多线程的基础知识很难学懂大数据开发

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
img

正文

| 搜索空间/全域空间 | - | 1536/1536 |
| 运行时间(分钟) | - | 6.36 |
| 搜索最优(RMSE) | 30571.266 | 29179.698 |
| 重建最优(RMSE) | - | 28572.070 |

#打包成函数供后续使用
#评估指标RMSE
def RMSE(cvresult,key):
    return (abs(cvresult[key])\*\*0.5).mean()
​
#计算参数空间大小
def count\_space(param):
    no_option = 1
    for i in param_grid_simple:
        no_option \*= len(param_grid_simple[i])
    print(no_option)
    
#在最优参数上进行重新建模验证结果
def rebuild\_on\_best\_param(ad_reg):
    cv = KFold(n_splits=5,shuffle=True,random_state=1412)
    result_post_adjusted = cross_validate(ad_reg,X,y,cv=cv,scoring="neg\_mean\_squared\_error"
                                          ,return_train_score=True
                                          ,verbose=True
                                          ,n_jobs=-1)
    print("训练RMSE:{:.3f}".format(RMSE(result_post_adjusted,"train\_score")))
    print("测试RMSE:{:.3f}".format(RMSE(result_post_adjusted,"test\_score")))

二、随机网格搜索 RandomizedSearchCV

1. 基本原理

  • 在讲解网格搜索时我们提到,伴随着数据和模型的复杂度提升,网格搜索所需要的时间急剧增加。以随机森林算法为例,如果使用过万的数据,搜索时间则会立刻上升好几个小时。因此,我们急需寻找到一种更加高效的超参数搜索方法。
  • 首先,当所使用的算法确定时,决定枚举网格搜索运算速度的因子一共有两个:
  • (1) 参数空间的大小:参数空间越大,需要建模的次数越多。
  • (2) 数据量的大小:数据量越大,每次建模时需要的算力和时间越多。
  • 因此,sklearn 中的网格搜索优化方法主要包括两类,其一是调整搜索空间,其二是调整每次训练的数据。其中,调整参数空间的具体方法,是放弃原本的搜索中必须使用的全域超参数空间,改为挑选出部分参数组合,构造超参数子空间,并只在子空间中进行搜索。
  • 以下图的二维空间为例,在这个 n_estimators 与 max_depth 共同组成的参数空间中,n_estimators 的取值假设为 [50,100,150,200,250,300],max_depth 的取值假设为 [2,3,4,5,6],则枚举网格搜索必须对 30 种参数组合都进行搜索。
  • 当我们调整搜索空间,我们可以只抽样出橙色的参数组合作为子空间,并只对橙色参数组合进行搜索。
fig, [ax1, ax2] = plt.subplots(1,2,dpi=300)
n_e_list = [\*range(50,350,50)]
m_d_list = [\*range(2,7)]
comb = pd.DataFrame([(n_estimators, max_depth) for n_estimators in n_e_list for max_depth in m_d_list])
​
ax1.scatter(comb.iloc[:,0],comb.iloc[:,1],cmap="Blues")
ax1.set_xticks([\*range(50,350,50)])
ax1.set_yticks([\*range(2,7)])
ax1.set_xlabel("n\_estimators")
ax1.set_ylabel("max\_depth")
ax1.set_title("GridSearch")
​
ax2.scatter(comb.iloc[:,0],comb.iloc[:,1],cmap="Blues")
ax2.scatter([50,250,200,200,300,100,150,150],[4,2,6,3,2,3,2,5],cmap="red",s=20,linewidths=5)
ax2.set_xticks([\*range(50,350,50)])
ax2.set_yticks([\*range(2,7)])
ax2.set_xlabel("n\_estimators")
ax2.set_ylabel("max\_depth")
ax2.set_title("RandomSearch");

在这里插入图片描述

  • 在 sklearn 中,随机抽取参数子空间并在子空间中进行搜索的方法叫做随机网格搜索 RandomizedSearchCV。
  • 由于搜索空间的缩小,需要枚举和对比的参数组的数量也对应减少,整体搜索耗时也将随之减少,因此:
  • 当设置相同的全域空间时,随机搜索的运算速度比枚举网格搜索快很多。
  • 当设置相同的训练次数时,随机搜索可以覆盖的空间比枚举网格搜索大很多。
  • 同时,绝妙的是,随机网格搜索得出的最小损失与枚举网格搜索得出的最小损失很接近。
  • 可以说,是提升了运算速度,又没有过多地伤害搜索的精度。
  • 不过,需要注意的是,随机网格搜索在实际运行时,并不是先抽样出子空间,再对子空间进行搜索,而是仿佛循环迭代一般,在这一次迭代中随机抽取 1 组参数进行建模,下一次迭代再随机抽取 1 组参数进行建模,由于这种随机抽样是不放回的,因此不会出现两次抽中同一组参数的问题。
  • 我们可以控制随机网格搜索的迭代次数,来控制整体被抽出的参数子空间的大小,这种做法往往被称为赋予随机网格搜索固定的计算量,当全部计算量被消耗完毕之后,随机网格搜索就停止。

2. 随机网格搜索的实现

from sklearn.model_selection import RandomizedSearchCV

  • 其函数语法模板如下:
class sklearn.model_selection.RandomizedSearchCV(estimator, param_distributions, \*, n_iter=10, scoring=None, n_jobs=None, refit=True, cv=None, verbose=0, pre_dispatch='2\*n\_jobs', random_state=None, error_score=nan, return_train_score=False)

  • 全部参数解读如下,其中加粗的是随机网格搜索独有的参数:
NameDescription
estimator调参对象,某评估器
param_distributions全域参数空间,可以是字典或者字典构成的列表
n_iter迭代次数,迭代次数越多,抽取的子参数空间越大
scoring评估指标,支持同时输出多个参数
n_jobs设置工作时参与计算的线程数
refit挑选评估指标和最佳参数,在完整数据集上进行训练
cv交叉验证的折数
verbose输出工作日志形式
pre_dispatch多任务并行时任务划分数量
random_state随机数种子
error_score当网格搜索报错时返回结果,选择’raise’时将直接报错并中断训练过程,其他情况会显示警告信息后继续完成训练
return_train_score在交叉验证中是否显示训练集中参数得分
  • 我们依然借用之前在网格搜索上见过的 X 和 y,以及随机森林回归器,来实现随机网格搜索:
X.shape
#(1460, 80)

X.head()

y.describe()

3. 相同的全域参数空间

  • 我们先创造参数空间,也就是和使用与网格搜索时完全一致的空间,以便于进行对比操作。
param_grid_simple = {"criterion": ["squared\_error","poisson"]
                     , 'n\_estimators': [\*range(20,100,5)]
                     , 'max\_depth': [\*range(10,25,2)]
                     , "max\_features": ["log2","sqrt",16,32,64,"auto"]
                     , "min\_impurity\_decrease": [\*np.arange(0,5,10)]
                    }
​

  • 然后建立回归器。进行交叉验证。
reg = RFR(random_state=1412,verbose=True,n_jobs=-1)
cv = KFold(n_splits=5,shuffle=True,random_state=1412)

  • 计算全域参数空间大小,这是我们能够抽样的最大值。
count_space(param_grid_simple)
#1536

  • 进行定义随机搜索。
search = RandomizedSearchCV(estimator=reg
                            ,param_distributions=param_grid_simple
                            ,n_iter = 800 #子空间的大小是全域空间的一半左右
                            ,scoring = "neg\_mean\_squared\_error"
                            ,verbose = True
                            ,cv = cv
                            ,random_state=1412
                            ,n_jobs=-1
                           )

  • 训练随机搜索评估器。
#=====【TIME WARNING: 5~10min】=====#
start = time.time()
search.fit(X,y)
print(time.time() - start)
#Fitting 5 folds for each of 800 candidates, totalling 4000 fits
#170.16785073280334

170.1678/60
#2.83613

  • 查看模型结果。
search.best_estimator_
#RandomForestRegressor(max\_depth=24, max\_features=16, min\_impurity\_decrease=0,
# n\_estimators=85, n\_jobs=-1, random\_state=1412,
# verbose=True)

abs(search.best_score_)\*\*0.5
#29251.284326350575

  • 根据最优参数重建模型。
ad_reg = RFR(max_depth=24, max_features=16, min_impurity_decrease=0,
                      n_estimators=85, n_jobs=-1, random_state=1412,
                      verbose=True)
rebuild_on_best_param(ad_reg)
#训练RMSE:11031.299
#测试RMSE:28639.969

HPO方法默认参数网格搜索随机搜索
搜索空间/全域空间-1536/1536800/1536
运行时间(分钟)-6.362.83(↓)
搜索最优(RMSE)30571.26629179.69829251.284
重建最优(RMSE)-28572.07028639.969(↑)
  • 很明显,在相同参数空间、相同模型的情况下,随机网格搜索的运算速度是普通网格搜索的一半,当然,这与子空间是全域空间的一半有很大的联系。
  • 由于随机搜索只是降低搜索的次数,并非影响搜索过程本身,因此其运行时间基本就等于n_iter/全域空间组合数 * 网格搜索的运行时间。

4. 随机网格搜索的理论极限

  • 在机器学习算法当中,有非常多通过随机来提升运算速度(比如 Kmeans,随机挑选样本构建簇心,小批量随机梯度下降,通过随机来减少每次迭代需要的样本)、或通过随机来提升模型效果的操作(比如随机森林,比如极度随机树)。
  • 两种随机背后的原理完全不同,而随机网格搜索属于前者,这一类机器学习方法总是伴随着“从某个全数据集/全域中进行抽样”的操作,而这种操作能够有效的根本原因在于:
  • (1)抽样出的子空间可以一定程度上反馈出全域空间的分布,且子空间相对越大(含有的参数组合数越多),子空间的分布越接近全域空间的分布。
  • (2) 当全域空间本身足够密集时,很小的子空间也能获得与全域空间相似的分布。
  • (3) 如果全域空间包括了理论上的损失函数最小值,那一个与全域空间分布高度相似的子空间很可能也包括损失函数的最小值,或包括非常接近最小值的一系列次小值。
  • 我们可以通过绘制图像来直观地呈现这些事实。许多在数学上比较抽象的概念都可以被可视化。在这里,我们借助 matplotlib 工具库 mplot3d 中的一组默认数据。
from mpl_toolkits.mplot3d import axes3d

p1, p2, MSE = axes3d.get_test_data(0.05)

  • 其中,get_test_data 巨头自动获取数据的功能,可以自动生成复合某一分布的数据。我们现在假设这一组数据中有两个参数,p1 与 p2,两个参数组成的参数组合对应着损失函数值 MSE。
  • 参数 0.05 是指参数空间中,点与点之间的距离。因此该数字越小,取出来的样本越多。
len(p1) #参数1的取值有120个
#120

len(p2) #参数2的取值也有120个
#120

  • 那么,现在参数空间当中一共有 120*120=14400 种组合,所以参数空间中一共有 14400 个点。
MSE.shape #损失函数值,总共14400个点
#(120, 120)

  • 随后,我们绘制 P1 与 P2 的参数空间,这是一个呈现出 14400 个点的密集空间。
plt.figure(dpi=300)
plt.scatter(p1,p2,s=0.2)
plt.xticks(fontsize=9)
plt.yticks(fontsize=9)

在这里插入图片描述

  • 参数与损失共同构建的函数。
p1, p2, MSE = axes3d.get_test_data(0.05)
plt.figure(dpi=300)
ax = plt.axes(projection="3d")
ax.plot_wireframe(p1,p2,MSE,rstride=2,cstride=2,linewidth=0.5)
ax.view_init(2, -15)
ax.zaxis.set_tick_params(labelsize=7)
ax.xaxis.set_tick_params(labelsize=7)
ax.yaxis.set_tick_params(labelsize=7)

在这里插入图片描述

np.min(MSE) #整个参数空间中,可获得的MSE最小值是-73.39
#-73.39620971601681

  • 现在,我们从该空间上抽取子空间。
MSE.shape
#(120, 120)

  • 我们从空间中抽取 n 个组合,n 越大子空间越大。现在总共有 14400 个组合,对被抽中的点来说,损失函数的值就是 MSE,对没有抽中的点来说,损失函数值是空值。
  • 因此,我们只需要找出没有抽中的点,并让它的损失函数值 MSE 为空就可以了。从 0~14400 中生成(14400-n)个随机数,形成没有被抽到子空间中的点的索引。
n = 100
unsampled = np.random.randint(0,14400,14400-n)​
p1, p2, MSE = axes3d.get_test_data(0.05)

  • 拉平 MSE,并将所有没抽中的点的损失函数变为空值。
MSE = MSE.ravel()
MSE[unsampled] = np.nan
MSE = MSE.reshape((120,120))

  • 设置完毕空值后,记得把 MSE 恢复成原来的结构,否则绘图报错。
#参数与损失共同构建的函数
plt.figure(dpi=300)
ax = plt.axes(projection="3d")
ax.view_init(2, -15)
ax.plot_wireframe(p1,p2,MSE,rstride=2,cstride=2,linewidth=0.5)
ax.zaxis.set_tick_params(labelsize=7)
ax.xaxis.set_tick_params(labelsize=7)
ax.yaxis.set_tick_params(labelsize=7)

  • 求出当前损失函数上的最小值,注意此时因为 MSE 中含有了空值,因此要先排除空值影响,否则 min 函数会返回空值。
MSE = MSE.ravel().tolist()
MSE = [x for x in MSE if str(x) != 'nan']
print(np.min(MSE))
#-73.24243733589367

在这里插入图片描述

  • 我们可以在图像上验证如下事实:
  • (1) 抽样出的子空间可以一定程度上反馈出全域空间的分布,且子空间相对越大(含有的参数组合数越多),子空间的分布越接近全域空间的分布。
  • (2) 当全域空间本身足够密集时,很小的子空间也能获得与全域空间相似的分布。
  • (3) 如果全域空间包括了理论上的损失函数最小值,那一个与全域空间分布高度相似的子空间很可能也包括损失函数的最小值,或包括非常接近最小值的一系列次小值。
  • 因此,只要子空间足够大,随机网格搜索的效果一定是高度逼近枚举网格搜索的。在全域参数空间固定时,随机网格搜索可以在效率与精度之间做权衡。子空间越大,精度越高,子空间越小,效率越高。

5. 更大/更密集的全域空间

  • 不过,由于随机网格搜索计算更快,所以在相同计算资源的前提下,我们可以对随机网格搜索使用更大的全域空间,因此随机搜索可能得到比网格搜索更好的效果。
  • 我们可以创造参数空间 ,从而让整体参数空间变得更密。
param_grid_simple = {'n\_estimators': [\*range(80,100,1)]
                     , 'max\_depth': [\*range(10,25,1)]
                     , "max\_features": [\*range(10,20,1)]
                     , "min\_impurity\_decrease": [\*np.arange(0,5,10)]
                    }

  • 计算全域参数空间大小,这是我们能够抽样的最大值。
count_space(param_grid_simple)
#3000

  • 建立回归器,进行交叉验证。
reg = RFR(random_state=1412,verbose=True,n_jobs=-1)
cv = KFold(n_splits=5,shuffle=True,random_state=1412)

  • 定义随机搜索。
search = RandomizedSearchCV(estimator=reg
                            ,param_distributions=param_grid_simple
                            ,n_iter = 1536 #使用与枚举网格搜索类似的拟合次数
                            ,scoring = "neg\_mean\_squared\_error"
                            ,verbose = True
                            ,cv = cv
                            ,random_state=1412
                            ,n_jobs=-1)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

   ,scoring = "neg\_mean\_squared\_error"
                        ,verbose = True
                        ,cv = cv
                        ,random_state=1412
                        ,n_jobs=-1)



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
[外链图片转存中...(img-NsNmKtsM-1713307237275)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值