导读:
在训练神经网络(例如长短期记忆复现神经网络)时,可能需要缩放序列预测问题的数据。
当输入数据序列分布并不标准,或者变化幅度(标准差)过大时,这会减慢网络的学习和收敛速度,也会阻碍网络的学习效率。
因此您需要了解如何归一化和标准化序列预测数据,以及如何确定将哪中形式用于输入和输出变量。
您可能需要考虑两种类型的系列缩放:归一化和标准化。
这些都可以使用scikit-learn库来实现。
源码地址:
https://github.com/yangwohenmai/LSTM/tree/master/%E9%95%BF%E7%9F%AD%E6%9C%9F%E8%AE%B0%E5%BF%86(LSTM)/LSTM%E7%9A%84%E6%95%B0%E6%8D%AE%E5%87%86%E5%A4%87/%E5%BD%92%E4%B8%80%E5%8C%96%E6%A0%87%E5%87%86%E5%8C%96%E9%95%BF%E7%9F%AD%E6%9C%9F%E5%86%85%E5%AD%98%E7%BD%91%E7%BB%9C%E7%9A%84%E6%95%B0%E6%8D%AE
<https://github.com/yangwohenmai/LSTM/tree/master/%E9%95%BF%E7%9F%AD%E6%9C%9F%E8%AE%B0%E5%BF%86(LSTM)/LSTM%E7%9A%84%E6%95%B0%E6%8D%AE%E5%87%86%E5%A4%87/%E5%BD%92%E4%B8%80%E5%8C%96%E6%A0%87%E5%87%86%E5%8C%96%E9%95%BF%E7%9F%AD%E6%9C%9F%E5%86%85%E5%AD%98%E7%BD%91%E7%BB%9C%E7%9A%84%E6%95%B0%E6%8D%AE>
1、什么时候用归一化?什么时候用标准化?
(1)如果对输出结果范围有要求,用归一化。
(2)如果数据较为稳定,不存在极端的最大最小值,用归一化。
(3)如果数据存在异常值和较多噪音,用标准化,可以间接通过中心化避免异常值和极端值的影响。
某知乎答主的回答提到了他个人经验:一般来说,我个人建议优先使用标准哈。对于输出有要求时再尝试别的方法,如归一化或者更加复杂的方法。很多方法都可以将输出范围调整到[0,
1],如果我们对于数据的分布有假设的话,更加有效的方法是使用相对应的概率密度函数来转换。让我们以高斯分布为例,我们可以首先计算高斯误差函数(Gaussian
Error Function),此处定为er fc(·),那么可以用下式进行转化:
这篇博客提到他的经验:1) 在分类、聚类算法中,需要使用距离来度量相似性的时候、或者使用PCA技术进行降维的时候,第二种方法(Z-score
standardization)表现更好。2)
在不涉及距离度量、协方差计算、数据不符合正太分布的时候,可以使用第一种方法或其他归一化方法。比如图像处理中,将RGB图像转换为灰度图像后将其值限定在[0
255]的范围。
2、 哪些模型必须归一化/标准化?
(1)SVM
不同的模型对特征的分布假设是不一样的。比如SVM
用高斯核的时候,所有维度共用一个方差,这不就假设特征分布是圆的么,输入椭圆的就坑了人家,所以简单的归一化都还不够好,来杯白化才有劲。比如用树的时候就是各个维度各算各的切分点,没所谓。
(2)KNN
需要度量距离的模型,一般在特征值差距较大时,都会进行归一化/标准化。不然会出现“大数吃小数”。
(3)神经网络
1)数值问题
归一化/标准化可以避免一些不必要的数值问题。输入变量的数量级未致于会引起数值问题吧,但其实要引起也并不是那么困难。因为tansig(tanh)的非线性区间大约在[-1.7,1.7]。意味着要使神经元有效,tansig(
w1x1 + w2x2 +b) 里的 w1x1 +w2x2 +b 数量级应该在 1
(1.7所在的数量级)左右。这时输入较大,就意味着权值必须较小,一个较大,一个较小,两者相乘,就引起数值问题了。
假如你的输入是421,你也许认为,这并不是一个太大的数,但因为有效权值大概会在1/421左右,例如0.00243,那么,在matlab里输入
421·0.00243 == 0.421·2.43,会发现不相等,这就是一个数值问题。
2)求解需要
a. 初始化:在初始化时我们希望每个神经元初始化成有效的状态,tansig函数在[-1.7,
1.7]范围内有较好的非线性,所以我们希望函数的输入和神经元的初始化都能在合理的范围内使得每个神经元在初始时是有效的。(如果权值初始化在[-1,1]且输入没有归一化且过大,会使得神经元饱和)
b.
梯度:以输入-隐层-输出这样的三层BP为例,我们知道对于输入-隐层权值的梯度有2ew(1-a^2)*x的形式(e是誤差,w是隐层到输出层的权重,a是隐层神经元的值,x是输入),若果输出层的数量级很大,会引起e的数量级很大,同理,w为了将隐层(数量级为1)映身到输出层,w也会很大,再加上x也很大的话,从梯度公式可以看出,三者相乘,梯度就非常大了。这时会给梯度的更新带来数值问题。
c.
学习率:由(2)中,知道梯度非常大,学习率就必须非常小,因此,学习率(学习率初始值)的选择需要参考输入的范围,不如直接将数据归一化,这样学习率就不必再根据数据范围作调整。
隐层到输出层的权值梯度可以写成 2ea,而输入层到隐层的权值梯度为 2ew(1-a^2)x ,受 x 和 w
的影响,各个梯度的数量级不相同,因此,它们需要的学习率数量级也就不相同。对w1适合的学习率,可能相对于w2来说会太小,若果使用适合w1的学习率,会导致在w2方向上步进非常慢,会消耗非常多的时间,而使用适合w2的学习率,对w1来说又太大,搜索不到适合w1的解。如果使用固定学习率,而数据没归一化,则后果可想而知。
d.搜索轨迹:已解释
(4)PCA
参考:
标准化和归一化什么区别? - 知乎:https://www.zhihu.com/question/20467170
R--数据标准化、归一化、中心化处理:https://zhuanlan.zhihu.com/p/33727799
特征工程中的[归一化]有什么作用? - 知乎:https://www.zhihu.com/question/20455227
神经网络为什么要归一化:http://nnetinfo.com/nninfo/showText.jsp?id=37
作者:brucep3
链接:https://www.jianshu.com/p/95a8f035c86c
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
归一化系列数据
归一化是对原始范围内的数据进行重新缩放,以使所有值都在0和1的范围内。
标准化要求您知道或能够准确估计最小和最大可观察值。您可以从可用数据中估算这些值。如果您的时间序列趋势向上或向下,估计这些预期值可能会很困难,并且规范化可能不是用于解决问题的最佳方法。
值的归一化如下:
1
y = (x - min) / (max - min)
其中最小值和最大值与值x被归一化有关。
例如,对于数据集,我们可以将min和max可观察值猜测为30和-10。然后我们可以将任何值标准化,如18.8,如下所示:
1
2
3
4
y = (x - min) / (max - min)
y = (18.8 - (-10)) / (30 - (-10))
y = 28.8 / 40
y = 0.72
您可以看到,如果提供的x值超出最小值和最大值的范围,则结果值将不在0和1的范围内。您可以在进行预测之前检查这些观察值并删除它们来自数据集或将它们限制为预定义的最大值或最小值。
您可以使用scikit-learn对象MinMaxScaler
<http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html>
规范化数据集。
使用MinMaxScaler和其他缩放技术的良好实践用法如下:
* 使用可用的训练数据安装定标器。对于归一化,这意味着训练数据将用于估计最小和最大可观察值。这是通过调用fit()函数完成的。
* 将比例应用于训练数据。这意味着您可以使用标准化数据来训练模型。这是通过调用transform()函数完成的。
* 将比例应用于未来的数据。这意味着您可以在将来准备要预测的新数据。
如果需要,可以反转变换。这对于将预测转换回其原始比例以进行报告或绘图非常有用。这可以通过调用inverse_transform()函数来完成。
下面是一个标准化10个量的人为序列的例子。
缩放器对象要求将数据作为行和列的矩阵提供。加载的时间序列数据作为Pandas系列加载。
from pandas import Series from sklearn.preprocessing import MinMaxScaler #
手动定义一串序列 data = [10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0]
series = Series(data) print(series) # 准备归一化数据格式 values = series.values values =
values.reshape((len(values), 1)) # 配置数据归一化方法MinMaxScaler scaler =
MinMaxScaler(feature_range=(0, 1)) scaler = scaler.fit(values) print('Min: %f,
Max: %f' % (scaler.data_min_, scaler.data_max_)) # 输出归一化数据 normalized =
scaler.transform(values) print(normalized) # 归一化逆转换 inversed =
scaler.inverse_transform(normalized) print(inversed)
我们还可以看到数据集的最小值和最大值分别为10.0和100.0。
运行该示例打印序列,打印从序列估计的最小值和最大值,打印相同的标准化序列,然后使用逆变换将值返回到其原始比例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
0 10.0
1 20.0
2 30.0
3 40.0
4 50.0
5 60.0
6 70.0
7 80.0
8 90.0
9 100.0
Min: 10.000000, Max: 100.000000
[[ 0. ]
[ 0.11111111]
[ 0.22222222]
[ 0.33333333]
[ 0.44444444]
[ 0.55555556]
[ 0.66666667]
[ 0.77777778]
[ 0.88888889]
[ 1. ]]
[[ 10.]
[ 20.]
[ 30.]
[ 40.]
[ 50.]
[ 60.]
[ 70.]
[ 80.]
[ 90.]
[ 100.]]
标准化系列数据
标准化数据集涉及重新调整值的分布,以便观察值的平均值为0,标准差为1。
这可以被认为是减去平均值或使数据居中。
与标准化一样,当您的数据具有不同比例的输入值时,标准化可能很有用,甚至在某些机器学习算法中也是必需的。
标准化假定您的观察结果符合高斯分布(钟形曲线),具有良好的平均值和标准偏差。如果不满足此期望,您仍然可以标准化时间序列数据,但可能无法获得可靠的结果。
标准化要求您知道或能够准确估计可观察值的均值和标准差。您可以从训练数据中估算这些值。
值标准化如下:
1
y = (x - mean) / standard_deviation
平均值计算如下:
1
mean = sum(x) / count(x)
而standard_deviation计算如下:
1
standard_deviation = sqrt( sum( (x - mean)^2 ) / count(x))
我们可以猜测平均值为10,标准偏差约为5.使用这些值,我们可以将第一个值20.7标准化如下:
1
2
3
4
y = (x - mean) / standard_deviation
y = (20.7 - 10) / 5
y = (10.7) / 5
y = 2.14
数据集的均值和标准差估计对新数据的稳健性可能比最小值和最大值更强。
您可以使用scikit-learn对象StandardScaler
<http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html>
来标准化数据集。
from pandas import Series from sklearn.preprocessing import StandardScaler
from math import sqrt # 手动定义一个待标准化序列 data = [1.0, 5.5, 9.0, 2.6, 8.8, 3.0, 4.1,
7.9, 6.3] series = Series(data) print(series) # 准备标准化数据格式 values =
series.values values = values.reshape((len(values), 1)) # 配置标准化方法StandardScaler
scaler = StandardScaler() scaler = scaler.fit(values) print('Mean: %f,
StandardDeviation: %f' % (scaler.mean_, sqrt(scaler.var_))) # 输出标准化后的数据
standardized = scaler.transform(values) print(standardized) # 标准化数据的逆转换
inversed = scaler.inverse_transform(standardized) print(inversed)
我们可以看到估计的平均值和标准偏差分别约为5.3和2.7。运行该示例打印序列,打印从序列估计的均值和标准差,打印标准化值,然后以原始比例打印值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
0 1.0
1 5.5
2 9.0
3 2.6
4 8.8
5 3.0
6 4.1
7 7.9
8 6.3
Mean: 5.355556, StandardDeviation: 2.712568
[[-1.60569456]
[ 0.05325007]
[ 1.34354035]
[-1.01584758]
[ 1.26980948]
[-0.86838584]
[-0.46286604]
[ 0.93802055]
[ 0.34817357]]
[[ 1. ]
[ 5.5]
[ 9. ]
[ 2.6]
[ 8.8]
[ 3. ]
[ 4.1]
[ 7.9]
[ 6.3]]
输入变量是否需要缩放取决于问题和每个变量的具体情况。我们来看一些例子。
分类输入
您可能有一系列分类输入,例如字母或状态。
通常,分类输入首先是整数编码,然后是一个热编码。也就是说,为每个不同的可能输入分配唯一的整数值,然后使用1和0的二进制向量来表示每个整数值。
根据定义,一个热编码将确保每个输入是一个小的实际值,在这种情况下为0.0或1.0。
实值输入
您可能有一系列数量作为输入,例如价格或温度。
如果数量的分布是正常的,则应该标准化,否则系列应该标准化。如果数值范围很大(10s 100s等)或小(0.01,0.0001),则适用。
如果数量值很小(接近0-1)且分布有限(例如标准偏差接近1),那么也许你可以在没有系列缩放的情况下逃脱。
其他输入
问题可能很复杂,如何最好地扩展输入数据可能并不清楚。
如果有疑问,请将输入序列标准化。如果您拥有这些资源,请使用原始数据,标准化数据和标准化来探索建模,并查看是否存在有益的差异。
缩放输出变量
输出变量是网络预测的变量。
您必须确保输出变量的比例与网络输出层上的激活函数(传递函数)的比例相匹配。
二元分类问题
如果您的问题是二进制分类问题,那么输出将是类值0和1.这最好使用输出层上的sigmoid激活函数建模。输出值将是介于0和1之间的实数值,可以捕捉到清晰的值。
多类分类问题
如果您的问题是多类分类问题,那么输出将是一个介于0和1之间的二进制类值的向量,每个类值一个输出。这最好使用输出层上的softmax激活功能建模。同样,输出值将是介于0和1之间的实数值,可以捕捉到清晰的值。
回归问题
如果您的问题是回归问题,那么输出将是一个实际值。这最好使用线性激活功能建模。如果值的分布正常,则可以标准化输出变量。否则,可以对输出变量进行标准化。
其他问题
可以在输出层上使用许多其他激活函数,并且您的问题的细节可能会增加混淆。
经验法则是确保网络输出与数据规模相匹配。
扩展时的实际考虑因素
缩放序列数据时有一些实际考虑因素。
* 估算系数
。您可以从训练数据中估算系数(标准化的最小值和最大值或标准化的平均值和标准偏差)。检查这些首先估算并使用领域知识或领域专家来帮助改进这些估算,以便将来对所有数据进行有用的更正。
* 保存系数。您将需要以与用于训练模型的数据完全相同的方式对未来的新数据进行标准化。保存用于存档的系数,并在需要在进行预测时扩展新数据时加载它们。
* 数据分析。使用数据分析可以帮助您更好地了解数据。例如,一个简单的直方图可以帮助您快速了解数量分布,看看标准化是否有意义。
* 扩展每个系列。如果您的问题有多个系列,请将每个系列视为一个单独的变量,然后分别对它们进行缩放。
* 在合适的时间缩放
。在正确的时间应用任何缩放变换非常重要。例如,如果您有一系列非静止的数量,则在首次使数据静止后进行缩放可能是合适的。在将系列转换为监督学习问题后对其进行扩展是不合适的,因为每个列的处理方式都不同,这是不正确的。
* 如果怀疑则缩放。您可能需要重新调整输入和输出变量。如果有疑问,至少要对数据进行标准化。
热门工具 换一换