机器学习
数学表达式用户指南的本部分涵盖机器学习函数。
距离和距离矩阵
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_s
和 zip_s
字段生成二维 facet 聚合。聚合了前 20 个投诉类型和每个投诉类型的前 25 个邮政编码。结果是一系列元组,每个元组都包含 complaint_type_s
、zip_s
字段和该对的计数。
然后使用 pivot
函数将字段转换为一个矩阵,其中 zip_s
字段作为行,complaint_type_s
字段作为列。count(*)
字段填充矩阵单元格中的值。
然后使用 distance
函数使用余弦距离计算矩阵列的距离矩阵。这会生成一个距离矩阵,该矩阵显示基于邮政编码出现的投诉类型之间的距离。
最后,使用 zplot
函数将距离矩阵绘制为热图。请注意,热图已配置为随着向量之间距离的减小而增加颜色的强度。
热图是交互式的,因此将鼠标悬停在某个单元格上会弹出该单元格的值。
请注意,HEAT/HOT WATER 和 UNSANITARY CONDITION 投诉的余弦距离为 .1(四舍五入到最近的十分之一)。
K 近邻 (KNN)
knn
函数使用搜索向量搜索矩阵的行,并返回 k 个最近邻域的矩阵。这允许对结果集进行二次向量搜索。
knn
函数支持通过提供以下距离测量函数之一来更改距离测量
-
euclidean
(默认) -
manhattan
-
canberra
-
earthMovers
-
cosine
-
haversineMeters
(地理空间距离度量)
以下示例展示了如何对聚合结果集执行二次搜索。该示例的目的是找到 nyc311 投诉数据库中与邮政编码 10280 具有相似投诉类型的邮政编码。
示例中的第一步是使用 facet2D
函数对 zip_s
和 complaint_type_s
字段执行二维聚合。在示例中,为曼哈顿区计算了前 119 个邮政编码和每个邮政编码的前 5 个投诉类型。结果是一系列元组,每个元组都包含 zip_s
、complaint_type_s
和组合的 count(*)
。
然后使用 pivot
函数将元组列表转换为矩阵。此示例中的 pivot
函数返回一个矩阵,其中行是邮政编码,列是投诉类型。元组中的 count(*)
字段填充矩阵的单元格。此矩阵将用作二次搜索矩阵。
下一步是找到 10280 邮政编码的向量。示例中分三步完成此操作。第一步是使用 getRowLabels
函数从矩阵中检索行标签。在这种情况下,行标签是通过 pivot
函数填充的邮政编码。然后使用 indexOf
函数在行标签列表中找到“10280”邮政编码的索引。然后使用 rowAt
函数从矩阵中返回该索引处的向量。此向量是搜索向量。
现在我们有了矩阵和搜索向量,就可以使用 knn
函数执行搜索。在示例中,knn
函数使用 K 为 5 的搜索向量搜索矩阵,使用余弦距离。余弦距离对于比较稀疏向量很有用,而本例中就是这种情况。knn
函数返回一个矩阵,其中包含与搜索向量最接近的 5 个近邻。
knn
函数填充返回矩阵的行和列标签,还将距离向量作为属性添加到矩阵中。
在示例中,zplot
函数使用 getRowLabels
和 getAttribute
函数提取行标签和距离向量。topFeatures
函数用于根据每列的计数提取每个邮政编码向量的前 5 个列标签。然后,zplot
以表格形式输出数据,该表格可以在 Zeppelin-Solr 中可视化。
上表显示了 knn
函数返回的每个邮政编码以及投诉列表和距离。这些邮政编码与 10280 邮政编码最相似,基于其前 5 种投诉类型。
K 近邻回归
K 近邻回归是一种非线性、双变量和多元回归方法。KNN 回归是一种惰性学习技术,这意味着它不会预先拟合训练集的模型。相反,整个训练集的观察和结果都保存在内存中,并且通过对 k 个最近邻域的结果求平均值来进行预测。
knnRegress
函数用于执行最近邻回归。
2D 非线性回归
以下示例显示了应用于 2D 散点图的 KNN 回归的回归图。
在此示例中,random
函数用于从包含两个字段 filesize_d
和 eresponse_d
的 logs
集合中绘制 500 个随机样本。然后使用存储在分配给变量 x 的向量中的 filesize_d
字段和存储在变量 y
中的 eresponse_d
向量对样本进行矢量化。然后将 knnRegress
函数应用于 20 作为最近邻参数,它返回一个 KNN 函数,可用于预测值。然后在 KNN 函数上调用 predict
函数以预测原始 x
向量的值。最后,使用 zplot
绘制原始 x
和 y
向量以及预测值。
请注意,回归图显示了 filesize_d
字段和 eresponse_d
字段之间的非线性关系。另请注意,KNN 回归通过散点图绘制非线性曲线。K(最近邻)的大小越大,曲线越平滑。
多元非线性回归
knnRegress
函数也是一种用于多元非线性回归的强大且灵活的工具。
在以下示例中,使用专为分析和预测葡萄酒质量而设计的数据库执行多元回归。该数据库包含近 1600 条记录,其中包含 9 个葡萄酒质量预测指标:pH 值、酒精、固定酸度、硫酸盐、密度、游离二氧化硫、挥发性酸度、柠檬酸、残留糖。还为每种葡萄酒分配了一个名为质量的字段,范围为 3 到 8。
KNN 回归可用于预测包含预测值向量的葡萄酒质量。
在该示例中,在 redwine
集合上执行搜索以返回数据库中所有观察行。然后,将质量字段和预测字段读入向量并设置为变量。
预测变量作为行添加到矩阵中,该矩阵进行转置,因此矩阵中的每一行都包含一个具有 9 个预测值的观察。这是我们的观测矩阵,它被分配给变量 obs
。
然后,knnRegress
函数对具有质量结果的观测进行回归。在此示例中,K 的值为 5,因此将使用 5 个最近邻的平均质量来计算质量。
然后使用 predict
函数为整个观察集生成一个预测向量。这些预测将用于确定 KNN 回归在观察数据上的执行情况。
然后通过从观测质量中减去预测质量来计算回归的误差或残差。ebeSubtract
函数用于执行两个向量之间的逐元素减法。
最后,zplot
函数格式化预测和误差以可视化残差图。
残差图在 x 轴上绘制预测值,在 y 轴上绘制预测的误差。散点图显示误差在整个预测范围内的分布情况。
可以解释残差图以了解 KNN 回归在训练数据上的执行情况。
-
该图显示预测误差似乎在零上方和下方相当均匀地分布。误差密度在接近零时增加。气泡大小反映了图中特定点处的误差密度。这为模型误差的分布提供了直观的感受。
-
该图还可视化了预测范围内的误差方差。这提供了对 KNN 预测在整个预测范围内的误差方差是否相似的直观理解。
还可以使用直方图可视化残差,以更好地了解残差分布的形状。以下示例显示了与上述相同的 KNN 回归以及误差分布图。
在该示例中,zplot
函数用于绘制残差的empiricalDistribution
函数,并使用 11 个箱直方图。
请注意,误差遵循一个接近 0 的钟形曲线。从这个图中,我们可以看到预测误差在 -1 到 1 之间的概率相当高。
其他 KNN 回归参数
knnRegression
函数有三个其他参数,使其适用于许多不同的回归场景。
-
只需将函数添加到调用中,即可将任何距离度量用于回归。这允许对稀疏向量(
cosine
)、稠密向量和地理空间 lat/lon 向量(haversineMeters
)进行回归分析。示例语法
r=knnRegress(obs, quality, 5, cosine()),
-
robust
命名参数可用于执行对结果中的异常值具有鲁棒性的回归分析。当使用robust
参数时,将使用 k 个最近邻域的中值结果,而不是平均值。示例语法
r=knnRegress(obs, quality, 5, robust="true"),
-
scale
命名参数可用于在预测时缩放观测值和搜索向量的列。当特征列处于不同的比例时,这可以提高 KNN 回归的性能,从而导致距离计算过多地加权较大的列。示例语法
r=knnRegress(obs, quality, 5, scale="true"),
knnSearch
knnSearch
函数根据文本相似性为文档返回 k 个最近邻域。在幕后,knnSearch
函数使用 Solr 的More Like This 查询解析器。此功能使用搜索引擎的查询、术语统计、评分和排名功能,对大型分布式索引执行快速、最近邻域搜索以查找类似文档。
此搜索的结果可以直接使用,或为机器学习操作(例如辅助 KNN 向量搜索)提供候选。
以下示例显示电影评论数据集上的 knnSearch
函数。搜索基于 review_t
字段的相似性,返回与特定文档 ID(83e9b5b0…
)最相似的 50 个文档。mindf
和 maxdf
指定用于执行搜索的术语的最小和最大文档频率。这些参数可以通过消除高频术语来加快查询速度,还可以通过从搜索中删除噪声术语来提高准确性。
在此示例中,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 地图上可视化聚类。下图已缩放到布鲁克林的一个特定区域,那里有大量老鼠出没。
请注意,在可视化中,仅从 5000 个样本中返回了 1019 个点。这就是 DBSCAN 算法过滤不符合聚类标准的记录的强大之处。绘制的所有点都属于明确定义的聚类。
可以进一步缩小地图可视化,以探索特定聚类的位置。以下示例显示了对密集聚类区域的缩小。
K 均值聚类
kmeans
函数对矩阵的行执行 k 均值聚类。聚类完成后,有许多有用的函数可用于检查和可视化聚类和质心。
聚类散点图
在此示例中,我们将再次对老鼠出没的 2D 纬度/经度点进行聚类。但与 DBSCAN 示例不同,k 均值聚类本身不执行任何降噪操作。因此,为了降低噪声,从数据中选择比 DBSCAN 示例中使用的更小的随机样本。
我们将看到,采样本身是一个强大的降噪工具,它有助于可视化聚类密度。这是因为从高密度聚类中抽取样本的概率更高,而从低密度聚类中抽取样本的概率更低。
在此示例中,random
函数从 nyc311
(投诉数据库)集合中提取 1500 条记录的样本,其中投诉描述与“老鼠目击”相符,并且记录中填充了纬度。然后对纬度和经度字段进行矢量化,并将其作为行添加到矩阵中。对矩阵进行转置,以便每行包含一个纬度、经度点。然后使用 kmeans
函数将纬度和经度点聚类到 21 个簇中。最后,使用 zplot
函数将簇可视化为散点图。
上面的散点图显示了每个纬度/经度点,这些点绘制在欧几里得平面上,经度在 x 轴上,纬度在 y 轴上。如果了解纽约市的各个区,则该图足够密集,以至于可以看到不同区的轮廓。
每个簇都显示为不同的颜色。此图提供了关于纽约市五个区老鼠目击密度的一些有趣的见解。例如,它突出显示了布鲁克林 cluster1 中密集目击的簇,周围是密度较低但仍然是高活动簇。
绘制质心
然后可以将每个簇的质心绘制在地图上,以可视化簇的中心。在下面的示例中,使用 getCentroids
函数从簇中提取质心,该函数返回质心的矩阵。
质心矩阵包含 2D 纬度/经度点。然后可以使用 colAt
函数按索引从矩阵中提取纬度和经度列,以便可以使用 zplot
绘制它们。下面使用地图可视化来显示质心。
然后可以缩放地图,以便更仔细地查看簇散点图中显示的高密度区域中的质心。
短语提取
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
参数是介于 1
和 2
之间的值,它决定了聚类分配的模糊程度。
执行聚类后,可以在聚类结果上调用 getMembershipMatrix
函数,以返回一个矩阵,描述每个向量的聚类成员资格概率。此矩阵可用于了解聚类之间的关系。
在以下示例中,fuzzyKmeans
用于对匹配短语“星球大战”的电影评论进行聚类。但不是查看聚类或质心,而是使用 getMembershipMatrix
来返回每个文档的成员资格概率。成员资格矩阵由每个已聚类的向量的行组成。矩阵中为每个聚类有一列。矩阵中的值包含特定向量属于特定聚类的概率。
在示例中,然后使用 distance
函数从成员资格矩阵的列创建距离矩阵。然后使用 zplot
函数将距离矩阵可视化为热图。
在示例中,cluster1
和 cluster5
具有最短的簇间距离。可以进一步分析两个簇中的特征,以了解 cluster1
和 cluster5
之间的关系。
热图已配置为随着距离缩短而增加颜色强度。 |
特征缩放
在执行机器学习操作之前,通常需要缩放特征向量,以便可以在相同的比例下进行比较。
以下所有缩放函数都针对向量和矩阵进行操作。在对矩阵进行操作时,将缩放矩阵的行。
最小/最大缩放
minMaxScale
函数在最小值和最大值之间缩放向量或矩阵。如果未提供最小/最大值,则默认情况下它将在 0
和 1
之间缩放。
下面是在 -5 和 5 之间缩放之前和之后的具有 1 振幅的正弦波图。
下面是矩阵在 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 振幅的正弦波图。
下面是标准化矩阵的简单示例。请注意,一旦引入相同的比例,这些向量就是相同的。
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 振幅的正弦波图。
下面是统一矩阵的简单示例。请注意,一旦引入相同的比例,这些向量就是相同的。
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
}
]
}
}