Skip to content

Commit d956d94

Browse files
mariuszwojcikCESARDELATORRE
authored andcommitted
#FS230: move F# BikeSharingDemand example to use direct ML.NET API. (dotnet#231)
* dotnet#202: migrate BikeSharingDemand F# sample to v0.9 * migrate Sentiment Analysis F# sample to v0.9 * dotnet#213: append CacheCheckpoint in F# samples to mitigate ML.NET bug #2099 * #FS230: move F# BikeSharingDemand example to use direct ML.NET API.
1 parent 7d51a58 commit d956d94

File tree

3 files changed

+46
-44
lines changed

3 files changed

+46
-44
lines changed

samples/fsharp/getting-started/Regression_BikeSharingDemand/BikeSharingDemand/BikeSharingDemandConsoleApp/BikeSharingDemand.fsproj

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
<ItemGroup>
99
<Compile Include="DataStructures\DataStructures.fs" />
1010
<Compile Include="..\..\..\..\common_v0.9\ConsoleHelper.fs" Link="Common\ConsoleHelper.fs" />
11-
<Compile Include="..\..\..\..\common_v0.9\ModelBuilder.fs" Link="Common\ModelBuilder.fs" />
12-
<Compile Include="..\..\..\..\common_v0.9\ModelScorer.fs" Link="Common\ModelScorer.fs" />
13-
<Compile Include="..\..\..\..\common_v0.9\Pipeline.fs" Link="Common\Pipeline.fs" />
1411
</ItemGroup>
1512

1613
<ItemGroup>

samples/fsharp/getting-started/Regression_BikeSharingDemand/BikeSharingDemand/BikeSharingDemandConsoleApp/ModelScoringTester.fs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
open System
44
open System.IO
55
open DataStructures
6+
open Microsoft.ML
67

78
let readSampleDataFromCsvFile dataLocation numberOfRecordsToRead =
89
File.ReadLines(dataLocation)
@@ -28,17 +29,13 @@ let readSampleDataFromCsvFile dataLocation numberOfRecordsToRead =
2829
|> Seq.toList
2930

3031

31-
let visualizeSomePredictions testDataLocation modelScorer numberOfPredictions =
32-
32+
let visualizeSomePredictions testDataLocation (predEngine : PredictionEngine<DemandObservation, DemandPrediction>) numberOfPredictions =
3333
//Make a few prediction tests
3434
// Make the provided number of predictions and compare with observed data from the test dataset
35-
let testData = readSampleDataFromCsvFile testDataLocation numberOfPredictions
36-
37-
for i = 0 to numberOfPredictions-1 do
3835

39-
let prediction =
40-
modelScorer
41-
|> Common.ModelScorer.predictSingle testData.[i]
42-
43-
Common.ConsoleHelper.printRegressionPredictionVersusObserved (float prediction.PredictedCount) (testData.[i].Count.ToString())
36+
let testData = readSampleDataFromCsvFile testDataLocation numberOfPredictions
37+
for i in 0 .. (numberOfPredictions - 1) do
38+
//Score
39+
let resultprediction = predEngine.Predict testData.[i]
40+
Common.ConsoleHelper.printRegressionPredictionVersusObserved (float resultprediction.PredictedCount) (testData.[i].Count.ToString())
4441

samples/fsharp/getting-started/Regression_BikeSharingDemand/BikeSharingDemand/BikeSharingDemandConsoleApp/Program.fs

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ open System
44
open Microsoft.ML
55
open Microsoft.ML.Core.Data
66
open Microsoft.ML.Data
7+
open System.IO
8+
open DataStructures
79

810
let modelsLocation = @"../../../../MLModels"
911

@@ -16,6 +18,12 @@ let testDataLocation = sprintf @"%s/hour_test.csv" datasetsLocation
1618
let read (dataPath : string) (dataLoader : TextLoader) =
1719
dataLoader.Read dataPath
1820

