开启成长之旅!这是我参加「日新方案 2 月更文挑战」的第 5 天,点击查看活动概况。

前言

一般机器学习使命其工作流程可总结为如下所示 pipeline

深度学习炼丹-数据标准化

在工业界,数据预处理进程对模型精度的进步的发挥着重要作用。关于机器学习使命来说,广泛的数据预处理一般有四个阶段(视觉使命一般只需 Data Transformation): 数据清洗(Data Cleaning)、数据整合(Data Integration)、数据转化(Data Transformation)和数据减缩(Data Reduction)。

深度学习炼丹-数据标准化

1,Data Cleaning: 数据整理是数据预处理进程的一部分,通过填充缺失值、平滑噪声数据、处理纷歧致和删除异常值来整理数据。

2,Data Integration: 用于将存在于多个源中的数据合并到一个更大的数据存储中,如数据仓库。例如,将来自多个医疗节点的图画整合起来,构成一个更大的数据库。

3,Data Transformation : 在完结 Data Cleaning 后,咱们需求运用以下数据转化战略更改数据的值、结构或格局。

  • Generalization: 运用概念层次结构将低级或粒度数据转化为高级信息。例如将城市等地址中的原始数据转化为国家等更高层次的信息。
  • Normalization: 意图是将数字特点按份额放大或缩小以合适指定规模。Normalization 常见办法:
    • Min-max normalization
    • Z-Score normalization
    • Decimal scaling normalization

4,Data Reduction 数据仓库中数据集的巨细或许太大而无法通过数据剖析和数据挖掘算法进行处理。一种或许的处理方案是取得数据集的减缩表明,该数据集的体积要小得多,但会发生相同质量的剖析成果。常见的数据减缩战略如下:

  • Data cube aggregation
  • Dimensionality reduction: 降维技能用于履行特征提取。数据集的维度是指数据的特点或个体特征。该技能旨在削减咱们在机器学习算法中考虑的冗余特征的数量。降维能够运用主成分剖析(PCA)等技能来完结。
  • Data compression: 通过运用编码技能,数据的巨细能够明显减小。
  • Discretization: 数据离散化用于将具有接连性的特点划分为具有区间的数据。这样做是由于接连特征往往与目标变量相关的或许性较小。例如,特点年龄能够离散化为 18 岁以下、18-44 岁、44-60 岁、60 岁以上等区间。

关于核算机视觉使命来说,在练习 CNN 模型之前,关于输入样本特征数据做规范化normalization,也叫归一化)预处理data preprocessing)操作是最常见的进程。

一,Normalization 概述

后续内容对 Normalization 不再运用中文翻译,是由于现在中文翻译有些歧义,依据我查阅的博客资料,翻译为“归一化”比较多,但仅供可参考。

1.1,Normalization 界说

Normalization 操作被用于对数据特点进行缩放,使其落在较小的规模之内(即改变到某个固定区间中),比方 [-1,1] 和 [0, 1],简略了解便是特征缩放进程。许多机器学习算法都获益于 Normalization 操作,比方:

  • 通常对分类算法有用。
  • 在梯度下降等机器学习算法的中心中运用的优化算法很有用。
  • 关于加权输入的算法(如回归和神经网络)以及运用间隔衡量的算法(如 K 最近邻)也很有用。

1.2,什么情况需求 Normalization

当咱们处理的数据具有不同规范(规模)different scale)时,通常就需求进行 normalization 操作了,它或许会导致一个重要特点(在较低规范上)的有效性被稀释,由于其他特点具有更大规模(规范)的值,简略点了解便是规模(scale)大点特点在模型傍边更具优先级,具体示例如下图所示。

深度学习炼丹-数据标准化

总而言之便是,当数据存在多个特点但其值具有不同规范(scale)时,这或许会导致咱们在做数据挖掘操作时数据模型表现不佳,因而履行 normalization 操作将所有特点置于相同的尺度内是很有必要的。

1.3,为什么要做 Normalization

  1. 样本的各个特征的取值要符合概率散布,即 [0,1][0,1](也可了解为降低模型练习对特征规范的敏感度)。输入数据特征取值规模和输出标签规模相同,从丢失函数等高线图来剖析,不做 Normalization 的练习进程会更曲折。

    深度学习炼丹-数据标准化

  2. 神经网络假定所有的输入输出数据都是规范差为1,均值为0,包括权重值的初始化,激活函数的挑选,以及优化算法的设计。

  3. 防止一些不必要的数值问题

    由于激活函数 sigmoid/tanh 的非线性区间大约在 [−1.7,1.7]。意味着要使神经元的激活函数有效,线性核算输出的值的数量级应该在1(1.7所在的数量级)左右。这时假如输入较大,就意味着权值有必要较小,一个较大,一个较小,两者相乘,就引起数值问题了。

  4. 梯度更新

    若果输出层的数量级很大,会引起丢失函数的数量级很大,这样做反向传达时的梯度也就很大,这时会给梯度的更新带来数值问题。

  5. 学习率

    特征数据数值规模不同,正确的梯度更新方向需求的学习率也会不同(假如梯度十分大,学习率就有必要十分小),即不同神经元权重 w1w_1w2w_2 所需的学习率也不同。因而,学习率(学习率初始值)的挑选需求参考输入的规模,这样不如直接将数据规范化,这样学习率就不必再依据数据规模作调整

