【问题标题】:Can anyone explain me StandardScaler?谁能解释一下 StandardScaler?
【发布时间】:2017-04-07 02:44:34
【问题描述】:

我无法理解sklearn文档中StandardScalerpage

谁能简单的给我解释一下?

【问题讨论】:

    标签: python machine-learning scikit-learn scaling standardized


    【解决方案1】:

    简介

    我假设您有一个矩阵 X,其中每个 行/行 是一个 样本/观察,每个 是一个 变量/特征(这是任何sklearn ML 函数的预期输入——X.shape 应该是[number_of_samples, number_of_features])。


    方法的核心

    主要思想是规范化/标准化μ = 0σ = 1X的特征/变量/列,单独之前 应用任何机器学习模型。

    StandardScaler()规范化特征,即每个 X 的单独,因此每个列/特征/变量将具有μ = 0σ = 1


    P.S:我在这个页面上找到了最受好评的答案,错了。 我引用的是“数据集中的每个值都会减去样本平均值”——这既不正确也不正确。


    另请参阅:How and why to Standardize your data: A python tutorial


    代码示例

    from sklearn.preprocessing import StandardScaler
    import numpy as np
    
    # 4 samples/observations and 2 variables/features
    data = np.array([[0, 0], [1, 0], [0, 1], [1, 1]])
    scaler = StandardScaler()
    scaled_data = scaler.fit_transform(data)
    
    print(data)
    [[0, 0],
     [1, 0],
     [0, 1],
     [1, 1]])
    
    print(scaled_data)
    [[-1. -1.]
     [ 1. -1.]
     [-1.  1.]
     [ 1.  1.]]
    

    验证每个特征(列)的均值是否为 0:

    scaled_data.mean(axis = 0)
    array([0., 0.])
    

    验证每个特征(列)的std为1:

    scaled_data.std(axis = 0)
    array([1., 1.])
    

    附录:数学


    更新 08/2020:关于输入参数 with_meanwith_stdFalse/True,我在这里提供了答案:StandardScaler difference between “with_std=False or True” and “with_mean=False or True”

    【讨论】:

    • 你知道为什么当我用 pandas df: pd.DataFrame(scaled_data).std(0) 计算时我得到[1.15, 1.15] 吗?
    • 当我运行pd.DataFrame(scaled_data)[0] 时,我得到一个带有Name: 0, dtype: float64 和值[-1.0, 1.0, -1.0, 1.0] 的系列。抱歉格式化
    • @seralouk 我喜欢你的回答,但是我仍然想知道使用 StandardScaler 转换输入数据的目的是什么,它是否使机器学习算法运行得更快,或者有助于做出更准确的决策,还是别的什么?
    • 数据集的标准化是许多机器学习估计器的共同要求:如果个别特征或多或少看起来不像标准正态分布数据(例如,均值和单位方差为 0 的高斯),它们可能表现不佳)。例如,学习算法的目标函数中使用的许多元素(例如 SVM 的 RBF 内核或线性模型的 L1 和 L2 正则化器)假设所有特征都以 0 为中心并且具有相同顺序的方差。
    • 因此,标准化导致 a) 更稳定 b) 受变量范围的影响较小 c) 更快的拟合 d) 更稳定的性能
    【解决方案2】:

    我们逐行申请StandardScalar()

    因此,对于一列中的每一行(我假设您正在使用 Pandas DataFrame):

    x_new = (x_original - mean_of_distribution) / std_of_distribution
    

    几点-

    1. 它被称为标准标量,因为我们将它除以分布的标准差(特征的分布)。同样,您可以猜测MinMaxScalar()

    2. 应用StandardScalar() 后,原始分布保持不变。将分布更改为正态分布是一种常见的误解。我们只是将范围压缩为 [0, 1]。

    【讨论】:

      【解决方案3】:

      上面的答案很好,但我需要一个简单的例子来减轻我过去的一些担忧。我想确保它确实是分别处理每一列。我现在放心了,找不到让我担心的例子。所有列 ARE 分别按上述说明进行缩放。

      代码

      import pandas as pd
      import scipy.stats as ss
      from sklearn.preprocessing import StandardScaler
      
      
      data= [[1, 1, 1, 1, 1],[2, 5, 10, 50, 100],[3, 10, 20, 150, 200],[4, 15, 40, 200, 300]]
      
      df = pd.DataFrame(data, columns=['N0', 'N1', 'N2', 'N3', 'N4']).astype('float64')
      
      sc_X = StandardScaler()
      df = sc_X.fit_transform(df)
      
      num_cols = len(df[0,:])
      for i in range(num_cols):
          col = df[:,i]
          col_stats = ss.describe(col)
          print(col_stats)
      

      输出

      DescribeResult(nobs=4, minmax=(-1.3416407864998738, 1.3416407864998738), mean=0.0, variance=1.3333333333333333, skewness=0.0, kurtosis=-1.3599999999999999)
      DescribeResult(nobs=4, minmax=(-1.2828087129930659, 1.3778315806221817), mean=-5.551115123125783e-17, variance=1.3333333333333337, skewness=0.11003776770595125, kurtosis=-1.394993095506219)
      DescribeResult(nobs=4, minmax=(-1.155344148338584, 1.53471088361394), mean=0.0, variance=1.3333333333333333, skewness=0.48089217736510326, kurtosis=-1.1471008824318165)
      DescribeResult(nobs=4, minmax=(-1.2604572012883055, 1.2668071116222517), mean=-5.551115123125783e-17, variance=1.3333333333333333, skewness=0.0056842140599118185, kurtosis=-1.6438177182479734)
      DescribeResult(nobs=4, minmax=(-1.338945389819976, 1.3434309690153527), mean=5.551115123125783e-17, variance=1.3333333333333333, skewness=0.005374558840039456, kurtosis=-1.3619131970819205)
      

      注意:

      scipy.stats 模块正确报告了“样本”方差,该方差在分母中使用 (n - 1)。 “总体”方差将在分母中使用 n 来计算方差。为了更好地理解,请看下面的代码,它使用了上面数据集第一列的缩放数据:

      代码

      import scipy.stats as ss
      
      sc_Data = [[-1.34164079], [-0.4472136], [0.4472136], [1.34164079]]
      col_stats = ss.describe([-1.34164079, -0.4472136, 0.4472136, 1.34164079])
      print(col_stats)
      print()
      
      mean_by_hand = 0
      for row in sc_Data:
          for element in row:
              mean_by_hand += element
      mean_by_hand /= 4
      
      variance_by_hand = 0
      for row in sc_Data:
          for element in row:
              variance_by_hand += (mean_by_hand - element)**2
      sample_variance_by_hand = variance_by_hand / 3
      sample_std_dev_by_hand = sample_variance_by_hand ** 0.5
      
      pop_variance_by_hand = variance_by_hand / 4
      pop_std_dev_by_hand = pop_variance_by_hand ** 0.5
      
      print("Sample of Population Calcs:")
      print(mean_by_hand, sample_variance_by_hand, sample_std_dev_by_hand, '\n')
      print("Population Calcs:")
      print(mean_by_hand, pop_variance_by_hand, pop_std_dev_by_hand)
      

      输出

      DescribeResult(nobs=4, minmax=(-1.34164079, 1.34164079), mean=0.0, variance=1.3333333422778562, skewness=0.0, kurtosis=-1.36000000429325)
      
      Sample of Population Calcs:
      0.0 1.3333333422778562 1.1547005422523435
      
      Population Calcs:
      0.0 1.000000006708392 1.000000003354196
      

      【讨论】:

      • 为什么方差不是1?
      • @Max,scipy stats 正在使用样本方差。查看新添加的答案。
      • @seralouk 是,如果总体方差和标准偏差,但不是样本方差和标准偏差 - scipy stats 默认为样本计算。
      【解决方案4】:

      StandardScaler 背后的想法是,它将转换您的数据,使其分布的平均值为 0,标准差为 1。
      在多变量数据的情况下,这是按特征完成的(换句话说,对于数据的每一列都是独立的)。
      给定数据的分布,数据集中的每个值都会减去平均值,然后除以整个数据集(或多变量情况下的特征)的标准差。

      【讨论】:

      • 我发现这个答案不正确。 each value in the dataset will have the sample mean value subtracted-- 这不是真的。每个特征/列的平均值将从特定列的值中减去。这是按列完成的。没有sample mean value subtracted - 请参阅下面的答案
      • @makis 根据您的建议,我编辑了我的答案。
      【解决方案5】:

      以下是一个简单的工作示例,用于解释标准化计算的工作原理。理论部分已经在其他答案中得到了很好的解释。

      >>>import numpy as np
      >>>data = [[6, 2], [4, 2], [6, 4], [8, 2]]
      >>>a = np.array(data)
      
      >>>np.std(a, axis=0)
      array([1.41421356, 0.8660254 ])
      
      >>>np.mean(a, axis=0)
      array([6. , 2.5])
      
      >>>from sklearn.preprocessing import StandardScaler
      >>>scaler = StandardScaler()
      >>>scaler.fit(data)
      >>>print(scaler.mean_)
      
      #Xchanged = (X−μ)/σ  WHERE σ is Standard Deviation and μ is mean
      >>>z=scaler.transform(data)
      >>>z
      

      计算

      正如您在输出中看到的,均值是 [6. , 2.5] 和标准偏差为 [1.41421356, 0.8660254 ]

      数据为 (0,1) 位置为 2 标准化 = (2 - 2.5)/0.8660254 = -0.57735027

      (1,0) 位置的数据是 4 标准化 = (4-6)/1.41421356 = -1.414

      标准化后的结果

      标准化后检查均值和标准差

      注意:-2.77555756e-17 非常接近于 0。

      参考文献

      1. Compare the effect of different scalers on data with outliers

      2. What's the difference between Normalization and Standardization?

      3. Mean of data scaled with sklearn StandardScaler is not zero

      【讨论】:

        【解决方案6】:

        StandardScaler 执行标准化的任务。通常,数据集包含规模不同的变量。例如Employee 数据集将包含 AGE 列,其值 在 20-70 范围内 和 SALARY 列,其值 在 10000-80000 范围内
        因为这两列的规模不同,它们在构建机器学习模型时被标准化以具有共同的规模。

        【讨论】:

        • 最容易理解的答案!谢谢。你能详细解释一下这个过程吗?
        【解决方案7】:

        应用StandardScaler()后,X中每一列的平均值为0,标准差为1。

        其他人在此页面上列出了公式。

        理由:某些算法要求数据看起来像这样(请参阅sklearn docs)。

        【讨论】:

        • 正确。一些答案显示了缩放数据样本均值和方差的 scipy stats 描述。小数据集的样本方差可能与总体方差显着不同。
        【解决方案8】:

        【讨论】:

          【解决方案9】:

          当您想要比较对应于不同单位的数据时,这很有用。在这种情况下,您要删除这些单位。要以一致的方式对所有数据执行此操作,您需要以方差为单一且序列均值为 0 的方式转换数据。

          【讨论】:

          • 你能用一个例子解释一下吗?
          猜你喜欢
          • 1970-01-01
          • 2015-12-21
          • 2015-11-23
          • 2013-05-23
          • 2017-07-23
          • 1970-01-01
          • 1970-01-01
          • 2020-06-16
          • 2017-01-25
          相关资源
          最近更新 更多