机器学习

数学表达式用户指南的本部分涵盖机器学习函数。

距离和距离矩阵

distance 函数计算两个数字数组的距离或矩阵列的距离矩阵。

有六个距离度量函数返回执行实际距离计算的函数

  • euclidean(默认)

  • manhattan

  • canberra

  • earthMovers

  • cosine

  • haversineMeters(地理空间距离度量)

距离度量函数可与支持距离度量的所有机器学习函数一起使用。

以下是计算两个数字数组的欧几里得距离的示例

let(a=array(20, 30, 40, 50),
    b=array(21, 29, 41, 49),
    c=distance(a, b))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "c": 2
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}

在下面,使用曼哈顿距离计算距离。

let(a=array(20, 30, 40, 50),
    b=array(21, 29, 41, 49),
    c=distance(a, b, manhattan()))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "c": 4
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 1
      }
    ]
  }
}

距离矩阵

距离矩阵是用于可视化两个或多个向量之间距离的有力工具。

如果将矩阵作为参数传递,则 distance 函数将构建距离矩阵。距离矩阵是针对矩阵的计算的。

以下示例演示了距离矩阵与二维分面的强大结合。

在此示例中,facet2D 函数用于根据 nyc311 投诉数据库中的 complaint_type_szip_s 字段生成二维 facet 聚合。聚合了前 20 个投诉类型和每个投诉类型的前 25 个邮政编码。结果是一系列元组,每个元组都包含 complaint_type_szip_s 字段和该对的计数。

然后使用 pivot 函数将字段转换为一个矩阵,其中 zip_s 字段作为complaint_type_s 字段作为count(*) 字段填充矩阵单元格中的值。

然后使用 distance 函数使用余弦距离计算矩阵列的距离矩阵。这会生成一个距离矩阵,该矩阵显示基于邮政编码出现的投诉类型之间的距离。

最后,使用 zplot 函数将距离矩阵绘制为热图。请注意,热图已配置为随着向量之间距离的减小而增加颜色的强度。

distance

热图是交互式的,因此将鼠标悬停在某个单元格上会弹出该单元格的值。

distanceview

请注意,HEAT/HOT WATER 和 UNSANITARY CONDITION 投诉的余弦距离为 .1(四舍五入到最近的十分之一)。

K 近邻 (KNN)

knn 函数使用搜索向量搜索矩阵的行,并返回 k 个最近邻域的矩阵。这允许对结果集进行二次向量搜索。

knn 函数支持通过提供以下距离测量函数之一来更改距离测量

  • euclidean(默认)

  • manhattan

  • canberra

  • earthMovers

  • cosine

  • haversineMeters(地理空间距离度量)

以下示例展示了如何对聚合结果集执行二次搜索。该示例的目的是找到 nyc311 投诉数据库中与邮政编码 10280 具有相似投诉类型的邮政编码。

示例中的第一步是使用 facet2D 函数对 zip_scomplaint_type_s 字段执行二维聚合。在示例中,为曼哈顿区计算了前 119 个邮政编码和每个邮政编码的前 5 个投诉类型。结果是一系列元组,每个元组都包含 zip_scomplaint_type_s 和组合的 count(*)

然后使用 pivot 函数将元组列表转换为矩阵。此示例中的 pivot 函数返回一个矩阵,其中行是邮政编码,列是投诉类型。元组中的 count(*) 字段填充矩阵的单元格。此矩阵将用作二次搜索矩阵。

下一步是找到 10280 邮政编码的向量。示例中分三步完成此操作。第一步是使用 getRowLabels 函数从矩阵中检索行标签。在这种情况下,行标签是通过 pivot 函数填充的邮政编码。然后使用 indexOf 函数在行标签列表中找到“10280”邮政编码的索引。然后使用 rowAt 函数从矩阵中返回该索引处的向量。此向量是搜索向量

现在我们有了矩阵和搜索向量,就可以使用 knn 函数执行搜索。在示例中,knn 函数使用 K 为 5 的搜索向量搜索矩阵,使用余弦距离。余弦距离对于比较稀疏向量很有用,而本例中就是这种情况。knn 函数返回一个矩阵,其中包含与搜索向量最接近的 5 个近邻。

knn 函数填充返回矩阵的行和列标签,还将距离向量作为属性添加到矩阵中。

