使用vb.NET和SDCA Trainer解决ML.NET问题

使用vb.NET和SDCA Trainer解决ML.NET问题,vb.net,ml.net,Vb.net,Ml.net,我正试图开发一个简单的成本预测引擎,以便根据几何信息和我们的历史数据猜测钢氧切零件的价格。这个工具是一个更大的应用程序的一部分,这个应用程序是用vb.net编写的,所以我不得不使用这种语言 关于ML.NET的所有信息都是基于C#的,而且,据我猜测,vb.NET的实现并不完全相同,因此适应这种语言正在成为一场噩梦。似乎vb.net flavor甚至跳过了一些培训师,缺少一些功能,支持也较少 首先,作为一个数值回归问题,我认为SDCA培训师是最好的选择,所以这就是我的方法。我已经向系统提供了一些“虚

我正试图开发一个简单的成本预测引擎,以便根据几何信息和我们的历史数据猜测钢氧切零件的价格。这个工具是一个更大的应用程序的一部分,这个应用程序是用vb.net编写的,所以我不得不使用这种语言

关于ML.NET的所有信息都是基于C#的,而且,据我猜测,vb.NET的实现并不完全相同,因此适应这种语言正在成为一场噩梦。似乎vb.net flavor甚至跳过了一些培训师,缺少一些功能,支持也较少

首先,作为一个数值回归问题,我认为SDCA培训师是最好的选择,所以这就是我的方法。我已经向系统提供了一些“虚构”的数据,使用Excel根据1000个部件的随机输入生成了一个“逻辑”成本(几乎是线性的!)。我认为任何回归预测系统都应该非常准确地管理这些测试数据。至少比预期的真实数据更精细

