dot 快速发展的未来即将在您所在的城市举办的活动中亮相。

加入我们在 Redis 发布会

Redis-ML 入门(第三部分)

这篇文章是介绍 Redis-ML 模块的一系列文章的第三部分。 本系列文章的第一篇文章可以在这里找到这里。 本文的示例代码需要几个 Python 库和一个运行 Redis-ML 的 Redis 实例。 运行代码的详细设置说明可以在本系列文章的第一部分或第二部分中找到。

逻辑回归

逻辑回归是另一种线性模型,用于根据观察到的数据构建预测模型。 与用于预测值的线性回归不同,逻辑回归用于预测二进制值(通过/失败、赢/输、健康/生病)。 这使得逻辑回归成为一种分类形式。 基本逻辑回归可以进行扩展以解决多类分类问题。

上面的示例,取自逻辑回归维基百科文章,显示了通过考试的概率与学习时间的相关图。 逻辑回归是解决此问题的良好方法,因为我们试图确定通过/失败,这是一个二进制选择器。 如果我们要确定考试的分数或百分比,则简单回归将是一种更好的技术。

为了演示逻辑回归及其如何与 Redis 结合使用,我们将探索另一个经典数据集,即Fisher 鸢尾花数据集

数据集

Fisher 鸢尾花数据库包含 150 个数据点,每个数据点都标记了三种不同的鸢尾花物种之一:山鸢尾变色鸢尾维吉尼亚鸢尾。 每个数据点包含植物的四个属性(特征)。 使用逻辑回归,我们可以使用这些属性将鸢尾花分类到三个物种之一。 

Fisher 鸢尾花数据库是 Python scikit learn 包中包含的数据集之一。 要加载数据集,请使用以下代码

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 对应于山鸢尾,1 对应于变色鸢尾,2 对应于维吉尼亚鸢尾。

Graph of Sepal measurements

为了更好地了解各种测量值与花卉类型之间的关系,我们生成了两个图:一个是萼片宽度与长度的关系图,另一个是花瓣宽度与长度的关系图。每个图都显示了三个类别的分类边界(通过逻辑回归确定),并在其上叠加了我们数据集中的点。 蓝色代表分类为山鸢尾的区域,绿色代表变色鸢尾,灰色代表维吉尼亚鸢尾

我们可以在两个图中看到,有一些异常值被误分类,但大多数鸢尾花类型聚集在一起,形成了不同的组。

执行逻辑回归

在 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.SETML.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 过程中,会创建多个分类器,每个分类器用于确定观察值属于特定类的概率。 然后,观察值将被标记为它最有可能属于的类。

对于我们的三类鸢尾花问题,我们需要创建三个独立的分类器,每个分类器都确定数据点属于该特定类的概率。 scikitLogisticRegression对象默认使用 One vs. Rest(在 scikit API 中为 ovr)并拟合三个独立分类器的系数。 

要模拟 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])

我们模拟发生在 LogisticRegression.predict 函数中的 One vs. Rest 预测过程,方法是遍历三个键,然后选择概率最高的类。 以下代码在测试数据上执行 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))

输出向量显示了实际的鸢尾花物种(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 做出了相同的预测,包括将一个维吉尼亚鸢尾花误标记为变色鸢尾花。

您可能不需要高度可用的实时鸢尾花分类器,但通过利用这个经典数据集,您已经学习了如何使用Redis-ML模块为自己的数据实现高度可用的实时分类器。

在下一篇文章中,我们将继续研究 Redis-ML 模块的功能,方法是查看 Redis-ML 支持的矩阵运算,以及如何使用它们来解决 ML 问题。 在此之前,如果您对这些文章有任何疑问,请在 Twitter 上联系作者(@tague)。