在示例中,zplot 函数使用 getRowLabelsgetAttribute 函数提取行标签和距离向量。topFeatures 函数用于根据每列的计数提取每个邮政编码向量的前 5 个列标签。然后,zplot 以表格形式输出数据,该表格可以在 Zeppelin-Solr 中可视化。

knn

上表显示了 knn 函数返回的每个邮政编码以及投诉列表和距离。这些邮政编码与 10280 邮政编码最相似,基于其前 5 种投诉类型。

K 近邻回归

K 近邻回归是一种非线性、双变量和多元回归方法。KNN 回归是一种惰性学习技术,这意味着它不会预先拟合训练集的模型。相反,整个训练集的观察和结果都保存在内存中,并且通过对 k 个最近邻域的结果求平均值来进行预测。

knnRegress 函数用于执行最近邻回归。

2D 非线性回归

以下示例显示了应用于 2D 散点图的 KNN 回归的回归图

在此示例中,random 函数用于从包含两个字段 filesize_deresponse_dlogs 集合中绘制 500 个随机样本。然后使用存储在分配给变量 x 的向量中的 filesize_d 字段和存储在变量 y 中的 eresponse_d 向量对样本进行矢量化。然后将 knnRegress 函数应用于 20 作为最近邻参数,它返回一个 KNN 函数,可用于预测值。然后在 KNN 函数上调用 predict 函数以预测原始 x 向量的值。最后,使用 zplot 绘制原始 xy 向量以及预测值。

knnRegress

请注意,回归图显示了 filesize_d 字段和 eresponse_d 字段之间的非线性关系。另请注意,KNN 回归通过散点图绘制非线性曲线。K(最近邻)的大小越大,曲线越平滑。

多元非线性回归

knnRegress 函数也是一种用于多元非线性回归的强大且灵活的工具。

在以下示例中,使用专为分析和预测葡萄酒质量而设计的数据库执行多元回归。该数据库包含近 1600 条记录,其中包含 9 个葡萄酒质量预测指标:pH 值、酒精、固定酸度、硫酸盐、密度、游离二氧化硫、挥发性酸度、柠檬酸、残留糖。还为每种葡萄酒分配了一个名为质量的字段,范围为 3 到 8。

KNN 回归可用于预测包含预测值向量的葡萄酒质量。

在该示例中,在 redwine 集合上执行搜索以返回数据库中所有观察行。然后,将质量字段和预测字段读入向量并设置为变量。

预测变量作为行添加到矩阵中,该矩阵进行转置,因此矩阵中的每一行都包含一个具有 9 个预测值的观察。这是我们的观测矩阵,它被分配给变量 obs

然后,knnRegress 函数对具有质量结果的观测进行回归。在此示例中,K 的值为 5,因此将使用 5 个最近邻的平均质量来计算质量。

然后使用 predict 函数为整个观察集生成一个预测向量。这些预测将用于确定 KNN 回归在观察数据上的执行情况。

然后通过从观测质量中减去预测质量来计算回归的误差或残差ebeSubtract 函数用于执行两个向量之间的逐元素减法。

最后,zplot 函数格式化预测和误差以可视化残差图

redwine1

残差图在 x 轴上绘制预测值,在 y 轴上绘制预测的误差。散点图显示误差在整个预测范围内的分布情况。

可以解释残差图以了解 KNN 回归在训练数据上的执行情况。

  • 该图显示预测误差似乎在零上方和下方相当均匀地分布。误差密度在接近零时增加。气泡大小反映了图中特定点处的误差密度。这为模型误差的分布提供了直观的感受。

  • 该图还可视化了预测范围内的误差方差。这提供了对 KNN 预测在整个预测范围内的误差方差是否相似的直观理解。

还可以使用直方图可视化残差,以更好地了解残差分布的形状。以下示例显示了与上述相同的 KNN 回归以及误差分布图。

在该示例中,zplot 函数用于绘制残差的empiricalDistribution 函数,并使用 11 个箱直方图。

redwine2

请注意,误差遵循一个接近 0 的钟形曲线。从这个图中,我们可以看到预测误差在 -1 到 1 之间的概率相当高。

其他 KNN 回归参数

