机器学习笔记(六):数据归一化 | 凌云时刻

凌云时刻 · 技术

导读:上一篇笔记的主要内容是机器学习算法中的一些主要概念,比如训练数据集、测试数据集,分类准确度,超参数。这一篇笔记会继续讲解另一主要概念:数据归一化。另外会具体用代码实现第一篇笔记中介绍过的线性回归算法。

作者 | 计缘

来源 | 凌云时刻(微信号:linuxpk)

数据归一化

  

大家先看看上面表格中的样本数据,两个样本的肿瘤大小相差有5倍,从医学角度来讲这个差距已经是非常大了,但从实际数值差距来讲并不是很大。再看看发现时间,两个样本之间相差100天,在数值上的差距远远大于肿瘤大小的差距。所以如果使用kNN算法,用欧拉距离计算的话,两个样本发现时间之差远远大于肿瘤大小之差,所以就会主导样本间的距离,这个显然是有问题的,对预测的结果是有偏差的。

所以我们就需要对样本数据进行数据归一化,将所有的数据映射到同一尺度。比较简便的方式就是最值归一化,既用下面的公式把所有数据映射到0-1之间:

     

最值归一化虽然简便,但是是有一定适用范围的,那就是适用于样本数据有明显分布边界的情况,比如学生的考试分数,从0到100分,或者像素值,从0到255等。假如像人的月收入这种没有边界的样本数据集,就不能使用最值归一化了,此时就需要用到另外一个数据归一化的方法均值方差归一化,该方法就是把所有数据归一到均值为0方差为1的分布中,公式如下:


   

就是将每个值减去均值,然后除以方差,通过均值方差归一化后的数据不一定在0-1之间,但是他们的均值为0,方差为1。

下面我们来分别实现一下这两个数据归一化方法。先来看看最值归一化的实现:

  

import numpy as np
import matplotlib.pyplot as plt
# 生成从0到100,一共100个元素的数组
x = np.random.randint(0, 100, size = 100)
# 变更数组元素的类型
x = np.array(x, dtype = float)
x_scale = (x - np.min(x)) / (np.max(x) - np.min(x))

# 生成50行,2列的矩阵,元素在0到100之间
X = np.random.randint(0, 100, (50, 2))
# 对每一列数据进行最值归一化
X[:, 0] = (X[:, 0] - np.min(X[:, 0])) / (np.max(X[:, 0]) - np.min(X[:, 0]))
X[:, 1] = (X[:, 1] - np.min(X[:, 1])) / (np.max(X[:, 1]) - np.min(X[:, 1]))

# 用matplotlib将X展示出来
plt.scatter(X[:, 0], X[:, 1])
plt.show()

  


可以看到最值归一化后数据都在0到1之间。我们再来看看均值方差归一化的实现:

  

X2 = np.random.randint(0, 100, (50, 2))
X2 = np.array(X2, dtype = float)
X2[:, 0] = (X2[:, 0] - np.mean(X2[:, 0])) / np.std(X2[:, 0])
X2[:, 1] = (X2[:, 1] - np.mean(X2[:, 1])) / np.std(X2[:, 1])

# 均值接近0
np.mean(X2[:, 0])
# 结果
6.2172489379008772e-17

# 方差接近1
np.std(X2[:, 0])
# 结果
0.99999999999999989

plt.scatter(X2[:, 0], X2[:, 1])
plt.show()

 

如何对测试数据集进行归一化

之前我们说过会对样本数据进行拆分,拆分为训练数据和测试数据,对于训练数据我们可以直接使用最值归一化或均值方法归一化,但是对测试数据我们就不能直接使用归一化的方法了,因为测试数据其实充当了真实环境中需要预测的数据,很多时候需要预测的数据只有一组,这时候我们是没办法对一组数据进行归一化的,因为无法得到均值和方差,所以我们需要结合归一化后训练数据归一化测试数据:(x_test - mean_train) / std_train。那么我们就需要保存训练数据归一化后的数据,此时我们就可以用到Scikit Learn提供的数据归一化的对象Scalar

 

 

Scalar的使用流程和机器学习算法的使用流程很像,输入训练数据集,进行fit操作,这里的fit操作就不是训练模型了,而是进行数据归一化处理,然后是transform,既对需要预测的数据进行归一化。我们来看看如何使用:

 

# 使用鸢尾花数据集
import numpy as np
from sklearn import datasets

iris = datasets.load_iris()
X = iris.data
y = iris.target

# 分割出训练数据集和测试数据集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 666)

# 导入StandardScaler,也就是均值方差归一化的对象
from sklearn.preprocessing import StandardScaler
standardScaler = StandardScaler()
standardScaler.fit(X_train)

# 将特征训练数据集和特征测试数据集进行归一化处理
X_train_standard = standardScaler.transform(X_train)
X_test_standard = standardScaler.transform(X_test)

# 使用kNN
from sklearn.neighbors import KNeighborsClassifier
knn_clf = KNeighborsClassifier(n_neighbors = 3)
knn_clf.fit(X_train_standard, y_train)
knn_clf.score(X_test_standard, y_test)

封装自己的数据归一化方法

 

import numpy as np

class StandardScaler:

	def __init__(self):
		self.mean_ = None
		self.scaler_ = None

	# 获取训练数据集的平均值和方差
	def fit(self, X):
		assert X.ndim == 2, "X 的维度必须为2,既X是一个矩阵"

		self.mean_ = np.array([np.mean(X[:, i]) for i in range(X.shape[1])])
		self.scaler_ = np.array([np.std(X[:, i]) for i in range(X.shape[1])])

		return self

	# 进行均值方差归一化处理
	def transform(self, X):
		assert X.ndim == 2, "X 的维度必须为2,既X是一个矩阵"
		assert self.mean_ is not None and self.scaler_ is not None, "均值和方差不能为空"
		assert X.shape[1] == len(self.mean_), "训练数据集矩阵的列数必须等于均值数组的元素个数"
		assert X.shape[1] == len(self.scaler_), "训练数据集矩阵的列数必须等于方差数组的元素个数"

		X_transform = np.empty(shape=X.shape, dtype=float)
		for col in range(X.shape[1]):
			X_transform[:, col] = (X[:, col] - self.mean_[col]) / self.scaler_[col]

		return X_transform

  

这样我们就封装好了自己的均值方差归一化的方法,另外,Scikit Learn也提供了最值归一化的对象MinMaxScaler,使用流程都是一样的,大家也可是试试看。

总结

这一篇笔记主要介绍了kNN算法实现逻辑以外的概念,但也是机器学习中非常重要的一些概念,以后也会经常看到它们的身影。通过四篇笔记的介绍,我们知道kNN算法是一个解决多分类问题的算法,而且算法实现相对比较简单,但效果很强大。下一篇我们来实现第一篇笔记中介绍过的线性回归法。

  

 

END

往期精彩文章回顾

机器学习笔记(五):超参数

机器学习笔记(四):kNN算法

机器学习笔记(三):NumPy、Matplotlib、kNN算法

机器学习笔记(二):矩阵、环境搭建、NumPy

机器学习笔记(一):机器的学习定义、导数和最小二乘

Kafka从上手到实践 - 实践真知:搭建Kafka相关的UI工具

Kafka从上手到实践 - Kafka集群:启动Kafka集群

Kafka从上手到实践 - Kafka集群:Kafka Listeners

Kafka从上手到实践 - Kafka集群:配置Broker

Kafka从上手到实践:搭建Zookeeper集群

长按扫描二维码关注凌云时刻

每日收获前沿技术与科技洞见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值