21+
/// Cast ML.NET pipeline object to IEstimator<ITransformer> interface
22+
let downcastPipeline (pipeline : IEstimator<'a>) =
23+
match pipeline with
24+
| :? IEstimator<ITransformer> as p -> p
25+
| _ -> failwith "The pipeline has to be an instance of IEstimator<ITransformer>."
26+
1927

2028
[<EntryPoint>]
2129
let main argv =
@@ -53,14 +61,13 @@ let main argv =
5361

5462
// 2: Common data process configuration with pipeline data transformations
5563
let dataProcessPipeline =
56-
mlContext.Transforms.CopyColumns("Count", "Label")
57-
|> Common.ModelBuilder.append(
58-
mlContext.Transforms.Concatenate("Features", "Season", "Year", "Month",
59-
"Hour", "Holiday", "Weekday",
60-
"Weather", "Temperature", "NormalizedTemperature",
61-
"Humidity", "Windspeed"))
62-
|> Common.ModelBuilder.appendCacheCheckpoint mlContext
63-
|> Common.ConsoleHelper.downcastPipeline
64+
(mlContext.Transforms.CopyColumns("Count", "Label") |> downcastPipeline)
65+
.Append(mlContext.Transforms.Concatenate("Features", "Season", "Year", "Month",
66+
"Hour", "Holiday", "Weekday",
67+
"Weather", "Temperature", "NormalizedTemperature",
68+
"Humidity", "Windspeed"))
69+
.AppendCacheCheckpoint(mlContext)
70+
|> downcastPipeline
6471

6572
// (Optional) Peek data in training DataView after applying the ProcessPipeline's transformations
6673
Common.ConsoleHelper.peekDataViewInConsole<DataStructures.DemandObservation> mlContext trainingDataView dataProcessPipeline 10 |> ignore
@@ -69,10 +76,10 @@ let main argv =
6976
// Definition of regression trainers/algorithms to use
7077
let regressionLearners : (string * IEstimator<ITransformer>) array =
7178
[|
72-
"FastTree", mlContext.Regression.Trainers.FastTree() |> Common.ConsoleHelper.downcastPipeline
73-
"Poisson", mlContext.Regression.Trainers.PoissonRegression() |> Common.ConsoleHelper.downcastPipeline
74-
"SDCA", mlContext.Regression.Trainers.StochasticDualCoordinateAscent() |> Common.ConsoleHelper.downcastPipeline
75-
"FastTreeTweedie", mlContext.Regression.Trainers.FastTreeTweedie() |> Common.ConsoleHelper.downcastPipeline
79+
"FastTree", mlContext.Regression.Trainers.FastTree() |> downcastPipeline
80+
"Poisson", mlContext.Regression.Trainers.PoissonRegression() |> downcastPipeline
81+
"SDCA", mlContext.Regression.Trainers.StochasticDualCoordinateAscent() |> downcastPipeline
82+
"FastTreeTweedie", mlContext.Regression.Trainers.FastTreeTweedie() |> downcastPipeline
7683
//Other possible learners that could be included
7784
//...FastForestRegressor...
7885
//...GeneralizedAdditiveModelRegressor...
@@ -83,38 +90,39 @@ let main argv =
8390
// Per each regression trainer: Train, Evaluate, and Save a different model
8491
for (learnerName, trainer) in regressionLearners do
8592
printfn "================== Training the current model =================="
86-
let modelBuilder =
87-
Common.ModelBuilder.create mlContext dataProcessPipeline
88-
|> Common.ModelBuilder.addTrainer trainer
89-
90-
let trainedModel =
91-
modelBuilder
92-
|> Common.ModelBuilder.train trainingDataView
93-
93+
let trainingPipeline = dataProcessPipeline.Append(trainer)
94+
let trainedModel = trainingPipeline.Fit(trainingDataView)
95+
9496
printfn "===== Evaluating Model's accuracy with Test data ====="
95-
let metrics =
96-
(trainedModel, modelBuilder)
97-
|> Common.ModelBuilder.evaluateRegressionModel testDataView "Count" "Score"
98-
97+
let predictions = trainedModel.Transform(testDataView)
98+
let metrics = mlContext.Regression.Evaluate(predictions, label = "Count", score = "Score")
9999
Common.ConsoleHelper.printRegressionMetrics learnerName metrics
100+
101+
100102

101103
//Save the model file that can be used by any application
102-
(trainedModel, modelBuilder)
103-
|> Common.ModelBuilder.saveModelAsFile (sprintf @"%s/%sModel.zip" modelsLocation learnerName)
104+
let modelPath = sprintf "%s/%sModel.zip" modelsLocation learnerName
105+
use fs = new FileStream(modelPath, FileMode.Create, FileAccess.Write, FileShare.Write)
106+
mlContext.Model.Save(trainedModel, fs);
107+
108+
printfn "The model is saved to %s" modelPath
104109

105110
// 4. Try/test Predictions with the created models
106111
// The following test predictions could be implemented/deployed in a different application (production apps)
107112
// that's why it is seggregated from the previous loop
108113
// For each trained model, test 10 predictions
109114
for (learnerName, _) in regressionLearners do
110-
//Load current model
111-
let modelScorer =
112-
Common.ModelScorer.create mlContext
113-
|> Common.ModelScorer.loadModelFromZipFile (sprintf @"%s/%sModel.zip" modelsLocation learnerName)
115+
//Load current model from .ZIP file
116+
let modelPath = sprintf "%s/%sModel.zip" modelsLocation learnerName
117+
use stream = new FileStream(modelPath, FileMode.Open, FileAccess.Read, FileShare.Read)
118+
let trainedModel = mlContext.Model.Load stream
114119

120+
// Create prediction engine related to the loaded trained model
121+
let predEngine = trainedModel.CreatePredictionEngine<DemandObservation, DemandPrediction>(mlContext)
115122
printfn "================== Visualize/test 10 predictions for model %sModel.zip ==================" learnerName
123+
116124
//Visualize 10 tests comparing prediction with actual/observed values from the test dataset
117-
ModelScoringTester.visualizeSomePredictions testDataLocation modelScorer 10
125+
ModelScoringTester.visualizeSomePredictions testDataLocation predEngine 10
118126

119127
Common.ConsoleHelper.consolePressAnyKey ()
120128

0 commit comments

Comments
 (0)