knnRegression 函数有三个其他参数,使其适用于许多不同的回归场景。

  1. 只需将函数添加到调用中,即可将任何距离度量用于回归。这允许对稀疏向量(cosine)、稠密向量和地理空间 lat/lon 向量(haversineMeters)进行回归分析。

    示例语法

    r=knnRegress(obs, quality, 5, cosine()),
  2. robust 命名参数可用于执行对结果中的异常值具有鲁棒性的回归分析。当使用 robust 参数时,将使用 k 个最近邻域的中值结果,而不是平均值。

    示例语法

    r=knnRegress(obs, quality, 5, robust="true"),
  3. scale 命名参数可用于在预测时缩放观测值和搜索向量的列。当特征列处于不同的比例时,这可以提高 KNN 回归的性能,从而导致距离计算过多地加权较大的列。

    示例语法

    r=knnRegress(obs, quality, 5, scale="true"),

knnSearch

knnSearch 函数根据文本相似性为文档返回 k 个最近邻域。在幕后,knnSearch 函数使用 Solr 的More Like This 查询解析器。此功能使用搜索引擎的查询、术语统计、评分和排名功能,对大型分布式索引执行快速、最近邻域搜索以查找类似文档。

此搜索的结果可以直接使用,或为机器学习操作(例如辅助 KNN 向量搜索)提供候选

以下示例显示电影评论数据集上的 knnSearch 函数。搜索基于 review_t 字段的相似性,返回与特定文档 ID(83e9b5b0…​)最相似的 50 个文档。mindfmaxdf 指定用于执行搜索的术语的最小和最大文档频率。这些参数可以通过消除高频术语来加快查询速度,还可以通过从搜索中删除噪声术语来提高准确性。

knnSearch
在此示例中,select 函数用于将输出中的评论截断为 220 个字符,以便在表格中更轻松地阅读。

DBSCAN

DBSCAN 聚类是一种功能强大的基于密度的聚类算法,特别适合地理空间聚类。DBSCAN 使用两个参数将结果集筛选到特定密度的聚类

  • eps(Epsilon):定义点之间的距离,以将其视为邻域

  • min 点:聚类中返回所需的最少点数。

2D 聚类可视化

zplot 函数通过使用 clusters 命名参数直接支持绘制 2D 聚类。

以下示例使用 DBSCAN 聚类和聚类可视化来查找 NYC 311 投诉数据库中老鼠目击事件地图上的热点

在此示例中,random 函数从 nyc311 集合中抽取记录样本,其中投诉描述与“发现老鼠”相匹配,且记录中填充了纬度。然后,对纬度和经度字段进行矢量化,并将其作为行添加到矩阵中。对矩阵进行转置,以便每行包含一个纬度、经度点。然后,使用 dbscan 函数对纬度和经度点进行聚类。请注意,示例中的 dbscan 函数有四个参数。

  • obs:纬度/经度点的观测矩阵

  • eps:被视为一个聚类的点之间的距离。示例中为 100 米。

  • min points:聚类中函数返回的最小点数。示例中为 5

  • distance measure:用于确定点之间距离的可选距离度量。默认值为欧几里得距离。示例中使用 haversineMeters,它返回以米为单位的距离,这对于地理空间用例更有意义。

最后,使用 zplot 函数在 Zeppelin-Solr 地图上可视化聚类。下图已缩放到布鲁克林的一个特定区域,那里有大量老鼠出没。

dbscan1

请注意,在可视化中,仅从 5000 个样本中返回了 1019 个点。这就是 DBSCAN 算法过滤不符合聚类标准的记录的强大之处。绘制的所有点都属于明确定义的聚类。

可以进一步缩小地图可视化,以探索特定聚类的位置。以下示例显示了对密集聚类区域的缩小。

dbscan2

K 均值聚类

kmeans 函数对矩阵的行执行 k 均值聚类。聚类完成后,有许多有用的函数可用于检查和可视化聚类和质心。

聚类散点图

在此示例中,我们将再次对老鼠出没的 2D 纬度/经度点进行聚类。但与 DBSCAN 示例不同,k 均值聚类本身不执行任何降噪操作。因此,为了降低噪声,从数据中选择比 DBSCAN 示例中使用的更小的随机样本。

我们将看到,采样本身是一个强大的降噪工具,它有助于可视化聚类密度。这是因为从高密度聚类中抽取样本的概率更高,而从低密度聚类中抽取样本的概率更低。

