本节使用数据集为手写识别MNIST数据集,在Alink教程的第13章已经对该数据集进行了详细介绍,而且尝试了几种常用的非深度多分类器,并对分类效果进行了对比,感兴趣的读者可以参阅,这里不再重复。本节的重点是演示如何使用深度神经网络(DNN)和卷积神经网络(CNN)进行图片分类。

数据相关的设置如下,并设置AlinkGlobalConfiguration.setPrintProcessInfo(True),打印输出各组件的运行信息。

  1. Chap13_DATA_DIR = ROOT_DIR + "mnist" + os.sep
  2. Chap13_DENSE_TRAIN_FILE = "dense_train.ak"
  3. Chap13_DENSE_TEST_FILE = "dense_test.ak"
  4. PIPELINE_TF_MODEL = "pipeline_tf_model.ak"
  5. PIPELINE_PYTORCH_MODEL = "pipeline_pytorch_model.ak"
  6. AlinkGlobalConfiguration.setPrintProcessInfo(True)

25.2.1 Softmax算法

在原始训练、测试集中,每个图像数据被存成一个向量,我们可以使用常用的Softmax算法进行多分类,具体代码如下:

  1. def softmax(train_set, test_set) :
  2. Pipeline()\
  3. .add(\
  4. Softmax()\
  5. .setVectorCol("vec")\
  6. .setLabelCol("label")\
  7. .setPredictionCol("pred")\
  8. )\
  9. .fit(train_set)\
  10. .transform(test_set)\
  11. .link(\
  12. EvalMultiClassBatchOp()\
  13. .setLabelCol("label")\
  14. .setPredictionCol("pred")\
  15. .lazyPrintMetrics()\
  16. )
  17. BatchOperator.execute()

如下代码所示,指定训练、预测集,运行。

  1. train_set = AkSourceBatchOp().setFilePath(Chap13_DATA_DIR + Chap13_DENSE_TRAIN_FILE)
  2. test_set = AkSourceBatchOp().setFilePath(Chap13_DATA_DIR + Chap13_DENSE_TEST_FILE)
  3. softmax(train_set, test_set)

输出评估结果如下,我们会将此作为baseline,后面构造深度模型提升效果。

  1. -------------------------------- Metrics: --------------------------------
  2. Accuracy:0.9224 Macro F1:0.9213 Micro F1:0.9224 Kappa:0.9137
  3. |Pred\Real| 9| 8| 7|...| 2| 1| 0|
  4. |---------|---|---|---|---|---|----|---|
  5. | 9|922| 11| 31|...| 4| 0| 0|
  6. | 8| 9|859| 3|...| 37| 10| 2|
  7. | 7| 23| 11|945|...| 8| 1| 3|
  8. | ...|...|...|...|...|...| ...|...|
  9. | 2| 2| 5| 24|...|915| 6| 1|
  10. | 1| 7| 10| 8|...| 10|1112| 0|
  11. | 0| 6| 9| 2|...| 11| 0|954|

25.2.2 使用深度神经网络(DNN)

我们尝试使用深度神经网络构建模型,在输入层和输出层之间添加2个全连接层,分别有256个和128个神经元。网络描述如下:

  1. _________________________________________________________________
  2. Layer (type) Output Shape Param #
  3. =================================================================
  4. tensor (InputLayer) [(None, 784)] 0
  5. _________________________________________________________________
  6. dense (Dense) (None, 256) 200960
  7. _________________________________________________________________
  8. dense_1 (Dense) (None, 128) 32896
  9. _________________________________________________________________
  10. logits (Dense) (None, 10) 1290
  11. =================================================================
  12. Total params: 235,146
  13. Trainable params: 235,146
  14. Non-trainable params: 0
  15. _________________________________________________________________

在Alink中实现该网络很简单,可以在Pipeline中使用Keras 分类器组件(KerasSequentialClassifier),通过setLayers方法,设置深度神经网络;由特征维度数和分类类别数,组件会自动设置输入层(784 bins)和输出层(10 bins)。注意:原始向量中各个分量的取值范围为[0, 255],在使用深度学习模型前,将每个分量除以255,使得每个分量的取值范围变为[0, 1]。

  1. def dnn(train_set, test_set) :
  2. Pipeline()\
  3. .add(
  4. VectorFunction()\
  5. .setSelectedCol("vec")\
  6. .setFuncName("Scale")\
  7. .setWithVariable(1.0 / 255.0)
  8. )\
  9. .add(\
  10. VectorToTensor()\
  11. .setTensorDataType("float")\
  12. .setSelectedCol("vec")\
  13. .setOutputCol("tensor")\
  14. .setReservedCols(["label"])\
  15. )\
  16. .add(\
  17. KerasSequentialClassifier()\
  18. .setTensorCol("tensor")\
  19. .setLabelCol("label")\
  20. .setPredictionCol("pred")\
  21. .setLayers([
  22. "Dense(256, activation='relu')",
  23. "Dense(128, activation='relu')"
  24. ])\
  25. .setNumEpochs(50)\
  26. .setBatchSize(512)\
  27. .setValidationSplit(0.1)\
  28. .setSaveBestOnly(True)\
  29. .setBestMetric("sparse_categorical_accuracy")\
  30. .setNumWorkers(1)\
  31. .setNumPSs(0)\
  32. )\
  33. .fit(train_set)\
  34. .transform(test_set)\
  35. .link(\
  36. EvalMultiClassBatchOp()\
  37. .setLabelCol("label")\
  38. .setPredictionCol("pred")\
  39. .lazyPrintMetrics()\
  40. )
  41. BatchOperator.execute()