这是我的简化代码,它从.csv文件构建和训练模型,并使用4个输入进行测试:

    Public Class CShapeCostPrediction

    Public Class CShapeInput
        <ColumnName("AgeFrom1990"), LoadColumn(0)>
        Public Property AgeFrom1990 As Single

        <ColumnName("Area"), LoadColumn(1)>
        Public Property Area As Single

        <ColumnName("RectangularArea"), LoadColumn(2)>
        Public Property RectangularArea As Single

        <ColumnName("Thickness"), LoadColumn(3)>
        Public Property Thickness As Single

        <ColumnName("Perimeter"), LoadColumn(4)>
        Public Property Perimeter As Single

        <ColumnName("Cuts"), LoadColumn(5)>
        Public Property Cuts As Single

        <ColumnName("Cost"), LoadColumn(6)>
        Public Property CostReal As Single

        Public Sub New()
        End Sub

        'For testing
        Public Sub New(sAge As Single, sArea As Single, sRectArea As Single, sThick As Single, sPerim As Single, sCuts As Single)
            AgeFrom1990 = sAge
            Area = sArea
            RectangularArea = sRectArea
            Thickness = sThick
            Perimeter = sPerim
            Cuts = sCuts
        End Sub

    End Class

    Public Class CShapeOutput
        Public Property Score As Single
    End Class

    'Shared members
    Public Shared Context As MLContext
    Public Shared PredictionEngine As PredictionEngine(Of CShapeInput, CShapeOutput)

    'Main simplified testing workflow
    Public Shared Function Testing() As Boolean
        Context = New MLContext()

        Dim oTrainingDataView As IDataView = Context.Data.LoadFromTextFile(Of CShapeInput)(path:="D:\ShapeInfo.csv",
                                                                                    hasHeader:=True,
                                                                                    separatorChar:=CChar(";"),
                                                                                    allowQuoting:=True, allowSparse:=False)

        'Normalization. Reportedly required for SDCA trainer
        Dim oNormalize As EstimatorChain(Of Transforms.NormalizingTransformer) = Context.Transforms.NormalizeMeanVariance("AgeFrom1990").
                                                                                    Append(Context.Transforms.NormalizeMeanVariance("Area")).
                                                                                    Append(Context.Transforms.NormalizeMeanVariance("RectangularArea")).
                                                                                    Append(Context.Transforms.NormalizeMeanVariance("Thickness")).
                                                                                    Append(Context.Transforms.NormalizeMeanVariance("Perimeter")).
                                                                                    Append(Context.Transforms.NormalizeMeanVariance("Cuts"))
        'Concatenate to features
        Dim oConcatenate As EstimatorChain(Of ColumnConcatenatingTransformer) = oNormalize.Append(Context.Transforms.Concatenate("Features", "AgeFrom1990", "Area", "RectangularArea", "Thickness", "Perimeter", "Cuts"))

        'Trainer to predict a label from a feature
        Dim oTrainer As Trainers.SdcaRegressionTrainer = Context.Regression.Trainers.Sdca(labelColumnName:="Cost", featureColumnName:="Features")

        Dim oTrainingPipeline As IEstimator(Of ITransformer) = oConcatenate.Append(oTrainer)

        Dim oTrainedModel As ITransformer = oTrainingPipeline.Fit(oTrainingDataView)   'Too fast!?

        Dim oCrossValidationResults As IEnumerable(Of TrainCatalogBase.CrossValidationResult(Of RegressionMetrics)) = Context.Regression.CrossValidate(oTrainingDataView, oTrainingPipeline, numberOfFolds:=5, labelColumnName:="Cost")

        'Get some metrics and show them
        Dim dRSQuared As Double = 0.0
        Dim dRootMeanSquaredError As Double = 0.0
        For Each oCVResult As TrainCatalogBase.CrossValidationResult(Of RegressionMetrics) In oCrossValidationResults
            dRSQuared += oCVResult.Metrics.RSquared
            dRootMeanSquaredError += oCVResult.Metrics.RootMeanSquaredError
        Next
        Dim dCount As Double = CDbl(oCrossValidationResults.LongCount)
        dRSQuared /= dCount
        dRootMeanSquaredError /= dCount
        MessageBox.Show(String.Format("R-Squared: {0:0.000}" & Environment.NewLine() & "Root Mean Squared Error (RMSE): {1:0.000}", dRSQuared, dRootMeanSquaredError))

        'Model saving for later use
        If IO.File.Exists("D:\ShapeModel.zip") Then
            IO.File.Delete("D:\ShapeModel.zip")
        End If
        Context.Model.Save(oTrainedModel, oTrainingDataView.Schema, "D:\ShapeModel.zip")

        'Build prediction engine
        PredictionEngine = Context.Model.CreatePredictionEngine(Of CShapeInput, CShapeOutput)(oTrainedModel)

        'Some testing using some of the same values in the feeding data
        Dim oTestInputs As New List(Of CShapeInput)
        oTestInputs.Add(New CShapeInput(26, 0.553079716, 1.624771712, 47, 4.905492266, 3))     'Cost = 193.42
        oTestInputs.Add(New CShapeInput(40, 0.006435867, 0.018295898, 12, 0.495820115, 4))     'Cost = 0.60
        oTestInputs.Add(New CShapeInput(26, 0.948809904, 3.598203278, 96, 7.049619315, 8))     'Cost = 703.96
        oTestInputs.Add(New CShapeInput(5, 0.814014957, 1.391183561, 10, 3.985410019, 3))     'Cost = 56.71

        'Predict
        Dim oTestOutputs As New List(Of CShapeOutput)
        oTestOutputs.Add(PredictionEngine.Predict(oTestInputs(0)))
        oTestOutputs.Add(PredictionEngine.Predict(oTestInputs(1)))
        oTestOutputs.Add(PredictionEngine.Predict(oTestInputs(2)))
        oTestOutputs.Add(PredictionEngine.Predict(oTestInputs(3)))

        MessageBox.Show(String.Format("Cost 1: {0:0.000}" & Environment.NewLine() & "Cost 2: {1:0.000}" & Environment.NewLine() & "Cost 3: {2:0.000}" & Environment.NewLine() & "Cost 4: {3:0.000}", oTestOutputs(0).Score, oTestOutputs(1).Score, oTestOutputs(2).Score, oTestOutputs(3).Score))

        Return True
    End Function
