上一篇介绍了如何将缺失值如何处理
代码及数据集
链接:https://pan.baidu.com/s/1tEz3gkTfmZjD-0JaC-nhVQ 密码:l16a
数据清洗知识脉络
缺失值识别
缺失值处理
归一化
归一化
- 由于机器学习模型收到scale的影响很大,如果有极端离群值可能对某些机器学习算法影响非常大
受尺度影响的算法
- KNN --因为依赖欧几里得距离
- K均值聚类 – 和KNN一样
- 逻辑回归、SVM、神经网络(如果使用梯度下降来学习权重)
- 主成分分析–特征向量将偏向较大的列
归一化
- 将所有定量列转化为同一个静态范围内的值
- 或者使用数据规则:所有列的均值和标准差必须相同
标准化
- 通过确保所有行和列在机器学习中得到平等的对待,让数据的处理保持一致
方法
- Z分数标准化
- min-max标准化
- 行归一化
数据集说明
- 数据集:皮马印第安人糖尿病预测数据集
- 数据来源:https://www.kaggle.com/uciml/pima-indians-diabetes-database
- 数据9列,768行
- 该数据希望通过体检结果细节,预测21岁以上的女性5年内会否会换上糖尿病
数据含义
- 怀孕次数
- 口服葡萄糖耐量试验中的2小时血浆葡萄糖浓度
- 舒张压(mmHg)
- 三头肌皮褶厚度(mm)
- 体重指数[BMI]
- 2小时血清胰岛素浓度(uU/ml)
- 糖尿病家族函数
- 年龄
- 类变量(0/1,代表是否患有糖尿病)
pima = pd.read_csv('data/pima.data', names=pima_colunmn_names)
# 使用前一章讲的填充方法使用均值填充
impute = Imputer(strategy='mean')
pima_imputed_mean = pd.DataFrame(impute.fit_transform(pima),
columns=pima_colunmn_names)
# 对数据进行可视化,画出直方图
pima_imputed_mean.hist(figsize=(15,15))
# 通过数据表查看具体数值
pima_imputed_mean.describe().T
- 可以看出每列的均值,最小最大值和标准差差别都很大
- 此表也可看出数据不平衡
- 因为一些机器学习模型接受尺度(scale) 的影响很大
- 例如 BloodPressure 在24-122之间 但是Insulin在14-846之间,这样对模型的影响很大
# 共享x轴进行可视化
pima_imputed_mean.hist(figsize=(15, 15), sharex=True)
- 如图可以看到当数据不进行归一化处理时,由于每个特征的尺度不同可能会导致一些特征的权重被动的减小。
- 例如Insulin的数据尺度比较大,相较于该列在机器学习模型中形成的影响,Pregnaci的影响就变小了非常多。
Z分数标准化
Z-score–标准数
- Z分数标准化的输出会被重新缩放,使均值为0,标准差为1
- 通过缩放特征、统一化均值和方差,可以使KNN达到最优化,而不会倾向于较大比例的特征
z = x − μ σ z = \frac{x-\mu}{\sigma} z=σx−μ- z : 新 的 值 z:新的值 z:新的值
- x : 原 值 x:原值 x:原值
- μ : 该 列 均 值 \mu :该列均值 μ:该列均值
- σ : 该 列 标 准 差 \sigma :该列标准差 σ:该列标准差
公式法
- 通过以上公式对数据进行标准化
mu = pima['Glucose'].mean()
sigma = pima['Glucose'].std()
((pima['Glucose'] - mu)/sigma)
使用scikit-learn进行z分数标准化
from sklearn.preprocessing import StandardScaler
print(pima['Glucose'].mean(),
pima['Glucose'].std())
# 均值:120.89453125 标准差:31.97261819513622
# 对标准化前进行可视化
ax = pima['Glucose'].hist()
ax.set_title('Distribution of Glucose')
# 实例化
scaler = StandardScaler()
Glucose_z_score = scaler.fit_transform(pima[['Glucose']])
# 使用双方括号因为转换需要一个dataframe
print(Glucose_z_score.mean(), Glucose_z_score.std())
# 此时均值为-9.25185853854297e-18 标准差为1.0
# 标准化之后可视化
ax = pd.Series(Glucose_z_score.reshape(-1, )).hist()
ax.set_title('Distributiopn of Glucose after Z score Scaling')
- 数据形状不会发生变化 但是x轴发生了变化
- 对所有数据进行一个z分数标准化
对所有列进行标准化
scale = StandardScaler()
pima_imputed_mean_scaled = pd.DataFrame(scale.fit_transform(pima_imputed_mean), columns=pima_colunmn_names)
pima_imputed_mean_scaled.hist(figsize=(15, 15), sharex=True)
min-max 标准化
m
=
(
x
−
x
m
i
n
)
(
x
m
a
x
−
x
m
i
n
)
m = \frac{(x - x_{min})}{(x_{max} - x_{min})}
m=(xmax−xmin)(x−xmin)
m : 新值
x : 原值
xmin : 该列最小值
xmax : 该列最大值
** 所有值都会被缩放到0-1这个区间**
from sklearn.preprocessing import MinMaxScaler
min_max = MinMaxScaler()
pima_min_max = MinMaxScaler()
# 使用min-max scaler
pima_min_maxed = pd.DataFrame(min_max.fit_transform(pima_imputed), columns=pima_colunmn_names)
pima_min_maxed.describe().T
- minmaxscaler对异常值非常敏感,因为是以最大最小值进行缩放的,异常值权重被降低了
行归一化
不是计算每列的统计值,而是保证每行有单位范数,意味着每行的向量长度相同
- n维空间中每行都有一个向量范数
- 认为每一行都是空间内的一个向量:
x = ( x 1 , x 2 , . . . x n ) x = (x_1, x_2,...x_n) x=(x1,x2,...xn) - 该数据集中n为8,响应特征不算,该范数计算方法为:
∣ ∣ x ∣ ∣ = ( x 1 2 + x 2 2 + . . . + x n 2 ) ||x||= \sqrt{(x_1^2+x_2^2+...+x_n^2)} ∣∣x∣∣=(x12+x22+...+xn2)
这里为L2范数
让每行有相同的范数,在使用文本数据或聚类算法是,非常方便
# 计算矩阵的平均范数
np.sqrt((pima_imputed**2).sum(axis=1)).mean()
# 223.36222025823747
# 进行行归一化
from sklearn.preprocessing import Normalizer
normalize = Normalizer()
pima_normalized = pd.DataFrame(normalize.fit_transform(pima_imputed),
columns=pima_colunmn_names)
np.sqrt((pima_normalized**2).sum(axis=1).mean())
# 行归一化后的平均范数为1