MLLinearRegression и Bitcoin с помощью Swift

(Контекст) Компания по покупке и торговле криптовалютами Bitso запустила 15 января 2022 года конкурс, в котором нужно угадать цену биткоина на 7 марта того же года, и тот, кто угадает правильно или окажется ближе всего к цене, выиграет не больше и не меньше биткоина.

Чтобы не дать себе увлечься интуицией и, даже зная, что очень трудно или невозможно, в зависимости от того, кого вы спросите, угадать цену биткойна через месяц, я решил применить фреймворк Apple под названием CreateML для разработки модели машинного обучения, чтобы помочь мне, по крайней мере, иметь смутное представление о цене, которую он может иметь, и как повод использовать Swift в Machine Learning.

Хотя Python — очень хороший и полезный язык, правда в том, что Swift, как мне кажется, имеет большой потенциал, который довольно сильно растрачен, я думаю, что известность как «языка разработки приложений Apple» не помогает ему в других областях, как вы, возможно, знаете, с некоторых пор он имеет открытый исходный код и совместим с Windows и Linux, у него также есть бэкенд-фреймворк под названием Vapor, который довольно быстрый, асинхронный, простой в использовании, и из-за его игровой площадки очень легко начать тестирование и игру с кодом, как мы увидим ниже.

Swift также был частью исследований Google по его использованию в Machine Learning, поскольку они интегрировали его с Google Colab и TensorFlow, но я не решаюсь много говорить об этом, поскольку не тестировал его на этой платформе, но это дает доказательства его использования в области Data Science, Некоторые из его преимуществ заключаются в том, что он быстр, отлично управляет памятью, сильно типизирован, прост в изучении, может использоваться в качестве бэкенда, использует fluent как язык шаблонов в html, может использоваться для консоли, мобильных и настольных компьютеров, очень безопасен, поддерживается Apple, подметает, шваброй и моет посуду; талант есть, просто нужно его поддерживать хаха.

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

Этот видеоролик об исследовании и манипулировании данными очень помог мне понять, что я делаю. И, конечно, сайт hackingswift, который направил меня и дал мне идею.

Я загрузил данные с сайта Nasdaq, файл CSV с датами и ценами закрытия, которые я использовал для линейной регрессии.

В любом случае, без лишних разговоров, вот код, все сделано в Xcode Playground, который, если честно, если я заметил одну или две ошибки, или это из-за того, что мой MacBook 2015 года с intel, как у воина-викинга, а не m2, как сейчас, кажется, вызвал беспокойство, внезапно он не показывал мне результаты или как будто застрял, не застряв, странные вещи, но на самом деле редко (или не так мало).


// Primero importamos las librerías que utilizaremos
import CreateML
import TabularData
import Foundation
// -------------------------------------------------

// Instanciamos CSVReadingOptions, lo usaremos para convertir la fecha de String a Date.
var options = CSVReadingOptions()
// --------------------------------------------------

// Creamos la estrategía para convertir la fecha de String a Date, dependiendo el formato-
// en el que se encuentre en el archivo CSV, en mi caso era MM/DD/YYYY. 01/31/2022.
options.addDateParseStrategy(
    Date.ParseStrategy(
        format: "(month: .twoDigits)/(day: .twoDigits)/(year: .defaultDigits)",
        locale: Locale(identifier: "en_US"),
        timeZone: TimeZone(abbreviation: "CST")!
    )
)
// --------------------------------------------------

// Aquí leemos los archivos CSV, debemos arrastrar los archivos a la sección Resources, 
// de lado izquierdo en la barra de nuextro Xcode.
// En este caso son dos archivos, el que contiene los datos y un segundo que creé con fechas
// de prueba para ver los resultados.
let csvFile = Bundle.main.url(forResource: "HistoricalData", withExtension: "csv")!
let csvPred = Bundle.main.url(forResource: "prediction", withExtension: "csv")!
// --------------------------------------------------

// Creamos nuestro primer DataFrame que usaremos para hacer el modelo de Regresión Líneal
var dataFrame = try DataFrame (
    contentsOfCSVFile: csvFile,                        // Colocamos la variable que contiene nuestro CSV.
    columns: ["Fecha","Cerrar/último"],                // Indicamos que columnas usaremos de nuestro CSV
    types: ["Fecha": .date, "Cerrar/último": .double], // Indicamos el tipo de dato que contienen las columnas.
    options: options // Cargamos nuestras opciones para leer correctamente las fechas.
)
// --------------------------------------------------

