Время прочтения: 3 мин.

Учитывая, насколько популярен язык Python, особенно среди новичков в области Data Science, он вполне может стать примером этого антипаттерна. В связи с этим, в данной статье рассмотрим решение задачи машинного обучения с использованием языка F#.

В связи с относительно низким порогом вхождения одним из популярных инструментов для реализации методов машинного обучения является язык Python с различными библиотеками (pandas, sklearn, numpy и т.п.) Но популярный метод — не всегда лучший, поэтому в этой статье познакомимся с такой альтернативой, как язык F# и библиотека ML.NET.

В качестве примера возьмём данные по опыту работы (в годах) и соответствующему уровню заработной платы и попробуем предсказать уровень заработной платы на основе тренировочных данных. Для загрузки файлов необходимо написать класс (тип):

open System
open Microsoft.ML
open Microsoft.ML.Data

let trainFile = "./ZPTrain.csv"
let testFile = "./ZPTest.csv"

type ZPData = {
  [<LoadColumn(0)>]
  StageRab: float32;

  [<LoadColumn(1)>]
  ZP: float32;
}

В приведённом выше коде определены два столбца для загрузки данных о стаже работы и уровне заработной платы, а также указаны физические пути к файлам. Далее также нужно создать подобный класс для выходных результатов прогнозирования.

[<CLIMutable>]
type ZPPrediction = {
  [<ColumnName("Score")>]
  PredictedZP: float32;
}

В главной функции программы (Main) определяется функция загрузки файлов в переменные и затем производится непосредственная загрузка:

[<EntryPoint>]
let main argv =
    let context = MLContext()

    let loadDataByPath path =
      context.Data.LoadFromTextFile<ZPData>(path, hasHeader=true, separatorChar=',')

    let trainData = loadDataByPath trainFile
    let testData = loadDataByPath testFile

После этого необходимо создать векторы путём конкатенации признаков и выбрать модель для предсказания. В данном случае используется регрессия Пуассона.

    let pipeline = 
      EstimatorChain()
        .Append(context.Transforms.Concatenate("Features", "StageRab"))
        .Append(context.Transforms.CopyColumns(("Label", "ZP")))
        .Append(context.Regression.Trainers.LbfgsPoissonRegression())

Далее, когда все признаки определены и выбрана модель, проводим обучение модели и оценку модели. В качестве метрик используем RMSE и коэффициент детерминации (R2).

let model = pipeline.Fit trainData

    let predictions = model.Transform testData
    let metrics = context.Regression.Evaluate(predictions, "Label", "Score")
    printfn "RMS - %.2f" metrics.RootMeanSquaredError
    printfn "R^2 - %.2f" metrics.RSquared

    let predictionFunc = context.Model.CreatePredictionEngine<ZPData, ZPPrediction >(model)

После того, как модель обучена можно использовать её для предсказания уровня заработной платы по определенному стажу, например, 7 лет и вывести результаты в консоль (Рис. 1):

    let ZPPrediction = { 
      StageRab = 7.0f 
      ZP = 0.0f
    }
    let prediction = predictionFunc.Predict(ZPPrediction)

    printfn "Prediction - %.2f" prediction. PredictedZP
Рис. 1 Результат выполнения программы обучения

Учитывая количество строк кода и простоту его написания, можно сделать вывод, что язык F# является достаточно неплохой альтернативой для Python и, вероятнее всего, будет более подходящим для ряда задач по анализу данных. Также одним из преимуществ этого языка является его парадигма – функциональное программирование, в том числе с поддержкой объектно-ориентированного программирования, что даёт больше возможностей программистам реализовывать разнообразные проекты и решения.