学而后思
梯度爆炸和梯度衰减问题
深度模型有关数值稳定性的典型问题是消失(vanishing)和爆炸(explosion)。
当神经网络的层数较多时,模型的数值稳定性容易变差。
假设一个层数为 $L$ 的多层感知机的第 $l$ 层 $\boldsymbol{H}^{(l)}$ 的权重参数为$\boldsymbol{W}^{(l)}$,输出层 $\boldsymbol{H}^{(L)}$ 的权重参数为 $\boldsymbol{W}^{(L)}$。
为了便于讨论,不考虑偏差参数,且设所有隐藏层的激活函数为恒等映射
(identity mapping)$\phi(x) = x$。
给定输入$\boldsymbol{X}$,多层感知机的第$l$层的输出$\boldsymbol{H}^{(l)} = \boldsymbol{X} \boldsymbol{W}^{(1)} \boldsymbol{W}^{(2)} \ldots \boldsymbol{W}^{(l)}$。此时,如果层数$l$较大,$\boldsymbol{H}^{(l)}$的计算可能会出现衰减或爆炸。
For Example:假设输入和所有层的权重参数都是标量,如权重参数为0.2和5,多层感知机的第30层输出为输入$\boldsymbol{X}$分别与$0.2^{30} \approx 1 \times 10^{-21}$(消失)和$5^{30} \approx 9 \times 10^{20}$(爆炸)的乘积。当层数较多时,梯度的计算也容易出现消失或爆炸。
解决方案:
过拟合和欠拟合问题
随机初始化模型参数
如何占据神经网络中不可或缺的位置?
话起 多层感知机 [ Multilayer Perceptron ]
假设输出层只保留一个输出单元$o_1$(删去$o_2$和$o_3$以及指向它们的箭头),且隐藏层使用相同的激活函数。
如果将每个隐藏单元的参数都初始化为相等的值,那么在正向传播时每个隐藏单元将根据相同的输入计算出相同的值,并传递至输出层。
在反向传播中,每个隐藏单元的参数梯度值相等。因此,这些参数在使用基于梯度的优化算法迭代后值依然相等。之后的迭代也是如此。
在这种情况下,无论隐藏单元有多少,隐藏层本质上只有1个隐藏单元在发挥作用
。因此通常将神经网络的模型参数,特别是权重参数,进行随机初始化。
列举两种随机初始化方式
PyTorch的默认随机初始化 Design and Realization of Linear Regression 中,使用 torch.nn.init.normal_() 使模型 net 的权重参数采用正态分布的随机初始化方式。
PyTorch中 nn.Module 的模块参数都采取了较为合理的初始化策略(不同类型的layer具体采样的哪一种初始化方法的可参考源代码 ),因此一般不用我们考虑。
Xavier随机初始化 假设某全连接层的输入个数为$a$,输出个数为$b$,Xavier随机初始化将使该层中权重参数的每个元素都随机采样于均匀分布
$$ U\left(-\sqrt{\frac{6}{a+b}}, \sqrt{\frac{6}{a+b}}\right). $$
模型参数初始化后,每层输出的方差不该受该层输入个数影响,且每层梯度的方差也不该受该层输出个数影响。
环境因素带来的问题
1.协变量偏移 2.标签偏移 3.概念偏移
协变量偏移
For Example : 一个在冬季部署的物品推荐系统在夏季的物品推荐列表中出现了圣诞礼物
我们假设,虽然输入的分布P(x)可能随时间而改变,但是标记函数,即条件分布P(y∣x)不会改变。【注意:容易忽视】
对于区分猫和狗,假设我们的训练数据使用的是猫和狗的真实的照片,但是在测试时,我们被要求对猫和狗的卡通图片进行分类。显然,这不太可能奏效。
训练集由照片组成,而测试集只包含卡通。在一个看起来与测试集有着本质不同的数据集上进行训练,而不考虑如何适应新的情况。
问题的根源在于特征分布的变化 ( 即协变量的变化 ) , 统计学家称这种协变量变化。
标签偏移
如果数据量足够的情况下,确保训练数据集和测试集中的数据取自同一个数据集,可以防止协变量偏移和标签偏移是正确的。如果数据量很少,少到测试集中存在训练集中未包含的标签,就会发生标签偏移。
当我们认为导致偏移的是标签P(y)上的边缘分布的变化,但类条件分布是不变的P(x∣y)时,就会出现相反的问题。当我们认为y导致x时,标签偏移是一个合理的假设。
For Example:
通常我们希望根据其表现来预测诊断结果。在这种情况下,我们认为诊断引起的表现,即疾病引起的症状。 病因(要预测的诊断结果)导致 症状(观察到的结果)。 训练数据集,数据很少只包含流感p(y)的样本。 而测试数据集有流感p(y)和流感q(y),其中不变的是流感症状p(x|y)。
有时标签偏移和协变量移位假设可以同时成立。例如,当真正的标签函数是确定的和不变的。
在概念转换中,有一种标签本身的定义发生变化的情况:
概念偏移
如果我们要建立一个机器翻译系统,分布P(y∣x)可能因我们的位置而异。这个问题很难发现。另一个可取之处是P(y∣x)通常只是逐渐变化。
换句话说就是:概念偏移可以根据其缓慢变化的特点缓解。
思而立行
Advanced Regression Techniques:House Prices
导入数据包和模块 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 %matplotlib inline import torchimport torch.nn as nnimport numpy as npimport pandas as pdtorch.set_default_tensor_type(torch.FloatTensor) import seaborn as snsimport matplotlib.pyplot as pltfrom scipy import statsfrom scipy.stats import normfrom sklearn.preprocessing import StandardScalerimport warningswarnings.filterwarnings('ignore' ) from sklearn import preprocessingfrom sklearn import linear_model, svm, gaussian_processfrom sklearn.ensemble import RandomForestRegressorfrom sklearn.model_selection import train_test_split
数据导入 1 2 test_data = pd.read_csv("path to test.csv" ) train_data = pd.read_csv("path to train.csv" )
分析数据变化趋势 1 2 3 4 train_data['SalePrice' ].describe() sns.distplot(train_data['SalePrice' ])
根据SalePrice变化趋势分析为正态分布,设定两个图像特征峰度(Kurtosis)和偏度(Skewness)
1 2 3 print("Skewness: %f" % train_data['SalePrice' ].skew()) print("Kurtosis: %f" % train_data['SalePrice' ].kurt())
提取有效特征 1 2 3 corrmat = train_data.corr() f, ax = plt.subplots(figsize=(20 , 9 )) sns.heatmap(corrmat, vmax=0.8 , square=True )
特征取舍和离散值参与分析 1 2 3 4 5 6 7 8 from sklearn import preprocessingf_names = ['CentralAir' , 'Neighborhood' ] for x in f_names: label = preprocessing.LabelEncoder() train_data[x] = label.fit_transform(train_data[x]) corrmat = train_data.corr() f, ax = plt.subplots(figsize=(20 , 9 )) sns.heatmap(corrmat, vmax=0.8 , square=True )
由相关性图可得:’CentralAir’, ‘Neighborhood’这两个特征对房价的影响并不大,舍去特征
列出关系矩阵 1 2 3 4 5 6 7 k = 10 cols = corrmat.nlargest(k, 'SalePrice' )['SalePrice' ].index cm = np.corrcoef(train_data[cols].values.T) sns.set(font_scale=1.25 ) hm = sns.heatmap(cm, cbar=True , annot=True , \ square=True , fmt='.2f' , annot_kws={'size' : 10 }, yticklabels=cols.values, xticklabels=cols.values) plt.show()
列出散点关系图 1 2 3 4 sns.set() cols = ['SalePrice' ,'OverallQual' ,'GrLivArea' , 'GarageCars' ,'TotalBsmtSF' , 'FullBath' , 'TotRmsAbvGrd' , 'YearBuilt' ] sns.pairplot(train_data[cols], size = 2.5 ) plt.show()
数据模拟 1 2 3 4 5 6 7 cols = ['OverallQual' ,'GrLivArea' , 'GarageCars' ,'TotalBsmtSF' , 'FullBath' , 'TotRmsAbvGrd' , 'YearBuilt' ] x = train_data[cols].values y = train_data['SalePrice' ].values x_scaled = preprocessing.StandardScaler().fit_transform(x) y_scaled = preprocessing.StandardScaler().fit_transform(y.reshape(-1 ,1 )) X_train,X_test, y_train, y_test = train_test_split(x_scaled, y_scaled, test_size=0.33 , random_state=42 )
随机森林回归 1 2 3 4 5 6 7 8 9 10 11 12 13 14 clfs = { 'svm' :svm.SVR(), 'RandomForestRegressor' :RandomForestRegressor(n_estimators=400 ), 'BayesianRidge' :linear_model.BayesianRidge() } for clf in clfs: try : clfs[clf].fit(X_train, y_train) y_pred = clfs[clf].predict(X_test) print(clf + " cost:" + str(np.sum(y_pred-y_test)/len(y_pred)) ) except Exception as e: print(clf + " Error:" ) print(str(e))
预测 1 2 3 4 5 6 7 8 9 10 11 12 cols = ['OverallQual' ,'GrLivArea' , 'GarageCars' ,'TotalBsmtSF' , 'FullBath' , 'TotRmsAbvGrd' , 'YearBuilt' ] x = train_data[cols].values y = train_data['SalePrice' ].values X_train,X_test, y_train, y_test = train_test_split(x, y, test_size=0.33 , random_state=42 ) clf = RandomForestRegressor(n_estimators=400 ) clf.fit(X_train, y_train) y_pred = clf.predict(X_test) print(y_pred) print(y_test) print(sum(abs(y_pred - y_test))/len(y_pred))
检验 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 rfr = clf test_data[cols].isnull().sum() test_data['GarageCars' ].describe() test_data['TotalBsmtSF' ].describe() cols2 = ['OverallQual' ,'GrLivArea' , 'FullBath' , 'TotRmsAbvGrd' , 'YearBuilt' ] cars = test_data['GarageCars' ].fillna(1.766118 ) bsmt = test_data['TotalBsmtSF' ].fillna(1046.117970 ) data_test_x = pd.concat( [test_data[cols2], cars, bsmt] ,axis=1 ) data_test_x.isnull().sum() x = data_test_x.values y_te_pred = rfr.predict(x) print(y_te_pred) print(y_te_pred.shape) print(x.shape) print(data_test_x)
输出数据表格式:1459 rows × 7 columns
输出结果到文件 1 2 3 4 5 6 prediction = pd.DataFrame(y_te_pred, columns=['SalePrice' ]) result = pd.concat([ test_data['Id' ], prediction], axis=1 ) result.columns result.to_csv('./Predictions.csv' , index=False )
Author:
Rokosnake
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Slogan:
How to thought, there is what kind of life.