本文共 1482 字,大约阅读时间需要 4 分钟。
许多技术对数据尺度很敏感。例如,设想一下,你有包含数百数据科学家身高(height)、体重(weight)的数据集,你正在尝试对其进行聚类。
直观上,我们想要聚集区表示彼此靠近的点集,这个意思是我们需要点之间距离的概念。我们已经掌握了欧式距离(Euclidean distance)函数,所以一个自然的方法可以把(height, weight)对看成二维空间里的点集。考虑下面的列表:
如果我们用英尺(inches)测量身高,那么B的最近的邻居就是A:
a_to_b = distance([63, 150], [67, 160]) # 10.77a_to_c = distance([63, 150], [70, 171]) # 22.14b_to_c = distance([67, 160], [70, 171]) # 11.40
然而,如果我们用厘米(centimeters)测量身高,那么B的最近邻居就是C:
a_to_b = distance([160, 150], [170.2, 160]) # 14.28a_to_c = distance([160, 150], [177.8, 171]) # 27.53b_to_c = distance([170.2, 160], [177.8, 171]) # 13.37
很显然,如果改变单位能改变结果,这是有问题的。为了解决这个问题,我们有时候改变数据的尺度,以便每个维度的均值为0,标准差为1。这种方法能够有效消除单位的影响。
首先,我们需要计算每一维度的均值和标准差:
def scale(data_matrix): """returns the means and standard deviations of each column""" num_rows, num_cols = shape(data_matrix) means = [mean(get_column(data_matrix,j)) for j in range(num_cols)] stdevs = [standard_deviation(get_column(data_matrix,j)) for j in range(num_cols)] return means, stdevs
使用它们创建新的数据矩阵:
def rescale(data_matrix): """rescales the input data so that each column has mean 0 and standard deviation 1 leaves alone columns with no deviation""" means, stdevs = scale(data_matrix) def rescaled(i, j): if stdevs[j] > 0: return (data_matrix[i][j] - means[j]) / stdevs[j] else: return data_matrix[i][j] num_rows, num_cols = shape(data_matrix) return make_matrix(num_rows, num_cols, rescaled)