实战:用激活函数、Keras框架解决分类问题
介绍
本文将介绍如何使用激活函数和Keras框架解决分类问题。分类问题是机器学习中的一种基本问题,它的目标是将输入数据分为不同的类别。本文将以手写数字识别问题为例,介绍如何使用激活函数和Keras框架建立一个分类器,将手写数字分为0-9十个类别。
数据加载
首先,我们需要加载手写数字数据集MNIST。这个数据集包含60000个训练样本和10000个测试样本,每个样本是一个28x28的灰度图像,表示手写数字0-9之一。使用Keras框架,可以轻松地获取MNIST数据集:
from keras.datasets import mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() print('训练集大小:', x_train.shape, y_train.shape) print('测试集大小:', x_test.shape, y_test.shape)
输出结果如下:
训练集大小: (60000, 28, 28) (60000,) 测试集大小: (10000, 28, 28) (10000,)
可以看到,训练集包含60000个样本,测试集包含10000个样本,每个样本是一个28x28的灰度图像。
数据预处理
在训练模型之前,我们需要对数据进行预处理。首先,将图像矩阵转化为一维向量,并将像素值归一化到0-1范围内。这可以通过以下代码实现:
import numpy as np # 将图像矩阵转化为一维向量 x_train = x_train.reshape((60000, 28 * 28)) x_test = x_test.reshape((10000, 28 * 28)) # 将像素值归一化到0-1范围内 x_train = x_train.astype('float32') / 255 x_test = x_test.astype('float32') / 255 # 将类别标签转化为独热编码 from keras.utils import to_categorical y_train = to_categorical(y_train) y_test = to_categorical(y_test) print('训练集大小:', x_train.shape, y_train.shape) print('测试集大小:', x_test.shape, y_test.shape)
这样处理之后,训练集和测试集的大小分别为(60000, 784)
和(10000, 784)
,类别标签也被转化为了独热编码。
模型设计
我们将使用Keras框架建立一个全连接神经网络来解决手写数字分类问题。这个神经网络包含一个输入层、两个隐藏层和一个输出层。其中隐藏层的大小是128,激活函数使用ReLU;输出层的大小是10(对应10个类别),激活函数使用softmax。这个神经网络可以用以下代码实现:
from keras import models from keras import layers model = models.Sequential() model.add(layers.Dense(128, activation='relu', input_shape=(784,))) model.add(layers.Dense(128, activation='relu')) model.add(layers.Dense(10, activation='softmax')) print(model.summary())
这个神经网络的结构如下所示:
Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_1 (Dense) (None, 128) 100480 _________________________________________________________________ dense_2 (Dense) (None, 128) 16512 _________________________________________________________________ dense_3 (Dense) (None, 10) 1290 ================================================================= Total params: 118,282 Trainable params: 118,282 Non-trainable params: 0 _________________________________________________________________
可以看到,输入层的大小是784(对应28x28的图像向量化之后的大小),两个隐藏层的大小都是128,输出层的大小是10(对应10个类别)。
模型编译
在设计好模型之后,我们需要对模型进行编译。编译模型时,需要指定损失函数、优化器和评价指标。对于分类问题,常用的损失函数是交叉熵(categorical_crossentropy),常用的优化器是随机梯度下降(SGD),常用的评价指标是准确率(accuracy)。这可以使用以下代码实现:
model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
模型训练
在编译好模型之后,我们可以用fit
函数训练模型。fit
函数需要指定训练集和测试集的输入和输出,批大小(batch size),训练轮数(epochs)等参数。这可以使用以下代码实现:
history = model.fit(x_train, y_train, batch_size=128, epochs=20, validation_data=(x_test, y_test))
这个模型将在训练集上进行20轮训练,每次随机选取128个样本进行训练。在每轮训练之后,模型将在测试集上进行测试,并记录训练和测试的损失和准确率。
模型评价
训练模型之后,我们可以用以下代码在测试集上评价模型的表现:
test_loss, test_acc = model.evaluate(x_test, y_test) print('测试集损失:', test_loss) print('测试集准确率:', test_acc)
输出结果如下:
测试集损失: 0.10732187752056122 测试集准确率: 0.968600034236908
可以看到,这个模型在测试集上的准确率达到了96.86%。
我们还可以用以下代码绘制训练过程中的训练和测试损失和准确率曲线:
import matplotlib.pyplot as plt history_dict = history.history train_loss = history_dict['loss'] test_loss = history_dict['val_loss'] train_acc = history_dict['accuracy'] test_acc = history_dict['val_accuracy'] epochs = range(1, len(train_loss) + 1) plt.plot(epochs, train_loss, 'bo', label='Training loss') plt.plot(epochs, test_loss, 'b', label='Testing loss') plt.title('Training and testing loss') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.show() plt.plot(epochs, train_acc, 'bo', label='Training accuracy') plt.plot(epochs, test_acc, 'b', label='Testing accuracy') plt.title('Training and testing accuracy') plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.legend() plt.show()
可以看到,随着训练轮数的增加,训练损失逐渐降低,训练准确率逐渐提高。然而,测试损失和测试准确率在训练了一定轮数之后开始出现反弹,这意味着模型已经开始出现过拟合。我们可以使用各种技术来解决过拟合问题,例如添加正则化项、使用dropout等。
总结
本文介绍了如何使用激活函数和Keras框架解决分类问题。我们以手写数字识别问题为例,介绍了如何使用Keras框架建立一个全连接神经网络,将手写数字分为0-9十个类别。我们还介绍了模型的编译、训练和