// Imprimimos nuestro DataFrame para conocer su estructura, como podemos observar
// la columna Fecha es de tipo Date y la columna Cierre es de tipo Double como indicamos
// en la configuración de arriba. Son los datos con los que entrenaremos nuestro modelo.
print(dataFrame)
//┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
//┃    ┃ Fecha                     ┃ Cierre   ┃
//┃    ┃ <Date>                    ┃ <Double> ┃
//┡━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
//│ 0  │ 2022-01-30 06:00:00 +0000 │ 36,958.5 │
//│ 1  │ 2022-01-29 06:00:00 +0000 │ 38,040.5 │
//│ 2  │ 2022-01-28 06:00:00 +0000 │ 37,844.5 │
//│ 3  │ 2022-01-27 06:00:00 +0000 │ 37,151.3 │
//│ 4  │ 2022-01-26 06:00:00 +0000 │ 35,905.8 │
//│ 5  │ 2022-01-25 06:00:00 +0000 │ 36,391.9 │
//│ 6  │ 2022-01-24 06:00:00 +0000 │ 36,013.2 │
//│ 7  │ 2022-01-23 06:00:00 +0000 │ 35,095.6 │
//│ 8  │ 2022-01-22 06:00:00 +0000 │ 35,245.4 │
//│ 9  │ 2022-01-21 06:00:00 +0000 │ 36,303.9 │
//│ 10 │ 2022-01-20 06:00:00 +0000 │ 38,853.1 │
//│ 11 │ 2022-01-19 06:00:00 +0000 │ 41,929.2 │
//│ 12 │ 2022-01-18 06:00:00 +0000 │ 41,705.1 │
//│ 13 │ 2022-01-17 06:00:00 +0000 │ 42,026.6 │
//│ 14 │ 2022-01-16 06:00:00 +0000 │ 42,721.7 │
//│ 15 │ 2022-01-15 06:00:00 +0000 │ 43,069.7 │
//│ 16 │ 2022-01-14 06:00:00 +0000 │ 42,878.6 │
//│ 17 │ 2022-01-13 06:00:00 +0000 │ 42,747.6 │
//│ 18 │ 2022-01-12 06:00:00 +0000 │ 43,618.7 │
//│ 19 │ 2022-01-11 06:00:00 +0000 │ 42,576.5 │
//┢╍╍╍╍┷╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍┷╍╍╍╍╍╍╍╍╍╍┪
//┇ ...                                       ┇
//┗╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍┛

// Lo mismo que arriba, pero solo para una sola columna.
var dfPred = try DataFrame(
    contentsOfCSVFile: csvPred,
    columns: ["Fecha"],
    types: ["Fecha": .date],
    options: options
)

// Las fechas para las que haremos las predicciones de los precios.
//┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
//┃    ┃ Fecha                     ┃
//┃    ┃ <Date>                    ┃
//┡━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
//│ 0  │ 2022-03-01 06:00:00 +0000 │
//│ 1  │ 2022-03-02 06:00:00 +0000 │
//│ 2  │ 2022-03-03 06:00:00 +0000 │
//│ 3  │ 2022-03-04 06:00:00 +0000 │
//│ 4  │ 2022-03-05 06:00:00 +0000 │
//│ 5  │ 2022-03-06 06:00:00 +0000 │
//│ 6  │ 2022-03-07 06:00:00 +0000 │<-- Fecha concurso Bitso
//│ 7  │ 2022-03-08 06:00:00 +0000 │
//│ 8  │ 2022-03-09 06:00:00 +0000 │
//│ 9  │ 2022-03-10 06:00:00 +0000 │
//│ 10 │ 2022-03-11 06:00:00 +0000 │
//│ 11 │ 2022-03-12 06:00:00 +0000 │
//└────┴───────────────────────────┘
// --------------------------------------------------

// Usamos la función renameColumn para cambiar el nombre de la columna, tiene muchas otras funciones útiles
// que me recuerda a Pandas para el manejo y transofrmación de datos, en este caso para que sea más simple la lectura de esa columna.
dataFrame.renameColumn("Cerrar/último", to: "Cierre")
// --------------------------------------------------

// Separamos los datos de entrenamiento y prueba
let (trainingData, testingData) = dataFrame.randomSplit(by: 0.8)
// --------------------------------------------------

