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

Содержание:

  • Изучение набора данных
  • Подготовка данных
  • Изучение различных моделей:
    – регрессия с глубоким обучением
    – регрессор случайного леса
    – регрессор опорных векторов
  • Сравнение и оценка моделей
  • Создание веб-API, использующего модель

Набор данных

Набор данных включает 226 строк (разные учащиеся), каждая из которых содержит 8 функций и значение класса. Поскольку данные об итоговых оценках по курсу отсутствуют, они берутся из исходных оценок по теории с некоторой модификацией.

Функции

Особенностями являются оценки студента за прошлые курсы с первого и второго семестров. Всего 8: ВВКН, СП, ДМ, ОНВД, ООП, К, АОК, АИПС

Отсутствующие значения

Некоторые студенты не проходят все эти курсы, поэтому значение формируется как среднее из аналогичных курсов.

Пример: Для студентов, которые не посещают курс DM, значение генерируется как среднее из DS1 и DS2, где изучается один и тот же материал, но более углубленно в 2 курсах.

Подготовка данных

К счастью, данные относительно чистые, поскольку оценка может принимать только шесть значений от 5 до 10 (F-A). Нам не нужно какое-либо кодирование, потому что значения являются целыми числами, и нам не нужно масштабировать данные.

Начнем с необходимого импорта, прочитаем набор данных и удалим ненужные столбцы.

import pandas as pd
from tensorflow import keras
import tensorflow as tf
from sklearn.model_selection import train_test_split
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
import math
# Load and shuffle the data
dataset = pd.read_excel('/content/ocenki.xlsx', header=0)
dataset = dataset.drop('Name',axis=1)
dataset = dataset.drop('Id',axis=1)
dataset = dataset.iloc[np.random.permutation(len(dataset))]
dataset.head()

Корреляция между функциями и классом

corr = dataset.corr()
corr.style.background_gradient(cmap='coolwarm')

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

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

Мы видим, что существует высокая корреляция между курсом вероятности и статистики (VIS) и другими математическими курсами, такими как DM и K.

# Split the data
features = dataset.drop('VIS',axis=1)
classes = dataset['VIS']
X_train, X_test, y_train, y_test = train_test_split(features, classes, test_size=0.2)Models

Регрессия глубокого обучения

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

Я буду использовать Keras и TensorFlow для обучения глубокой нейронной сети для прогнозирования оценки с использованием 2 скрытых слоев, среднеквадратичной потери ошибки и оптимизатора RMSprop.

# build the model with 2 hidden layers
model = Sequential()
model.add(Dense(12, activation='relu', input_shape=(8,)))
model.add(Dense(32, activation='relu'))
model.add(Dense(1))

model.compile(loss='mse',optimizer=tf.keras.optimizers.RMSprop(),metrics=['mae', 'mse'])
# fit with 200 epochs
history = model.fit(X_train,y_train,epochs=200,validation_data=(X_test,y_test), verbose=1)

Построим график ошибки и потерь при обучении и оценим модель

import seaborn as sns
import matplotlib.pyplot as plt


def plot_graph_loss(history):
    plt.plot(history.history['mae'])
    plt.plot(history.history['val_mae'])
    plt.title('model error')
    plt.ylabel('error')
    plt.xlabel('epoch')
    plt.legend(['train', 'test'], loc='upper left')
    plt.show()
    # summarize history for loss
    plt.plot(history.history['loss'])
    plt.plot(history.history['val_loss'])
    plt.title('model loss')
    plt.ylabel('loss')
    plt.xlabel('epoch')
    plt.legend(['train', 'test'], loc='upper left')
    plt.show()
# graph error and loss
plot_graph_loss(history)
model.evaluate(X_test, y_test, batch_size=128)

1/1 [==============================] - 0s 22ms/step - loss: 0.8523 - mae: 0.6958 - mse: 0.8523

При таком подходе мы получаем среднюю абсолютную ошибку 0,69.

Нам также нужно сохранить модель, чтобы развернуть ее в API. Поскольку я использую Google Colab, я могу легко сохранить его на диске Google.

# save to google drive
from google.colab import drive
import joblib
drive.mount('/content/gdrive').
model.save('/content/gdrive/My Drive/VIS_Predictors/deep_learning')

Случайный лесной регрессор

Инициализируйте случайный лес со 100 деревьями решений и обучите его на тех же данных.

from sklearn.ensemble import RandomForestRegressor
# init model with 100 trees
forest_model = RandomForestRegressor(n_estimators=100)
forest_model.fit(X_train,y_train)

Вспомогательная функция для расчета средней абсолютной ошибки на тестовом наборе.

def mae(real,pred):
  score = 0
  for x,y in zip(real,pred):
    score += abs(x-y)
  return score/len(real)
mae(y_test,forest_model.predict(X_test))

Мы получаем MAE 0,58.

Давайте также сохраним эту модель.

joblib.dump(forest_model,'/content/gdrive/MyDrive/VIS_Predictors/random_forest')

Регрессор опорных векторов

Инициализируйте регрессор опорных векторов с C=1 и epsilon=0,2.

from sklearn.svm import SVR
svr = SVR(C=1.0, epsilon=0.2)
svr.fit(X_train, y_train)
mae(y_test,svr.predict(X_test))

Мы получаем MAE 0,57, что является лучшим на данный момент.

# save the model
joblib.dump(svr,'/content/gdrive/My Drive/VIS_Predictors/svr')

Сравнение моделей

Учитывая, что это небольшой ограниченный набор данных, имеет смысл, что почти все модели выдают одинаковую среднюю абсолютную ошибку на тестовом наборе. Регрессия опорных векторов имеет наилучшую MAE 0,57. Глубокое обучение с некоторой настройкой гиперпараметров, вероятно, может быть даже ниже 0,69.

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

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

Развертывание модели в качестве веб-API

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

Мы можем создать фляжный веб-API, который загружает модель и отвечает на запросы.

from flask import Flask, request, jsonify
from urllib.request import urlopen
app = Flask(__name__)
@app.route(‘/’, methods=[‘GET’])
def index():
    return “Hello”
@app.route(‘/prediction’, methods=[‘POST’])
def predict():
    lr = joblib.load(PATH_TO_SAVED_MODEL)
    if lr:
        json = request.json
        predict = list(lr.predict([json]))
        return jsonify({‘prediction’: str(predict[0])})
    else:
        return ‘Failed to load’
if __name__ == “__main__”:
    app.run()

Если вы хотите разместить его самостоятельно, просто запустите сервер и все. Однако вы также можете бесплатно разместить его в Azure. Это довольно просто, следуя руководству здесь.

Заключительные заметки

В этом посте мы рассмотрели создание и развертывание базовых моделей регрессии с использованием различных методов.

Я разместил веб-API и создал реагирующее веб-приложение, в котором студенты могут прогнозировать, пройдут ли они курс вероятности и статистики здесь. Он использует регрессор случайного леса из этого поста.