1.4,Data Normalization 常用办法

1,z-Score Normalization

zero-mean Normalization,有时也称为 standardization,将数据特征缩放成均值为 0,方差为 1 的散布,对应公式:

x′=x−mean(x){x}’ = \frac{x-mean(x)}{\sigma}

其间:

  • xx:原始值
  • mean(x)mean(x):表明变量 xx 的均值(有些地方用 =1N∑i=1Nxi\mu =\frac{1}{N}\sum_{i=1}^{N} x_i
  • \sigma: 表明变量的规范差(整体规范差数学界说 =1N∑i=1N(xi−)2\sigma = \sqrt{\frac{1}{N} \sum_{i=1}^{N}(x_i – \mu)^2}
  • x′{x}’ 是数据缩放后的新值

通过 zero-mean Normalization 操作之后的数据正态散布函数曲线图会发生如下所示转化。

深度学习炼丹-数据标准化

其间,正态散布函数曲线中均值和规范差值的确定参考下图。

深度学习炼丹-数据标准化

2,Min-Max Normalization

履行线性操作,将数据规模缩放到 [0,1][0,1] 区间内,对应公式:

x′=x−min(x)max(x)−min(x){x}’ = \frac{x – min(x)}{max(x) – min(x)}

其间 max(x)max(x) 是变量最大值,min(x)min(x) 是变量最小值。

1.5,代码完成

z-Score Normalization 办法既能够调用相关 python 库的 api 完成,也能够自己完成相关功用。

以下是运用 sklearn 相关类和基于 numpy 库完成 z-Score Normalization 功用,并给出数据直方图比照的示例代码。

代码不是特别规范,仅供参考,当作功用了解和试验测试用。

## 输出高清图画
%config InlineBackend.figure_format = 'retina'
%matplotlib inline
import numpy as np
from sklearn import preprocessing
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
np.random.seed(42)
plt.figure(dpi = 200)
plt.figure(figsize=(20, 15))
# X_train = np.array([[ 10., -1.7,  21.4],
#                     [ 2.4,  0.,  0.6],
#                     [ 0.9,  1., -1.9]])
# 生成指定 size 和 规模 [low,high) 的随机浮点数
X_train = np.random.uniform(low=0.0, high=100.0, size = (100, 15))
# 1, 制作原始数据的直方图
plt.subplot(3, 1, 1)
plt.title("original data distribution")
sns.distplot(X_train, color='y')
# 2, 运用 sklearn 库的 z-Score Normalization 类,并制作直方图
scaler = preprocessing.StandardScaler().fit(X_train)
X_scaled = scaler.transform(X_train)
plt.subplot(3, 1, 2)
plt.title("z-Score Normalization by sklearn")
sns.distplot(X_scaled, color='r')
# 3,利用 numpy 函数完成 z-Score Normalization,并制作直方图
def z_Score_Normalization(data):
    data_mat = np.array(data)
    data_z_np = (data_mat - np.mean(data_mat, axis=0)) / np.std(data_mat, axis=0)
    return data_z_np
data_scaled = z_Score_Normalization(X_train)
plt.subplot(3, 1, 3)
plt.title("z-Score Normalization by numpy")
sns.distplot(data_scaled, color='g')

程序输出成果如下。能够看出通过 z-Score Normalization 操作之后,原始数据的散布转化成平均值为 =0\mu=0,规范差为 =1\sigma = 1 的正太散布(称为规范正态散布)。

深度学习炼丹-数据标准化

Min-Max Normalization 办法的完成比较简略,以下是基于 numpy 库完成 Min-Max Normalization 功用的示例代码:

# 导入必要的库
import numpy as np
# 界说数据集
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
def Min_Max_Normalization(X):
    # 核算数据集的最小值和最大值
    Xmin = X.min()
    Xmax = X.max()
    # 核算最小-最大规范化
    X_norm = (X - Xmin) / (Xmax - Xmin)
    return X_norm
# 打印成果
print(Min_Max_Normalization(X))

程序输出成果如下,能够看出原始数组数据都被缩放到 [0,1][0, 1] 规模内了。

深度学习炼丹-数据标准化

二,normalize images

2.1,图画 normalization 界说

当咱们运用卷积神经网络处理核算机视觉使命时,一般需求对输入图画数据做 normalization 来完结预处理工作,常见的图画 normalization 办法有两种: min-max normalizationzero-mean normalization

1,以单张图画的 zero-mean Normalization 为例,它使得图画的均值和规范差别离变为 0.01.0。由于是多维数据,与纯表格数据不同,它首要需求从每个输入通道中减去通道平均值,然后将成果除以通道规范差。因而可界说两种 normalization 形式如下所示:

# min-max Normalization
output[channel] = (input[channel] - min[channel]) / (max[channel] - min[channel])
# zero-mean Normalization
output[channel] = (input[channel] - mean[channel]) / std[channel]

2.2,图画 normalization 的好处

图画 normalization 有助于使数据处于必定规模内并削减偏度skewness),从而有助于模型更快更好地学习。归一化还能够处理梯度递减和爆炸的问题。

2.3,PyTorch 实践图画 normalization

Pytorch 框架中,图画变换(image transformation)是指将图画像素的原始值改变为新值的进程。其间常见的 transformation 操作是运用 torchvision.transforms.ToTensor() 办法将图画变换为 Pytorch 张量(tensor),它完成了将像素规模为 [0, 255] 的 PIL 图画转化为形状为(C,H,W)且规模为 [0.0, 1.0] 的 Pytorch FloatTensor。另外,torchvision.transforms.normalize() 办法完成了逐 channel 的对图画进行规范化(均值变为 0,规范差变为 1)。总结如下:

  • min-max Normalization: 对应 torchvision.transforms.ToTensor() 办法
  • zero-mean Normalization: 对应 torchvision.transforms.Normalize() 办法,利用用均值和规范差对张量图画进行 zero-mean Normalization。

ToTensor() 函数的语法如下:

"""
Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.
Converts a PIL Image or numpy.ndarray (H x W x C) in the range
[0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0].
Args:
    pic (PIL Image or numpy.ndarray): Image to be converted to tensor.
Returns:
    Tensor: Converted image.
"""

Normalize() 函数的语法如下:

Syntax: torchvision.transforms.Normalize()
Parameter:
    * mean: Sequence of means for each channel.
    * std: Sequence of standard deviations for each channel.
    * inplace: Bool to make this operation in-place.
Returns: Normalized Tensor image.

在 PyTorch 中对图画履行 zero-mean Normalization 的进程如下:

  1. 加载原图画;
  2. 运用 ToTensor() 函数将图画转化为 Tensors;
  3. 核算 Tensors 的均值和方差;
  4. 运用 Normalize() 函数履行 zero-mean Normalization 操作。

下面给出利用 PyTorch 实践 Normalization 操作的具体代码和输出图。

# import necessary libraries
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
def show_images(imgs, num_rows, num_cols, titles=None, scale=8.5):
    """Plot a list of images.
    Defined in :numref:`sec_utils`"""
    figsize = (num_cols * scale, num_rows * scale)
    _, axes = plt.subplots(num_rows, num_cols, figsize=figsize)
    axes = axes.flatten()
    for i, (ax, img) in enumerate(zip(axes, imgs)):
        try:
            img = np.array(img)
        except:
            pass
        ax.imshow(img)
        ax.axes.get_xaxis().set_visible(False)
        ax.axes.get_yaxis().set_visible(False)
        if titles:
            ax.set_title(titles[i])
    return axes
def normalize_image(image_path):
    img = Image.open(img_path) # load the image
    # 1, use ToTensor function
    transform = transforms.Compose([
        transforms.ToTensor()
    ])
    img_tensor = transform(img) # transform the pIL image to tensor
    # 2, calculate mean and std by tensor's attributes
    mean, std = img_tensor.mean([1,2]), img_tensor.std([1,2])
    # 3, use Normalize function
    transform_norm = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize(mean, std)
    ])
    img_normalized = transform_norm(img) # get normalized image
    img_np = np.array(img) # convert PIL image to numpy array
    # print array‘s shape mean and std
    print(img_np.shape) # (height, width, channel), (768, 1024, 3)
    print("mean and std before normalize:")
    print("Mean of the image:", mean)
    print("Std of the image:", std)
    return img_np, img_tensor, img_normalized