End Class
获得的指标包括: RSquared:0.857 RMSE:63.41

然而,预测结果远远不正确(预期/获得):

测试1:193.4/192.8(在.csv文件中的第一行,可以正常工作)

测试2:0.6/-156.7(阴性!)

测试3:555.9/703.9

测试4:56.7/128.5

唯一准确预测的结果是.csv文件的第一行,因此我不确定是否没有读取整个信息

此外,拟合过程非常快,保持大约1-2秒,因为度量评估过程比较长。这有点奇怪,因为我认为拟合1000个输入需要一些处理。我可以避免交叉验证步骤获得相同的预测结果,因此它似乎根本不是强制性的

老实说,我对这一切的了解都很原始,我的代码是从C#中不同来源复制和改编不同代码片段的结果,因此我确信这远远不能被接受

例如,我对规范化和列连接的方式没有信心,在不同的返回数据类型上附加不同的结果。关于此工作流的所有信息都在C#上编码,以更直接的方式跳过数据类型

如果您能提供任何信息,我将不胜感激,因为我还没有找到任何相关信息


提前非常感谢!

有点离题,但你是否无法将所有处理放入c#库并从vb.net调用它?我们有许多混合语言的解决方案,没有问题。谢谢你的建议。是的,我知道这种方法。事实上,我甚至在考虑用Python/Tensorflow和从我的主要vb.net应用程序调用,但这会让事情变得有点复杂,如果我的目标是得到一个合理的近似值,而不是开发一个健壮的系统。不幸的是,这些编码任务只是我日程中的一小部分,不专注于编程。这就是为什么我试图让整个事情变得简单和可维护。你试过CLI或Model Builder?这至少可以帮助您找到一个可能工作得最好的模型。我尝试了Model Builder,我的部分代码来自于此。但Model Builder似乎无法在vb.net上工作,而只能在C#上工作。翻译并不简单,因为两种语言的功能不相同。事实上,Model Builder中采用的培训师似乎没有o存在于vb.net上,因此我不得不转向SDCA。如你所见,我的方法是可耻的,对我在所有步骤中所做的事情没有确切的了解。有点离题,但你无法将所有处理放入c#库并从vb.net调用它吗?我们有许多混合语言的解决方案,没有问题。谢谢你的建议。是的,我知道这种方法。事实上,我甚至想过用Python/Tensorflow编写这个功能,并从我的主要vb.net应用程序调用它,但这让事情变得有点复杂,如果我的目标是得到一个合适的近似值,而不是开发一个健壮的系统。不幸的是,这些编码任务只是我日程中的一个狭窄部分,而不是专注于编程。这就是为什么我试图让整个事情变得简单和可维护。你试过CLI或Model Builder吗?这至少可以帮助你找到一个可能工作得最好的模型。我试过Model Builder,我的部分代码就是从那里来的。但是Model Builder似乎在vb.net上不起作用,只是在C#上。翻译并不简单,因为两种语言的功能并不相同。事实上,Model Builder中采用的培训师似乎不存在于vb.net中,因此我不得不转向SDCA。正如您所看到的,我的方法是可耻的,我对所有步骤都不了解。
AgeFrom1990;Area;RectangularArea;Thickness;Perimeter;Cuts;Cost
26.000;0.553;1.625;47.000;4.905;3.000;193.425
23.000;0.198;0.351;33.000;3.520;7.000;48.176
5.000;0.740;2.981;55.000;4.727;6.000;310.574
39.000;0.110;0.182;41.000;1.263;4.000;32.389
40.000;0.111;0.557;27.000;1.890;1.000;23.167
15.000;0.635;0.826;51.000;3.589;1.000;218.191
18.000;0.763;0.994;89.000;5.638;9.000;482.146
36.000;0.095;0.143;87.000;1.455;7.000;60.164
15.000;0.942;1.404;50.000;4.037;1.000;319.190
34.000;0.124;0.189;17.000;2.205;6.000;15.295
35.000;0.679;3.285;63.000;6.535;5.000;335.729
18.000;0.240;1.060;17.000;2.123;3.000;31.298