在此示例中,random 函数从 nyc311(投诉数据库)集合中提取 1500 条记录的样本,其中投诉描述与“老鼠目击”相符,并且记录中填充了纬度。然后对纬度和经度字段进行矢量化,并将其作为行添加到矩阵中。对矩阵进行转置,以便每行包含一个纬度、经度点。然后使用 kmeans 函数将纬度和经度点聚类到 21 个簇中。最后,使用 zplot 函数将簇可视化为散点图。

2DCluster1

上面的散点图显示了每个纬度/经度点,这些点绘制在欧几里得平面上,经度在 x 轴上,纬度在 y 轴上。如果了解纽约市的各个区,则该图足够密集,以至于可以看到不同区的轮廓。

每个簇都显示为不同的颜色。此图提供了关于纽约市五个区老鼠目击密度的一些有趣的见解。例如,它突出显示了布鲁克林 cluster1 中密集目击的簇,周围是密度较低但仍然是高活动簇。

绘制质心

然后可以将每个簇的质心绘制在地图上,以可视化簇的中心。在下面的示例中,使用 getCentroids 函数从簇中提取质心,该函数返回质心的矩阵。

质心矩阵包含 2D 纬度/经度点。然后可以使用 colAt 函数按索引从矩阵中提取纬度和经度列,以便可以使用 zplot 绘制它们。下面使用地图可视化来显示质心。

centroidplot

然后可以缩放地图,以便更仔细地查看簇散点图中显示的高密度区域中的质心。

centroidzoom

短语提取

K 均值聚类生成质心或原型向量,可用于表示每个簇。在此示例中,提取质心的关键特征以表示 TF-IDF 术语向量的簇的关键短语。

以下示例适用于 TF-IDF 词向量。部分 文本分析和词向量 对这些功能进行了全面说明。

在示例中,search 函数返回其中 review_t 字段匹配短语“星球大战”的文档。select 函数在结果集上运行,并应用 analyze 函数,该函数使用附加到架构字段 text_bigrams 的分析器来重新分析 review_t 字段。此分析器返回双词组,然后将其注释到称为 terms 的字段中的文档中。

然后,termVectors 函数从存储在 terms 字段中的双词组创建 TD-IDF 词向量。然后使用 kmeans 函数将双词组词向量聚类到 5 个聚类中。最后,从质心提取前 5 个特征并返回。请注意,这些特征都是具有语义意义的双词组短语。

let(a=select(search(reviews, q="review_t:\"star wars\"", rows="500"),
             id,
             analyze(review_t, text_bigrams) as terms),
    vectors=termVectors(a, maxDocFreq=.10, minDocFreq=.03, minTermLength=13, exclude="_,br,have"),
    clusters=kmeans(vectors, 5),
    centroids=getCentroids(clusters),
    phrases=topFeatures(centroids, 5))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "phrases": [
          [
            "empire strikes",
            "rebel alliance",
            "princess leia",
            "luke skywalker",
            "phantom menace"
          ],
          [
            "original star",
            "main characters",
            "production values",
            "anakin skywalker",
            "luke skywalker"
          ],
          [
            "carrie fisher",
            "original films",
            "harrison ford",
            "luke skywalker",
            "ian mcdiarmid"
          ],
          [
            "phantom menace",
            "original trilogy",
            "harrison ford",
            "john williams",
            "empire strikes"
          ],
          [
            "science fiction",
            "fiction films",
            "forbidden planet",
            "character development",
            "worth watching"
          ]
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 46
      }
    ]
  }
}

多 K 均值聚类

K 均值聚类会根据质心的初始位置产生不同的结果。K 均值足够快,可以执行多次试验,以便可以选择最佳结果。

multiKmeans 函数针对给定的试验次数运行 k 均值聚类算法,并根据哪个试验产生最低的类内方差来选择最佳结果。

以下示例与短语提取示例相同,只是它使用 multiKmeans 进行 15 次试验,而不是 kmeans 函数的一次试验。

let(a=select(search(reviews, q="review_t:\"star wars\"", rows="500"),
             id,
             analyze(review_t, text_bigrams) as terms),
    vectors=termVectors(a, maxDocFreq=.10, minDocFreq=.03, minTermLength=13, exclude="_,br,have"),
    clusters=multiKmeans(vectors, 5, 15),
    centroids=getCentroids(clusters),
    phrases=topFeatures(centroids, 5))

此表达式返回以下响应