// Al igual que con CSVReadingOptions, instanciamos ModelParameters para acceder y configurar
// propiedades para generar nuestro modelo.
var params = MLLinearRegressor.ModelParameters()
params.maxIterations = 10000 // Iteramos 10000 para mayor placer (exactitud).
// --------------------------------------------------

// Generamos nuestro modelo con MLLinearRegressor
let btcPricer = try MLLinearRegressor(
    trainingData: trainingData.base, // Le pasamos nuestros datos de entrenamiento creados anteriormente.
    targetColumn: "Cierre",          // Colocamos el nombre de la columna de la que queremos las predicciones (output)
    featureColumns: ["Fecha"],       // Colocamos el dato que será de entrada (el segundo CSV en este caso), las fechas para que prediga el precio (Cierre)
    parameters: params.              // Colocamos la variable con los parametros establecidos en la sección anterior.
)
// --------------------------------------------------

// Aquí nos muestra la información de nuestro modelo y su nivel de exactitud
print(btcPricer.description)

//Parameters
//Max Iterations: 10000
//L1 Penalty: 0.0
//L2 Penalty: 0.01
//Step Size: 1.0
//Convergence Threshold: 0.01
//Feature Rescaling: true
//Performance on Training Data
//Max error: 27973.70
//Root mean squared error: 10217.46
//Performance on Validation Data
//Max error: 24645.20
//Root mean squared error: 10218.74
// --------------------------------------------------

// Basicamente lo mismo de arriba, pero resumido.
let evaluationMetrics = btcPricer.evaluation(on: testingData.base)
print(evaluationMetrics.rootMeanSquaredError)
print(evaluationMetrics.maximumError)
// --------------------------------------------------

// La metadata que contendrá nuestro modelo
let metadata = MLModelMetadata(
    author: "RigelGC",
    shortDescription: "Bitcoin Price Predictor 8000",
    version: "1.0"
)
// --------------------------------------------------

// Aquí guardamos nuestro modelo de Machine Learning para hacer predicciones, lo podemos usar con Python
// con la librería CoreMLTools y hacer predicciones desde ahí.
try btcPricer.write(
    to: URL(fileURLWithPath: "/Users/rigelgc/Downloads/btcPricer.mlmodel"), // La ruta donde se guardará nuestro archivo *.mlmodel
metadata: metadata                                                          // La metadata que generamos anteriormente.
)
// --------------------------------------------------

// Imprimimos nuestra predicción, mandamos llamar btcPricer.Predictions y dentro le pasamos nuestro segundo DataFrame
// Con los datos de entrada, en este caso solo una columna llamada Fechas con las fechas a las cuales quiero hacer la predicción.
print(try btcPricer.predictions(from: dfPred))

// Nos regresa el siguiente resultado para el segundo DataFrame
// con la columna Fecha y sus 12 fechas.
//┏━━━━━━━━━━━━━┓
//┃ Predictions ┃
//┃ <Double>    ┃
//┡━━━━━━━━━━━━━┩
//│  53,086.847 │
//│  53,140.417 │
//│  53,193.986 │
//│  53,247.555 │
//│  53,301.125 │
//│  53,354.694 │
//│  53,408.263 │ 2022-03-07 <-- Fecha concurso Bitso
//│  53,461.832 │.               Para esa Fecha ese es el precio que predice que tendrá.
//│  53,515.402 │
//│  53,568.971 │
//│   53,622.54 │
//│   53,676.11 │
//└─────────────┘

Войдите в полноэкранный режим Выход из полноэкранного режима

Теперь представьте, что у вас есть магазин, например, и вы хотите узнать, как будут продаваться определенные товары в течение какого-то месяца или части года, вы можете извлечь информацию из баз данных ваших торговых точек и применить этот же метод для прогнозирования.

Хотя верно, что в этой модели есть много возможностей для улучшения, в качестве первого знакомства с языком и фреймворками Apple она показалась мне очень интересной. Это правда, что он намного проще в использовании, чем TensorFlow или SKLearn или другие на Python, но в последнем автоматизация, на данный момент, проще для многих случаев использования.

В любом случае, я надеюсь, что это небольшое руководство было полезным, еще многому предстоит научиться, самым сложным было преобразование данных хаха и понимание некоторых ситуаций между DataFrame и MLDataTable, что было немного головной болью, но всегда очень интересно 😄.
Приветствую всех.

Bitso — лучшая платформа для приобретения криптовалют в Мексике на данный момент, я оставляю вам ссылку.

Оцените статью
devanswers.ru
Добавить комментарий