神经网络在多分类上的应用——数据预处理部分
标签: 神经网络 多分类
- 首先建立思路,然后在实行过程中根据需求找方法和工具。
- 本文以
用三层神经网络识别给定的图片是人,猫还是狗
项目为例,记录实现过程中的思路,遇到的难点和多次的调整。
目录
数据预处理
主要工具:pandas
matplotlib
seaborn
numpy
sklearn
- 项目已给定经过预处理后较小的数据集data.csv,数据集中仅含提取的图像的特征结果。数据集部分如下面表格形式:
feature1 | feature2 | feature3 | feature4 | class |
---|---|---|---|---|
5.1 | 1400 | 1.4 | 2 | 0 |
4.9 | 1200 | 1.4 | 2 | 0 |
4.7 | 1280 | 1.3 | 2 | 0 |
[数据集描述]
数据集含有4个特征每个输入的x向量有4个坐标
;每行代表一个图像;class代表图像的类别:有三种情况——0代表是人,1代表是猫,2代表是狗
[加载数据]
使用pandas包读取data文件为DataFrame格式。
dataset = pd.read_csv('data.csv')
[数据集随机化]
由表格可以看出,数据集仍需要进一步处理:
数据集是按类别分类后按顺序依次排列的,需要将其打乱。
已知python自带有shuffle方法,这里dataset为DataFrame格式,可以使用pandas中设定抽取比例为1时的sample方法。
# 打乱后索引仍按照正常的排序
dataset = dataset.sample(frac=1).reset_index(drop=True)
[数据分析——数据可视化]
使用matplotlib
包和seaborn
工具绘制数据图,直观分析它们之间的关系和数据的特点。
matplotlib
- 选取feature1和feature2作为二维图像的横纵坐标;
- 分别取出类别为人,猫和狗时的二维特征数组;
- 分别绘制不同颜色的散点图,注意这三种类别的数据点应该体现在一张二维图像上。
代码如下:
def plot_points(dataset):
X = np.array(dataset[["feature1", "feature2"]]) # X保存特征,先绘制二维图(选取feature1和feature2)
y = np.array(dataset["class"]) # y保存类别
people = X[np.argwhere(y == 0)] # 取出图片为人时的特征值数组
cat = X[np.argwhere(y == 1)] # 取出图片为猫时的特征值数组
dog = X[np.argwhere(y == 2)] # 取出图片为狗时的特征值数组
# 对于类别为人,猫,狗,分别绘制不同颜色的数据点——对应于同一张二维坐标图
plt.scatter([s[0][0] for s in people], [s[0][1] for s in people], s=25, color='red', edgecolor='k')
plt.scatter([s[0][0] for s in cat], [s[0][1] for s in cat], s=25, color='cyan', edgecolor='k')
plt.scatter([s[0][0] for s in dog], [s[0][1] for s in dog], s=25, color='yellow', edgecolor='k')
plt.xlabel('Feature_1')
plt.ylabel('Feature_2')
plot_points(dataset)
plt.show() # 绘制散点图
绘制图像如下:
- 由上图可以看出仅依据两个特征并不能很好地分离图片类别。
seaborn
- 使用seaborn中的pairplot函数绘制多变量图——如本项目中特征有四个维度;
- 若pairplot的变量参数有n个,则会绘制n*n的方格。当i=j时,为直方图;i≠j时,为散点图;
- 仍然使用matplotlib的显示函数来显示图像。
代码如下:
import seaborn as sns # seaborn作为matplotlib的补充,导入后会覆盖matplotlib的默认作图风格
sns.pairplot(dataset, hue='class', vars=["feature1", "feature2", "feature3", "feature4"]) # hue : 使用指定变量为分类变量画图;vars : 与data使用,否则使用data的全部变量
plt.show() # 仍然使用matplotlib的显示函数
绘制图像如下:
- 根据四个特征维度,图像的类别得到了很好地分离
[数据分离——将数据集拆分为输入和标签]
在训练神经网络时,训练集的数据要分开使用:输入每个数据的n维特征,得到神经网络的输出结果,并将该结果与训练集中的类别[标签]来对比,构造误差函数等,从而利用梯度下降算法对神经网络的模型进行优化。
可以使用pandas
包中的iloc和loc属性,其中
- loc是根据DataFrame的行、列标签名来进行选取,可以选取单个元素,也可以选取一个区域
- iloc是根据DataFrame的行、列索引来进行选取,可以选取单个元素,也可以选取一个区域
代码如下:
data = dataset.iloc[0: 150, 0: 4] # 输入
# print(data)
label = dataset.iloc[0: 150, 4] # 标签
# print(label)
[数据标准化]
有时输入数据的几个特征(维度)所在的数值范围是不一致的,这意味着数据存在偏差,不利于神经网络的处理,需要将所有特征的值规划到同一数值范围内。
处理方法:一般将大的特征值缩小,可使用(x-min)/(max-min)规划到[0,1]的范围内。
本例代码:
data['feature2'] = (data['feature2'] - data['feature2'].min()) / (data['feature2'].max() - data['feature2'].min())
data['feature4'] = (data['feature4'] - data['feature4'].min()) / (data['feature4'].max() - data['feature4'].min())
[将类别(标签)进行One-hot编码]
- 原始训练集的类别为0,1,2,不容易进行神经网络的训练,需要对标签进行One-hot编码;即有n种类别便将每个图像的标签转化为n维向量,只有其对应正确类别的索引下的值为1,其余为0。
- 本项目是一个三分类问题,类别(离散特征)的取值之间没有大小关系,可以使用One-hot编码。[若有大小关系则采用数值映射的方式]
- 将标签进行One-hot编码后,可以对应softmax函数的概率分布意义,得到神经网络的预测结果并进行误差分析。
使用pandas
库中的get_dummies
方法进行One-hot编码:
one_hot_label = pd.get_dummies(label)
得到编码后的部分标签如下:
训练数据集和测试数据集的划分
- 为防止过拟合,需要将给定的数据集按一定的比例划分为训练集和测试集:训练集用于得到优秀的神经网络模型,测试集用于测试神经网络的泛化能力。
- 数据集划分的比例和组成不同也会对神经网络模型产生一定的影响
有很多方式可以进行数据集的随机划分:
- 使用
numpy.random.choice
- 使用
sklearn.model_selection.train_test_split
或sklearn.cross_validation.train_test_split
,其中cross_validation指交叉验证。
这里使用第2种方式:
from sklearn.cross_validation import train_test_split
# 使用sklearn.cross_validation.train_test_split方法,暂取随机数种子为1,以在重复试验时,得到相同的随机数组
train_data, test_data, train_label, test_label = train_test_split(data, label, test_size=0.3, random_state=1)