Machine Learning, Python

Браузерный ML с TensorFlow.js

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

TensorFlow – библиотека, которая имеет открытый исходный код, с помощью нее можно разрабатывать и обучать ML модели.

Библиотека появилась на свет 6 лет назад, изначально была реализована на Python, так же есть реализации и на других языках, то есть: R, C, C#, Java, Swift.

Спустя время библиотека была доработана и появилась реализация для JavaScript — TensorFlow.Js. Реализация на JS позволяет развертывать и обучать модели в браузере и на Node.js. Разработчик имеет возможность обучить и запустить модель при помощи высокоуровневого API.

За счёт заранее обученных моделей разработчик может решать задачи самой разной сложности. Например, предсказание стоимости автомобиля или выдать ли кредит тому или иному человеку и всё это в нескольких строчках кода.

Давайте посмотрим, как же работает браузерный ML.

Вариант первый: мы можем запустить наш код в тегах <script></script> HTML файла. Код, который я привел ниже, решает задачу линейной регрессии.

Загрузка tensorflow.js:

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.10.0"></script>

Определение модели линейной регрессии и создание простейшей нейронной сети:

const LRModel = tf.sequential({
        layers: [tf.layers.dense({ units: 1, inputShape: 1 })],
      });

Подготовка модели:

LRModel.compile({ loss: "meanSquaredError", optimizer: "adam" });

Создание выборки:

const x = tf.tensor2d([1, 3, 5, 7], [4, 1]);
const y = tf.tensor2d([2, 4, 6, 8], [4, 1]);

Обучение модели:

LRModel.fit(x, y).then(() => {
        LRModel.predict(tf.tensor2d([4], [1, 1])).print();
      });

Результат обучения:

Tensor
     [[-2.4567912],]

Вариант второй: импортируем TensorFlow.js в проект при помощи npm. В таком случае  код будет расположен в файле с расширением «.js»:

import * as tf from "@tensorflow/tfjs";
      const LRModel = tf.sequential({
        layers: [tf.layers.dense({ units: 1, inputShape: 1 })],
      });
      LRModel.compile({ loss: "meanSquaredError", optimizer: "adam" });
      const x = tf.tensor2d([1, 3, 5, 7], [4, 1]);
      const y = tf.tensor2d([2, 4, 6, 8], [4, 1]);
      LRModel.fit(x, y).then(() => {
        LRModel.predict(tf.tensor2d([4], [1, 1])).print();
      });

Код аналогичен тому, который мы запускали из HTML разметки, исключением становится импорт фреймворка, ведь тут он будет использоваться локально.

Теперь давайте рассмотрим работу tf.js на реальных данных. Возьмем всем известный датасет для задачи классификации Ирисы Фишера.

Выглядит он следующим образом:

async function tensorflow_test(){
const dataset = 'iris.csv';
const train_data = tf.data.csv(
    dataset, {columnConfigs: {
        variety: {
            isLabel: true
        }
    }
});

Столбец «variety» является меткой и будет частью набора у, все остальное является характеристиками и будет частью набора x, n_features – количество функций (количество функций есть имена столбцов с длинной минус единица, чтобы исключить имена этих самых столбцов)

Методом map преобразуем наши значения x как массив, а у как метки (Setosa (100), Virginica(010) и Versicolor (001)). Преобразованные данные пойдут на обучение нашей модели.

const n_features = (await train_data.columnNames()).length - 1;
const n_samples = 150;
const convert_data = train_data.map(({xs, ys}) => {
    const labels = [
        ys.variety == "Setosa" ? 1 : 0,
        ys.variety == "Virginica" ? 1 : 0,
        ys.variety == "Versicolor" ? 1 : 0
    ]
    return{xs: Object.values(xs), ys: Object.values(labels)};}).batch(7);

Создаем модель, активируем её функцией relu. В выходном слое будет три единички, так как три класса, и активировать его мы будет softmax. Компилируем модель с средней квадратичной ошибкой и оптимизатором adam. Так же мы можем настроить скорость обучения, чтобы получить наилучшие результаты, но здесь я этого делать не стал. Тренируем нашу модель, используем 100 эпох и в консоль будем выводить номер эпохи и loss.

const model = tf.sequential();
model.add(tf.layers.dense({inputShape: [n_features], activation: "relu", units: 5}))
model.add(tf.layers.dense({activation: "softmax", units: 3}));
model.compile({loss: "meanSquaredError", optimizer: 'adam'});
await model.fitDataset(convert_data, {epochs:100, callbacks:{onEpochEnd: async(epoch, logs) =>{
    console.log("Epoch: " + epoch + " Loss: " + logs.loss);
}}});

Создадим тестовые данные для прогнозирования:

const predict_val = tf.tensor2d([1.3, 2.7, 0.4, 3.2], [1, 4]);
const prediction = model.predict(predict_val);
const Indexes = tf.argMax(prediction, axis=1).dataSync();
const Names = ["Setosa", "Virginica", "Versicolor"];
console.log("Результат: ", Names[Indexes]);
}

Запускаем нашу функцию, переходим в консоль разработчика в браузере и смотрим за обучением нашей модели 🙂

tensorflow_test();

В заключение хочу выделить преимущества TensorFlow.js:

  1. Интерактивность, в браузере полно инструментов для визуализации происходящих процессов (анимации, графики и т.д.);
  2. Совместимость с моделями, которые были реализованы на языке Python;
  3. Огромное сообщество.

Полную документацию по TensorFlow.js вы найдете по ссылке

Советуем почитать