如下代码所示,指定训练、预测集,运行。

  1. train_set = AkSourceBatchOp().setFilePath(Chap13_DATA_DIR + Chap13_DENSE_TRAIN_FILE)
  2. test_set = AkSourceBatchOp().setFilePath(Chap13_DATA_DIR + Chap13_DENSE_TEST_FILE)
  3. dnn(train_set, test_set)

计算出模型评估指标如下,相对于Softmax方法有明显提升。

  1. -------------------------------- Metrics: --------------------------------
  2. Accuracy:0.9795 Macro F1:0.9794 Micro F1:0.9795 Kappa:0.9772
  3. |Pred\Real| 9| 8| 7|...| 2| 1| 0|
  4. |---------|---|---|----|---|----|----|---|
  5. | 9|983| 4| 7|...| 0| 0| 1|
  6. | 8| 3|947| 4|...| 6| 3| 2|
  7. | 7| 3| 3|1000|...| 4| 1| 1|
  8. | ...|...|...| ...|...| ...| ...|...|
  9. | 2| 0| 3| 9|...|1010| 3| 0|
  10. | 1| 2| 0| 3|...| 0|1125| 0|
  11. | 0| 1| 4| 2|...| 3| 0|970|

25.2.3 使用卷积神经网络(CNN)

本节侧重卷积神经网络(CNN)的实现,关于CNN的基本概念和理论不展开介绍。这里主要使用2维卷积层和2维最大池化层构建了卷积神经网络,详细网络描述如下:

  1. _________________________________________________________________
  2. Layer (type) Output Shape Param #
  3. =================================================================
  4. tensor (InputLayer) [(None, 28, 28)] 0
  5. _________________________________________________________________
  6. reshape (Reshape) (None, 28, 28, 1) 0
  7. _________________________________________________________________
  8. conv2d (Conv2D) (None, 26, 26, 32) 320
  9. _________________________________________________________________
  10. max_pooling2d (MaxPooling2D) (None, 13, 13, 32) 0
  11. _________________________________________________________________
  12. conv2d_1 (Conv2D) (None, 11, 11, 64) 18496
  13. _________________________________________________________________
  14. max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64) 0
  15. _________________________________________________________________
  16. flatten (Flatten) (None, 1600) 0
  17. _________________________________________________________________
  18. dropout (Dropout) (None, 1600) 0
  19. _________________________________________________________________
  20. logits (Dense) (None, 10) 16010
  21. =================================================================
  22. Total params: 34,826
  23. Trainable params: 34,826
  24. Non-trainable params: 0
  25. _________________________________________________________________

可以在Pipeline中使用Keras 分类器组件(KerasSequentialClassifier),通过setLayers方法,设置卷积神经网络。

  1. def cnn(train_set, test_set) :
  2. Pipeline()\
  3. .add(
  4. VectorFunction()\
  5. .setSelectedCol("vec")\
  6. .setFuncName("Scale")\
  7. .setWithVariable(1.0 / 255.0)
  8. )\
  9. .add(\
  10. VectorToTensor()\
  11. .setTensorDataType("float")\
  12. .setTensorShape([28, 28])\
  13. .setSelectedCol("vec")\
  14. .setOutputCol("tensor")\
  15. .setReservedCols(["label"])\
  16. )\
  17. .add(\
  18. KerasSequentialClassifier()\
  19. .setTensorCol("tensor")\
  20. .setLabelCol("label")\
  21. .setPredictionCol("pred")\
  22. .setLayers([
  23. "Reshape((28, 28, 1))",
  24. "Conv2D(32, kernel_size=(3, 3), activation='relu')",
  25. "MaxPooling2D(pool_size=(2, 2))",
  26. "Conv2D(64, kernel_size=(3, 3), activation='relu')",
  27. "MaxPooling2D(pool_size=(2, 2))",
  28. "Flatten()",
  29. "Dropout(0.5)"
  30. ])\
  31. .setNumEpochs(20)\
  32. .setValidationSplit(0.1)\
  33. .setSaveBestOnly(True)\
  34. .setBestMetric("sparse_categorical_accuracy")\
  35. .setNumWorkers(1)\
  36. .setNumPSs(0)\
  37. )\
  38. .fit(train_set)\
  39. .transform(test_set)\
  40. .link(\
  41. EvalMultiClassBatchOp()\
  42. .setLabelCol("label")\
  43. .setPredictionCol("pred")\
  44. .lazyPrintMetrics()\
  45. )
  46. BatchOperator.execute()

如下代码所示,指定训练、预测集,运行。

  1. train_set = AkSourceBatchOp().setFilePath(Chap13_DATA_DIR + Chap13_DENSE_TRAIN_FILE)
  2. test_set = AkSourceBatchOp().setFilePath(Chap13_DATA_DIR + Chap13_DENSE_TEST_FILE)
  3. cnn(train_set, test_set)

计算出模型评估指标如下,和前面的深度模型相比,效果进一步提升。

  1. -------------------------------- Metrics: --------------------------------
  2. Accuracy:0.9918 Macro F1:0.9918 Micro F1:0.9918 Kappa:0.9909
  3. |Pred\Real| 9| 8| 7|...| 2| 1| 0|
  4. |---------|---|---|----|---|----|----|---|
  5. | 9|995| 2| 1|...| 0| 0| 0|
  6. | 8| 3|965| 1|...| 2| 1| 1|
  7. | 7| 2| 1|1016|...| 3| 0| 1|
  8. | ...|...|...| ...|...| ...| ...|...|
  9. | 2| 0| 1| 6|...|1026| 3| 0|
  10. | 1| 2| 0| 3|...| 0|1131| 1|
  11. | 0| 1| 2| 0|...| 1| 0|977|