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

Логистическая регрессия

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

В приведенном выше примере, взятом из Статьи Википедии о логистической регрессии, показан график зависимости вероятности сдачи экзамена от количества часов, потраченных на обучение. Логистическая регрессия — хороший метод для решения этой проблемы, потому что мы пытаемся определить годен/не годен, двоичный селектор. Если бы мы хотели определить оценку или процент по тесту, лучшим методом была бы простая регрессия.

Чтобы продемонстрировать логистическую регрессию и то, как ее можно использовать в сочетании с Redis, мы рассмотрим еще один классический набор данных — Набор данных Fisher Iris Plant.

Набор данных

База данных Fisher Iris состоит из 150 точек данных, помеченных одним из 3 различных видов ириса: Iris setosa, Iris versicolor и Iris Virginica. Каждая точка данных состоит из четырех атрибутов (признаков) объекта. Используя логистическую регрессию, мы можем использовать атрибуты, чтобы отнести ирис к одному из трех видов.

База данных Fisher Iris является одним из наборов данных, включенных в учебный пакет Python scikit. Чтобы загрузить набор данных, используйте следующий код:

from sklearn.datasets import load_iris
iris = load_iris()

Мы можем распечатать данные в таблице и увидеть, что наши данные состоят из длины чашелистика, ширины чашелистика, длины лепестка и ширины лепестка, все в сантиметрах.

sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
0                  5.1               3.5                1.4               0.2
1                  4.9               3.0                1.4               0.2
2                  4.7               3.2                1.3               0.2
3                  4.6               3.1                1.5               0.2
4                  5.0               3.6                1.4               0.2
5                  5.4               3.9                1.7               0.4

Наша целевая классификация закодирована целыми числами 0, 1 и 2. 0 соответствует Iris Setosa, 1 соответствует Iris Versicolor, а 2 соответствует Iris Virginica.

Чтобы лучше понять взаимосвязь между различными измерениями и типом цветка, мы создали два графика: один для ширины чашелистика в зависимости от длины, а другой — для ширины лепестка в зависимости от длины. Каждый график показывает границы классификации (определенные с помощью логистической регрессии) трех классов и накладывает на них точки из нашего набора данных. Синий представляет область, классифицированную как Iris setosa, зеленый — Iris versicolor, а серый — Iris Virginica:

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

Выполнение логистической регрессии

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

Чтобы разделить тренировочный и тестовый наборы, мы используем следующий код:

x_train = [ x for (i, x) in enumerate(iris.data) if i%10 !=0 ]
x_test = [x for (i, x) in enumerate(iris.data) if i%10 == 0
y_train = [ y for (i, y) in enumerate(iris.target) if i%10 != 0 ]
y_test = [ y for (i, y) in enumerate(iris.target) if i%10 == 0 ]

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

После того, как мы создадим наши обучающие и тестовые наборы, для подбора логистической регрессии потребуется две строки кода:

logr = LogisticRegression()
logr.fit(x_train, y_train)
y_pred = logr.predict(x_test)

Последняя строка кода использует нашу обученную логистическую регрессию для прогнозирования типов радужной оболочки нашего тестового набора.

Предиктор Redis

Как и в нашем примере с линейной регрессией, мы можем построить предиктор логистической регрессии с помощью Redis.

Модуль Redis-ML предоставляет функции ML.LOGREG.SET и ML.LOGREG.PREDICT для создания ключей логистической регрессии.

Чтобы добавить модель логистической регрессии в Redis, вам нужно использовать команду ML.LOGREG.SET для добавления ключа в базу данных. Команда ML.LOGREG.SET имеет следующий вид:

ML.LINREG.SET key intercept coeef [...]

а функция ML.LOGREG.PREDICT используется для оценки логистической регрессии по значениям признаков и имеет форму:

ML.LOGREG.PREDICT key feature [...]

Порядок значений признаков в команде PREDICT должен соответствовать коэффициентам. Результатом команды PREDICT является вероятность того, что наблюдение принадлежит определенному классу.

Чтобы использовать Redis для создания мультиклассового классификатора, мы должны эмулировать процедуру One vs. Rest, используемую для мультиклассовой классификации. В процедуре One vs. Rest создается несколько классификаторов, каждый из которых используется для определения вероятности того, что наблюдение относится к определенному классу. Затем наблюдение помечается классом, к которому оно, скорее всего, принадлежит.

Для нашей задачи с тремя классами радужной оболочки нам потребуется создать три отдельных классификатора, каждый из которых определяет вероятность того, что точка данных находится в этом конкретном классе. Объект scikit LogisticRegression по умолчанию имеет значение One vs. Rest (ovr в API scikit) и соответствует коэффициентам для трех отдельных классификаторов.

Чтобы эмулировать эту процедуру в Redis, мы сначала создадим три ключа логистической регрессии, соответствующие коэффициентам, подобранным scikit:

r = redis.StrictRedis('localhost', 6379)
 for i in range(3):
     r.execute_command("ML.LOGREG.SET", "iris-predictor:{}".format(i), logr.intercept_[i], *logr.coef_[i])

Мы эмулируем процедуру прогнозирования One vs. Rest, которая выполняется в функции LogisticRegression.predict, перебирая наши три ключа и затем выбирая класс с наибольшей вероятностью. Следующий код выполняет процедуру One vs. Rest для наших тестовых данных и сохраняет полученные метки в векторе:

# Run predictions in Redis  
r_pred = np.full(len(x_test), -1, dtype=int)
for i, obs in enumerate(x_test):
     probs = np.zeros(3)
     for j in range(3):
         probs[j] = float(r.execute_command("ML.LOGREG.PREDICT", "iris-predictor:{}".format(j), *obs))
     r_pred[i] = probs.argmax()

Мы сравниваем окончательные классификации, распечатывая три вектора результатов:

# Compare results as numerical vector 
print("y_test = {}".format(np.array(y_test)))
print("y_pred = {}".format(y_pred))
print("r_pred = {}".format(r_pred))

Выходные векторы показывают фактические виды Iris (y_test) и прогнозы, сделанные scikit (y_pred) и Redis (r_pred). Каждый вектор хранит выходные данные в виде упорядоченной последовательности меток, закодированных как целые числа.

y_test = [0 0 0 0 0 1 1 1 1 1 2 2 2 2 2]
y_pred = [0 0 0 0 0 1 1 2 1 1 2 2 2 2 2]
r_pred = [0 0 0 0 0 1 1 2 1 1 2 2 2 2 2]

Redis и scikit сделали идентичные прогнозы, включая ошибочную маркировку одного сорта Virginica как Versicolor.

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

В следующем посте мы продолжим изучение возможностей модуля Redis-ML, рассмотрев матричные операции, поддерживаемые Redis-ML, и то, как их можно использовать для решения проблем ML. До тех пор, если у вас есть какие-либо вопросы относительно этих сообщений, свяжитесь с автором в Твиттере (@tague).

Познакомьтесь с Redis Enterprise на нашем новом веб-сайтеredislabs.com — и испытайте самую быструю и продуктивную базу данных в мире!

Этот блог изначально был размещен по адресу: https://redislabs.com/blog/introduction-redis-ml-part-three/

Если вы хотите просмотреть прошлые статьи Redis Watch или подписаться на Redis Watch, посетите нас здесь: https://redislabs.com/resources/redis-watch-archive/