学生成绩预测案例
本案例的数据来源为加州大学尔湾分校的机器学习公开样本数据集,数据介绍页面和下载地址为: https://archive.ics.uci.edu/ml/datasets/Student+Performance。该数据集包含了来自两所学校的学生的问卷调查结果,以及每位学生的综合成绩。数据集为CSV格式,每个字段的含义在官网上都有详细介绍,因此,在这里就不再赘述了。确定问题类型
我们的任务很简单,就是基于这套已有的学生问卷调查结果以及综合成绩,进行机器学习模型训练,然后,再根据一套给定的学生情况信息,来预测该名学生的综合成绩。不难发现,我们需要使用监督学习中的回归算法来进行模型训练,因为我们需要得到一个连续的预测值,而不是离散的二元或者多元值。在确定了我们的任务之后,就可以对得到的数据集进行一些预处理,以便机器学习的过程能够顺利进行。数据预处理与数据分析
在得到训练数据集之后,通常不能直接拿来进行机器学习,需要对数据进行一些处理。数据预处理任务大致有:- 数据格式规整化:对每一列的数据进行类型和单位统一,比如,“浓度”字段有些行使用的是ug/mL,有些行使用的是g/L,需要对单位进行统一,并将“浓度”字段的值转换为数值类型,以便进行统计
- 特殊值处理:有些样本数据的取值比较异常,超出正常范围很多,对于这样的数据,可以直接丢弃,也可以通过一些统计学算法对其进行修正
- 空值、无效值处理:有些样本数据的取值为空(或者对于数值型的数据,取值为0,并且不合理),对于这样的数据,也需要进行修正或者舍弃
- 数据一致性校验:对数据一致性进行校验
- 识别特征属性与目标属性:分析训练数据中,哪些属性会对预测目标造成影响,哪些属性不会影响预测结果
基于ML.NET的模型训练
注:本案例代码已开源。地址是: https://github.com/daxnet/mlnet-trainer。 通过上面的分析不难得出,我们的应用场景属于监督学习中的回归(Regression)预测,因此,我们可以选择使用ML.NET中所提供的回归算法,使用样本数据逐一完成模型训练,然后,使用测试数据对每个模型的预测结果进行评估,以选择合适的预测算法。为了对所有ML.NET默认支持的回归算法进行预测评估,在程序中使用如下数据结构来保存这些算法的实例,以便之后进行模型训练的时候,可以逐一对这些算法进行训练和评估:
1
2
3
4
5
6
7
8
9
10
|
var
trainers =
new
List {
mlContext.Regression.Trainers.FastTree(),
mlContext.Regression.Trainers.FastForest(),
mlContext.Regression.Trainers.FastTreeTweedie(),
mlContext.Regression.Trainers.GeneralizedAdditiveModels(),
mlContext.Regression.Trainers.OnlineGradientDescent(),
mlContext.Regression.Trainers.PoissonRegression(),
mlContext.Regression.Trainers.StochasticDualCoordinateAscent()
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
public
IEnumerable {
var
metrics =
new
Dictionary<
string
, RegressionMetrics>();
foreach
(
var
trainer
in
this
.trainers)
{
var
pipeline = mlContext.Transforms.CopyColumns(inputColumnName:
"G3"
, outputColumnName:
"Label"
)
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"School"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Sex"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Age"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Famsize"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Guardian"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Traveltime"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Studytime"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Failures"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Paid"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Higher"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Famrel"
))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(
"Absences"
))
.Append(mlContext.Transforms.Concatenate(
"Features"
,
"School"
,
"Sex"
,
"Age"
,
"Famsize"
,
"Guardian"
,
"Traveltime"
,
"Studytime"
,
"Failures"
,
"Paid"
,
"Higher"
,
"Famrel"
,
"Absences"
))
.AppendCacheCheckpoint(mlContext)
.Append(trainer);
var
trainedModel = pipeline.Fit(trainingDataView);
trainedModels.Add(trainer.GetType().Name, trainedModel);
var
predictionModel = trainedModel.Transform(testDataView);
var
regMetrics = mlContext.Regression.Evaluate(predictionModel);
metrics.Add(trainer.GetType().Name, regMetrics);
}
return
metrics;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// 基于训练数据集进行训练,并基于测试数据集进行评估,然后输出评估结果
var
regressionMetrics = session.TrainAndEvaluate(trainingDataView, testingDataView);
foreach
(
var
item
in
regressionMetrics)
{
LearningSession.OutputRegressionMetrics(item.Key, item.Value);
}
// 找到RMS最小的算法,作为最优算法
var
winnerAlgorithmName = regressionMetrics.OrderBy(x => x.Value.Rms).First().Key;
Console.WriteLine($
"最优算法为:{winnerAlgorithmName}"
);
Console.WriteLine();
var
winnerModel = session.GetTrainedModel(winnerAlgorithmName);
using
(
var
fileStream =
new
FileStream(ModelFileName, FileMode.Create, FileAccess.Write))
{
mlContext.Model.Save(winnerModel, fileStream);
}
|