{
  "result-set": {
    "docs": [
      {
        "phrases": [
          [
            "science fiction",
            "original star",
            "production values",
            "fiction films",
            "forbidden planet"
          ],
          [
            "empire strikes",
            "princess leia",
            "luke skywalker",
            "phantom menace"
          ],
          [
            "carrie fisher",
            "harrison ford",
            "luke skywalker",
            "empire strikes",
            "original films"
          ],
          [
            "phantom menace",
            "original trilogy",
            "harrison ford",
            "character development",
            "john williams"
          ],
          [
            "rebel alliance",
            "empire strikes",
            "princess leia",
            "original trilogy",
            "luke skywalker"
          ]
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 84
      }
    ]
  }
}

模糊 K 均值聚类

fuzzyKmeans 函数是一种软聚类算法,它允许将向量分配到多个聚类中。fuzziness 参数是介于 12 之间的值,它决定了聚类分配的模糊程度。

执行聚类后,可以在聚类结果上调用 getMembershipMatrix 函数,以返回一个矩阵,描述每个向量的聚类成员资格概率。此矩阵可用于了解聚类之间的关系。

在以下示例中,fuzzyKmeans 用于对匹配短语“星球大战”的电影评论进行聚类。但不是查看聚类或质心,而是使用 getMembershipMatrix 来返回每个文档的成员资格概率。成员资格矩阵由每个已聚类的向量的行组成。矩阵中为每个聚类有一列。矩阵中的值包含特定向量属于特定聚类的概率。

在示例中,然后使用 distance 函数从成员资格矩阵的列创建距离矩阵。然后使用 zplot 函数将距离矩阵可视化为热图。

在示例中,cluster1cluster5 具有最短的簇间距离。可以进一步分析两个簇中的特征,以了解 cluster1cluster5 之间的关系。

fuzzyk
热图已配置为随着距离缩短而增加颜色强度。

特征缩放

在执行机器学习操作之前,通常需要缩放特征向量,以便可以在相同的比例下进行比较。

以下所有缩放函数都针对向量和矩阵进行操作。在对矩阵进行操作时,将缩放矩阵的行。

最小/最大缩放

minMaxScale 函数在最小值和最大值之间缩放向量或矩阵。如果未提供最小/最大值,则默认情况下它将在 01 之间缩放。

下面是在 -5 和 5 之间缩放之前和之后的具有 1 振幅的正弦波图。

minmaxscale

下面是矩阵在 0 和 1 之间进行最小/最大缩放的简单示例。请注意,一旦引入相同的比例,这些向量就是相同的。

let(a=array(20, 30, 40, 50),
    b=array(200, 300, 400, 500),
    c=matrix(a, b),
    d=minMaxScale(c))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "d": [
          [
            0,
            0.3333333333333333,
            0.6666666666666666,
            1
          ],
          [
            0,
            0.3333333333333333,
            0.6666666666666666,
            1
          ]
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}

标准化

standardize 函数缩放向量,使其均值为 0,标准差为 1。

下面是在标准化之前和之后的具有 1 振幅的正弦波图。

standardize

下面是标准化矩阵的简单示例。请注意,一旦引入相同的比例,这些向量就是相同的。

let(a=array(20, 30, 40, 50),
    b=array(200, 300, 400, 500),
    c=matrix(a, b),
    d=standardize(c))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "d": [
          [
            -1.161895003862225,
            -0.3872983346207417,
            0.3872983346207417,
            1.161895003862225
          ],
          [
            -1.1618950038622249,
            -0.38729833462074165,
            0.38729833462074165,
            1.1618950038622249
          ]
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 17
      }
    ]
  }
}

单位向量

unitize 函数将向量缩放为 1 的幅度。幅度为 1 的向量称为单位向量。当向量数学处理向量方向而不是幅度时,首选单位向量。

下面是在统一之前和之后的具有 1 振幅的正弦波图。

unitize

下面是统一矩阵的简单示例。请注意,一旦引入相同的比例,这些向量就是相同的。

let(a=array(20, 30, 40, 50),
    b=array(200, 300, 400, 500),
    c=matrix(a, b),
    d=unitize(c))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "d": [
          [
            0.2721655269759087,
            0.40824829046386296,
            0.5443310539518174,
            0.6804138174397716
          ],
          [
            0.2721655269759087,
            0.4082482904638631,
            0.5443310539518174,
            0.6804138174397717
          ]
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 6
      }
    ]
  }
}