在Alink教材第16章,以葡萄酒的品质预测为例,演示了线性模型、随机森林、GBDT等算法的回归训练及预测。本节仍以葡萄酒的品质预测为例,重点演示如何使用深度学习进行回归训练及预测。

数据相关的设置如下,

  1. Chap16_DATA_DIR = ROOT_DIR + "wine" + os.sep
  2. Chap16_TRAIN_FILE = "train.ak";
  3. Chap16_TEST_FILE = "test.ak";
  4. Chap16_FEATURE_COL_NAMES = [
  5. "fixedAcidity", "volatileAcidity", "citricAcid", "residualSugar", "chlorides",
  6. "freeSulfurDioxide", "totalSulfurDioxide", "density", "pH", "sulphates",
  7. "alcohol"
  8. ]

25.3.1 线性回归算法

首先,我们先使用线性回归算法,得到一个baseline,具体代码如下:

  1. def linearReg(train_set, test_set) :
  2. LinearRegression()\
  3. .setFeatureCols(Chap16_FEATURE_COL_NAMES)\
  4. .setLabelCol("quality")\
  5. .setPredictionCol("pred")\
  6. .enableLazyPrintModelInfo()\
  7. .fit(train_set)\
  8. .transform(test_set)\
  9. .lazyPrintStatistics()\
  10. .link(\
  11. EvalRegressionBatchOp()\
  12. .setLabelCol("quality")\
  13. .setPredictionCol("pred")\
  14. .lazyPrintMetrics()\
  15. )
  16. BatchOperator.execute()

其中使用了enableLazyPrintModelInfo方法,会打印出模型的信息,如下所示,“intercept”对应的是线性回归的常数项,每个特征列对应一个线性回归的参数。

  1. ----------------------------- model meta info -----------------------------
  2. {hasInterception: true, model name: Linear Regression, num feature: 11}
  3. ---------------------------- model weight info ----------------------------
  4. | colName[0,9]| intercept|fixedAcidity|volatileAcidity| citricAcid|residualSugar| chlorides|freeSulfurDioxide|totalSulfurDioxide| density| pH|
  5. | weight[0,9]| 147.2227| 0.05561785| -1.88292677|-0.02573757| 0.08013539|-0.32426272| 0.00370713| -0.00037885|-147.10297328|0.64837239|
  6. |colName[10,11]| sulphates| alcohol| | | | | | | | |
  7. | weight[10,11]|0.64099725| 0.19730515|

线性回归预测结果的统计如下,可以看到quality列的均值为5.8735,方差为0.7235;预测结果的均值为5.8767,方差为0.2083。

  1. Summary:
  2. | colName|count|missing| sum| mean| variance| min| max|
  3. |------------------|-----|-------|----------|--------|---------|------|------|
  4. | fixedAcidity| 980| 0| 6722.4| 6.8596| 0.73| 4.7| 10|
  5. | volatileAcidity| 980| 0| 271.38| 0.2769| 0.0099| 0.08| 1.1|
  6. | citricAcid| 980| 0| 327.46| 0.3341| 0.014| 0| 1|
  7. | residualSugar| 980| 0| 6280.75| 6.4089| 26.1442| 0.7| 26.05|
  8. | chlorides| 980| 0| 44.462| 0.0454| 0.0004| 0.012| 0.239|
  9. | freeSulfurDioxide| 980| 0| 34358.5| 35.0597| 286.5621| 2| 138.5|
  10. |totalSulfurDioxide| 980| 0| 135518.5|138.2842|1948.7059| 9| 303|
  11. | density| 980| 0| 974.1799| 0.9941| 0|0.9872| 1.003|
  12. | pH| 980| 0| 3125.47| 3.1893| 0.0219| 2.85| 3.82|
  13. | sulphates| 980| 0| 483.09| 0.4929| 0.0123| 0.27| 0.98|
  14. | alcohol| 980| 0|10289.4933| 10.4995| 1.5211| 8.4| 14.05|
  15. | quality| 980| 0| 5756| 5.8735| 0.7235| 3| 9|
  16. | pred| 980| 0| 5759.1695| 5.8767| 0.2083|4.1547|7.2093|

使用EvalRegressionBatchOp组件,计算显示回归统计指标如下:

  1. -------------------------------- Metrics: --------------------------------
  2. MSE:0.5309 RMSE:0.7286 MAE:0.5748 MAPE:10.0995 R2:0.2655

25.3.2 深度回归算法

使用深度回归模型的代码如下:

  1. def dnnReg(train_set, test_set) :
  2. Pipeline()\
  3. .add(\
  4. StandardScaler()\
  5. .setSelectedCols(Chap16_FEATURE_COL_NAMES)\
  6. )\
  7. .add(\
  8. VectorAssembler()\
  9. .setSelectedCols(Chap16_FEATURE_COL_NAMES)\
  10. .setOutputCol("vec")\
  11. )\
  12. .add(\
  13. VectorToTensor()\
  14. .setSelectedCol("vec")\
  15. .setOutputCol("tensor")\
  16. .setReservedCols(["quality"])\
  17. )\
  18. .add(\
  19. KerasSequentialRegressor()\
  20. .setTensorCol("tensor")\
  21. .setLabelCol("quality")\
  22. .setPredictionCol("pred")\
  23. .setLayers([
  24. "Dense(64, activation='relu')",
  25. "Dense(64, activation='relu')",
  26. "Dense(64, activation='relu')",
  27. "Dense(64, activation='relu')",
  28. "Dense(64, activation='relu')"
  29. ])\
  30. .setNumEpochs(20)\
  31. .setNumWorkers(1)\
  32. .setNumPSs(0)\
  33. )\
  34. .fit(train_set)\
  35. .transform(test_set)\
  36. .lazyPrintStatistics()\
  37. .link(\
  38. EvalRegressionBatchOp()\
  39. .setLabelCol("quality")\
  40. .setPredictionCol("pred")\
  41. .lazyPrintMetrics()\
  42. )
  43. BatchOperator.execute()

在Pipeline中使用了多个组件:
1、数据标准化组件StandardScaler,因为数据中各列的数值范围差异较大,标准化后,有助于提升深度模型的效果
2、拼接向量组件VectorAssembler,将多列数值数据转化为一列向量数据。
3、向量转化为张量的组件VectorToTensor,后面的Keras组件的输入格式为张量
4、Keras回归器组件KerasSequentialRegressor,定义了深度模型

Pipeline使用fit方法对训练集train_set进行训练,然后使用transform方法对测试集test_set进行预测。如下代码所示,指定训练、预测集,运行。

  1. train_set = AkSourceBatchOp().setFilePath(Chap16_DATA_DIR + Chap16_TRAIN_FILE)
  2. test_set = AkSourceBatchOp().setFilePath(Chap16_DATA_DIR + Chap16_TEST_FILE)
  3. dnnReg(train_set, test_set)

预测结果的统计如下

  1. Summary:
  2. |colName|count|missing| sum| mean|variance| min| max|
  3. |-------|-----|-------|---------|------|--------|------|------|
  4. |quality| 980| 0| 5756|5.8735| 0.7235| 3| 9|
  5. | tensor| 980| 0| NaN| NaN| NaN| NaN| NaN|
  6. | pred| 980| 0|5766.3137| 5.884| 0.3881|3.8637|7.5729|

相应的评估指标如下,可以看到均方误差MSE和平均绝对误差MAE等指标,相对线性回归算法有明显改进。

  1. -------------------------------- Metrics: --------------------------------
  2. MSE:0.485 RMSE:0.6964 MAE:0.5323 MAPE:9.3756 R2:0.3289