Python数据预处理(包括处理数据离散值和归一化,分开处理训练集与测试集)
flyfish
引用自百度的深度学习系统PaddlePaddle中的线性回归部分代码
数据预处理的代码分析
代码摘抄自PaddlePaddle,经过修改在Windows 10下 Python3.6下编译通过
import numpy as np
import matplotlib.pyplot as plt
import os
feature_names = [
'CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX',
'PTRATIO', 'B', 'LSTAT', 'convert'
]
def feature_range(maximums, minimums):
import matplotlib
#matplotlib.use('Agg')
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
feature_num = len(maximums)
ax.bar(range(feature_num), maximums - minimums, color='r', align='center')
ax.set_title('feature scale')
plt.xticks(range(feature_num), feature_names)
plt.xlim([-1, feature_num])
fig.set_figheight(6)
fig.set_figwidth(10)
if not os.path.exists('./image'):
os.makedirs('./image')
fig.savefig('image/ranges.png', dpi=48)
plt.close(fig)
def load_data(filename, feature_num=14, ratio=0.8):
#加载数据,数据之间由空格隔开
data = np.fromfile(filename, sep=' ')
print(data.shape)
print(data.shape[0])#7084
print(data.shape[0] / feature_num)#506
data = data.reshape( int(data.shape[0] / feature_num), feature_num)
print(data.shape)#(506, 14)
maximums, minimums, avgs = data.max(axis=0), data.min(axis=0), data.sum(
axis=0) / data.shape[0]
feature_range(maximums[:-1], minimums[:-1])
for i in range(feature_num - 1):
data[:, i] = (data[:, i] - avgs[i]) / (maximums[i] - minimums[i])
#整理训练集与测试集
offset = int(data.shape[0] * ratio)
UCI_TRAIN_DATA = data[:offset]
UCI_TEST_DATA = data[offset:]
load_data(r"H:\1.data")
关于代码解释先用示例程序解释
import numpy as np
#x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
x = np.array([1.0, 9.0, 300.0, 4.0, 400.0, 60.0, 7.0, 8.0,90,100,11,12])
print(x.shape)#(8,)
feature_num=4
print(x.shape[0] / feature_num)# 2.0
x = x.reshape(int(x.shape[0] / feature_num), feature_num)
print(x.shape)# 2,4 2行4列
print(x.shape[0])#2 取出行数
print(x.shape[1])#4 取出列数
#reshape 将一个1维 转换成二维
maximums, minimums, avgs = x.max(axis=0), x.min(axis=0), x.sum(axis=0) / x.shape[0]
print(maximums)#[5. 6. 7. 8.]
print(minimums)#[1. 2. 3. 4.]
print(avgs)#[3. 4. 5. 6.]
#avgs表示平均数
'''
ndarray.max([int axis])
函数功能:求ndarray中指定维度的最大值,默认求所有值的最大值。
axis=0:求各column的最大值
axis=1:求各row的最大值
[1.0, 9.0, 300.0, 4.0,
400.0, 60.0, 7.0, 8.0,
90,100,11,12])
参数为0输出结果是
[400. 100. 300. 12.]
[1. 9. 7. 4.]
[163.67 56.33 106. 8. ]
其他函数参考max
'''
print(maximums[:-1])#[5. 6. 7.] 去除最后一列
print(minimums[:-1])#[1. 2. 3.]
for i in range(feature_num - 1):#归一化(normalization)
x[:, i] = (x[:, i] - avgs[i]) / (maximums[i] - minimums[i])
print(x[:, i])
'''
输出
[-0.5 0.5]
[-0.5 0.5]
[-0.5 0.5]
如果是[1.0, 9.0, 300.0, 4.0, 400.0, 60.0, 7.0, 8.0,90,100,11,12] 则输出
[-0.40768588 0.59231412 -0.18462824]
[-0.52014652 0.04029304 0.47985348]
[ 0.66211604 -0.33788396 -0.32423208]
'''
# 第一个冒号代表获取行的起止行号
# 第二个冒号代表获取列的起止行号
以下文字全部引用自PaddlePaddle的线性回归
连续值与离散值
观察一下数据,我们的第一个发现是:所有的13维属性中,有12维的连续值和1维的离散值(CHAS)。
离散值虽然也常使用类似0、1、2这样的数字表示,但是其含义与连续值是不同的,因为这里的差值没有实际意义。
例如,我们用0、1、2来分别表示红色、绿色和蓝色的话,我们并不能因此说“蓝色和红色”比“绿色和红色”的距离更远。
所以通常对一个有d 个可能取值的离散属性,
我们会将它们转为d 个取值为0或1的二值属性或者将每个可能取值映射为一个多维向量。
不过就这里而言,因为CHAS本身就是一个二值属性,就省去了这个麻烦
。
属性的归一化
另外一个稍加观察即可发现的事实是,各维属性的取值范围差别很大(如图2所示)。例如,属性B的取值范围是[0.32,
396.90],而属性NOX的取值范围是[0.3850, 0.8170]。这里就要用到一个常见的操作-归一化(normalization)了。归一化的目标是把各位属性的取值范围放缩到差不多的区间,例如[-0.5,0.5]。这里我们使用一种很常见的操作方法:减掉均值,然后除以原取值范围。做归一化(或 Feature scaling)至少有以下3个理由: •过大或过小的数值范围会导致计算时的浮点上溢或下溢。
•不同的数值范围会导致不同属性对模型的重要性不同(至少在训练的初始阶段如此),而这个隐含的假设常常是不合理的。这会对优化的过程造成困难,使训练时间大大的加长。
•很多的机器学习技巧/模型(例如L1,L2正则项,向量空间模型-Vector Space
Model)都基于这样的假设:所有的属性取值都差不多是以0为均值且取值范围相近的。
整理训练集与测试集
我们将数据集分割为两份:一份用于调整模型的参数,即进行模型的训练,模型在这份数据集上的误差被称为训练误差;另外一份被用来测试,模型在这份数据集上的误差被称为测试误差。我们训练模型的目的是为了通过从训练数据中找到规律来预测未知的新数据,所以测试误差是更能反映模型表现的指标。分割数据的比例要考虑到两个因素:更多的训练数据会降低参数估计的方差,从而得到更可信的模型;而更多的测试数据会降低测试误差的方差,从而得到更可信的测试误差。我们这个例子中设置的分割比例为8:2
8:2在更复杂的模型训练过程中,我们往往还会多使用一种数据集:验证集。因为复杂的模型中常常还有一些超参数(Hyperparameter)需要调节,所以我们会尝试多种超参数的组合来分别训练多个模型,然后对比它们在验证集上的表现选择相对最好的一组超参数,最后才使用这组参数下训练的模型在测试集上评估测试误差。由于本章训练的模型比较简单,我们暂且忽略掉这个过程。