def convert_tensor_np(tensor):
    img_arr = np.array(tensor)
    img_tr = img_arr.transpose(1, 2, 0)
    return img_tr
if __name__ == '__main__': 
    img_path = 'Koalainputimage.jpeg'
    img_np, img_tensor, img_normalized = normalize_image(img_path)
    # transpose tensor to numpy array and shape of (3,,) to shape of (,,3)
    img_normalized1 = convert_tensor_np(img_tensor)
    img_normalized2 = convert_tensor_np(img_normalized)
    show_images([img_np, img_normalized1, img_normalized2], 1, 3, titles=["orignal","min-max normalization", "zero-mean normalization"])

1,程序输出和两种 normalization 操作作用可视化比照图如下所示:

深度学习炼丹-数据标准化

2,原图和两种 normalization 操作后的图画像素值散布可视化比照图如下所示:

深度学习炼丹-数据标准化

像素值散布可视化用的代码如下。

# plot the pixel values
plt.hist(img_np.ravel(), bins=50, density=True)
plt.xlabel("pixel values")
plt.ylabel("relative frequency")
plt.title("distribution of pixels")

参考资料

  • A Simple Guide to Data Preprocessing in Machine Learning
  • Data Normalization in Data Mining
  • scikit-learn-6.3. Preprocessing data
  • numpy.ravel
  • 05.3 样本特征数据规范化
  • numpy np.random生成随机数
  • How To Compute Z-scores in Python