以下文章来源于木东居士 ,作者Japson https://mp.weixin.qq.com/s/RkenakI_DSXoMLwNNvUAAw
1.1 为什么要数据归一化
在实际应用中,样本的不同特征的单位不同,会在求距离时造成很大的影响。比如:在两个样本中肿瘤大小的分别为1cm和5cm,发现时间分别为100天和200天,那么在求距离时,时间差为100、大小差为4,那么其结果会被时间所主导,因为肿瘤大小的差距太小了。但是如果我们把时间用年做单位,0.27年与0.55年的差距又远小于肿瘤大小的差距,结果又会被大小主导了。 我们发现,在量纲不同的情况下,以上的情况,不能反映样本中每一个特征的重要程度。这就需要数据归一化了。 一般来说,我们的解决方案是:把所有的数据都映射到同一个尺度(量纲)上。 一般来说,常用的数据归一化有两种: 最值归一化(normalization): 把所有数据映射到0-1之间。最值归一化的使用范围是特征的分布具有明显边界的(分数0~100分、灰度0~255),受outlier的影响比较大
均值方差归一化(standardization): 把所有数据归一到均值为0方差为1的分布中。适用于数据中没有明显的边界,有可能存在极端数据值的情况.
1.2 最值归一化实现
为了了解最值归一化的代码实现,我们可以创建100个随机数,然后对其进行最值归一化。
import numpy as np
#创建100个随机数
x = np.random.randint(0,100,size=100)
#最值归一化(向量)
#最值归一化公式,映射到0,1之间
(x-np.min(x))/(np.max(x) - np.min(x))
#最值归一化(矩阵)
#0~100范围内的50*2的矩阵
X = np.random.randint(0,100,(50,2)) #?
#最值归一化公式,对于每一个维度(列方向)进行归一化
#X[:,0]第一列,第一个特征
X[:,0] = (X[:,0] - np.min(X[:,0]))/(np.max(X[:,0]) - np.min(X[:,0]))
#X[:,0]第一列,第一个特征
X[:,1] = (X[:,1] - np.min(X[:,1]))/(np.max(X[:,1]) - np.min(X[:,1]))
#如果有n个特征,可以写个循环-
for i in range(0,2):
X[:,i] = (X[:,i]-np.min(X[:,i])) / (np.max(X[:,i]) - np.min(X[:,i]))
X = np.random.randint(0,100,(50,2))
下面我们可以简单地绘制样本,并使用np.mean()/np.std()来计算其均值和方差
import matplotlib.pyplot as plt
#简单绘制样本,看横纵坐标
plt.scatter(X[:,0],X[:,1])
plt.show()

1.3 均值方差归一化实现
同样地,为了了解均值方差归一化的代码实现,我们可以创建100个随机数,然后对其进行均值方差归一化。
X2 = np.array(np.random.randint(0,100,(50,2)),dtype = float)
#套用公式,对每一列做均值归一化
for i in range(0,2):
X2[:,i]=(X2[:,i]-np.mean(X2[:,i]))/np.std(X2[:,i])

计算器均值/方差
np.mean(X2[:,0])# x
np.std(X2[:,1])#y
1.4 Sklearn中的归一化
首先我们来看一个在实际使用归一化时的一个小陷阱。 我们在建模时要将数据集划分为训练数据集&测试数据集。 训练数据集进行归一化处理,需要计算出训练数据集的均值mean_train和方差std_train。 问题是:我们在对测试数据集进行归一化时,要计算测试数据的均值和方差么? 答案是否定的。在对测试数据集进行归一化时,仍然要使用训练数据集的均值train_mean和方差std_train。这是因为测试数据是模拟的真实环境,真实环境中可能无法得到均值和方差,对数据进行归一化。只能够使用公式(x_test - mean_train) / std_train并且,数据归一化也是算法的一部分,针对后面所有的数据,也应该做同样的处理. 因此我们要保存训练数据集中得到的均值和方差。 在sklearn中专门的用来数据归一化的方法:StandardScaler。
下面我们加载鸢尾花数据集
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
iris = datasets.load_iris()
X = iris.data
y = iris.target
X_train,X_test,y_train,y_test = train_test_split(iris.data,iris.target,test_size=0.2,random_state=666)
使用数据归一化的方法:
from sklearn.preprocessing import StandardScaler
standardScaler = StandardScaler()
#归一化的过程跟训练模型一样
standardScaler.fit(X_train)
standardScaler.mean_
standardScaler.scale_ #表述数据分布范围的变量,替代std_
#使用transform
X_train_standard = standardScaler.transform(X_train)
y_train_standard = standardScaler.transform(X_test)
如此就能输出归一化后的数据了。
1.5 自己实现均值方差归一化
同样地,我们仿照sklearn的风格,可以自己实现一下均值方差归一化的方法。 我们在之前的工程中创建processing.py:
3.4 sklearn中的KDTree
Sklearn中有KDTree的实现,仅构建了一个二维空间的k-d tree,然后对其作k近邻搜索及指定半径的范围搜索。多维空间的检索,调用方式与此例相差无多。
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import Circle
from sklearn.neighbors import KDTree
np.random.seed(0)
points = np.random.random((100,2))
tree = KDTree(points)
point = points[0]
#kNN
dists,indices = tree.query([point],k=3)
print(dists,indices)
#query radius
indices = tree.query_radius([point],r=0.2)
print(indices)
fig = plt.figure()
ax = fig.add_subplot(111,aspect='equal')
ax.add_patch(Circle(point,0.2,color='r',fill=False))
X,Y = [p[0] for p in points],[p[1] for p in points]
plt.scatter(X,Y)
plt.scatter([point[0]],[point[1]],c='r')
plt.show()

网友评论