本期文章,我们对embedding词嵌入、similarity相似性和clustering聚类进行相关的介绍,而这些都是大多数 ML机器学习的基础,也是自动编码器必不可少的算法。
在计算机中将真实的相关数据表示为计算机可以识别的数据过程称为embedding词嵌入,这在我们介绍transformer模型时有相关的介绍,因为计算机不能直接识别图片,或者文字,我们需要把这些图片或者文字进行一定的编码操作后,才能让计算机识别。在分析现实世界中的数据,并将其用于应用程序之前,embedding词嵌入是必不可少的。
Similarity 算法用来发现真实数据经过embedding词嵌入后,彼此之间的相似程度,类似的应用,比如说产品推荐,大数据杀熟等应用程序。
clustering聚类识别真实数据,并把相关有关联的数据,聚集在一起,例如识别哪些书是关于同一主题的,那些电影是相关主题的电影,然后根据推荐算法,推荐给有相关兴趣爱好的人
Embedding
计算机不会识别现实生活中的图片,音频等信息,计算机只会识别数字,那如何让计算机能够识别出现实世界的物体,图片,音频那。
在计算机中表示某物的过程称为Embedding。计算机只知道数字,因此必须这样表示真实世界的数据。Embedding开始于我们希望表达什么以及如何表达某物的问题。
比如如下的例子,通过用数码相机拍摄其页面的图像来得到一张图书的照片。相机有很多微型传感器,每个传感器都会获取它所看到的颜色并将该颜色转换为数字。这些传感器将相机看到的内容分成小方块,每个方块都是一个传感器得到的相关数据
Embedding一本书需要很多数字。一个“G”字母需要 5x5=25 个数字,一个 48 个字符的句子需要 25x48=1.200数字,一页 28 行需要 1.200*28=33.600,整本书 250 页需要 33.600*250=8.400.000 个数字——这么多的数字该如何来表达?
数字和字母通常采用称为ASCII的格式,数字介于 48 和 122 之间,其中计算机知道 48 是“0”,而 71 是大写“G”。使用 ASCII 表示一个字符是 1 个数字,一个句子是 1x48=48 个数字,一页是 48*28=1344 个数字,一本书是 1433*250=336.000 个数字。
通过ASCII码的形式来表达数字与字母,就节省了很多资源
计算机存储字符(数字和字母)的 ASCII 表
一本书的内容可以用科幻、传记、恐怖和小说等类型来表示。假设有 256 种不同的类型,那么我们可以用0-255数字来表示此书的类型,这样我们就可以根据读者的兴趣爱好来推荐了。当然,我们也可以0101二进制代码来表示,无论如何,我们都需要把现实世界的问题转换为数字问题,以便计算机能够正常识别。
这样,把现实世界的一个问题,转换为计算机可以识别的问题,称之为Embedding,当然Embedding在ML机器学习领域中最出名的便是one-hot编码了。在Transformer模型中,我们也介绍过word-embedding,其操作就是词嵌入的一种,只是transformer模型的维度为512
动画详解Transformer模型 VIT 模型 SWIN Transformer模型http://t.csdn.cn/FSc0M
相似性和向量化
相似性的目标是找到相似的数据,当然数据都是经过Embedding后的。模型可以使用相似性来推荐与读者已经阅读过的书籍相似的其他书籍。
但什么是相似性?相似性基于可以绘制到坐标系中的数值(也称为测量值、样本或点),也称为维度空间(或简称空间)。将数值放置到坐标系中时,我们将其称为一个点。下面是设置到二维坐标系中的四本书的示例。
四本书放置在一个二维坐标系中
如果点在空间上靠得更近,它们就会更相似。书籍也是如此。两本小说类书籍(A 点和 B 点)比一本非小说类书籍更相似(A 点和 C 点)。相似度是两点之间的距离,L1 < L2 表明 A 和 B 比 A 和 C 更相似。
A 和 B 之间的距离(即 L1)以及 A 和 C 之间的距离(即 L2)。A 和 B 比 A 和 C 更接近,因为 L1 < L2。
在实践中,向量化允许我们计算它们之间的距离(即相似度),我们建立一个二维坐标系,坐标系便是一个向量空间。每个点在这个二维坐标系中,就有了坐标,每个点的坐标形成一个向量。
假设点从 (0, 0) 开始,可以将它们转换为向量
AB之间的距离是在两点之间传播的向量的长度,称为欧几里得距离。公式如下
欧几里得相似度是两点之间的距离
在 Python 中,欧几里得相似度的计算方法是使用 Numpy 创建两个向量。然后相减取norm即可
import numpy
import math
A = numpy.array([2, 3])
B = numpy.array([4, 1])
A_B = A - B
dist = numpy.linalg.norm(A_B)
sum_of_squared_distances = numpy.dot(A_B, A_B)
euclidean_dist_manuel = math.sqrt(sum_of_squared_distances)
确定相似度的另一种方法是余弦相似度,它着眼于向量之间的角度,而不是它们末端之间的距离。A 点更侧重于小说,B 点更侧重于 Life-Journey——即使它们在欧几里得空间中彼此接近,但是它们的概念与特征大不相同。
余弦相似度是两个向量之间的夹角,我们在介绍transformer模型时也有提示类似的概念,当2个向量之间的夹角越小,说明在某个维度上最相似,夹角越大,说明在某个维度相似性最小,比如上面图示的2本书,若AB之间的夹角越小,说明在某个图书类别上有一定的相似性,若夹角等于90度,那2本书在图书类别上来讲,就没有任何相似性了。
计算余弦相似度分数的公式
在 Python 中,余弦相似度是通过使用 Numpy 创建两个向量并使用 Scipy 找到两者之间的余弦来计算的。
from scipy import spatial
import math
# ---- 使用API计算----
cosine_dist_easy = spatial.distance.cosine(A, B)
# ---- 使用公式手动计算 ----
product_AB = numpy.dot(A, B)
book_A_length = numpy.linalg.norm(A,2)
book_B_length = numpy.linalg.norm(B,2)
cosine_dist_manuel = 1 - (product_AB / (book_A_length * book_B_length))
我们可以同时使用欧几里得相似度和余弦相似度,找到自己数据集中符合要求的算法。
聚类Clustering
聚类是一种帮助我们在数据中找到相似聚类组的技术。还根据我们读书的例子,系统根据读者喜欢阅读的群体/类型推荐新书。直观地说,一个聚类组由相似的对象组成。聚类任务是确定哪些点最相似,以及如何将它们组合成适当数量的聚类组。聚类方法使用相似度公式来评估点之间相似度;我们通过使用点之间的欧几里得相似性并结合最接近的点来创建下图中的两个组。对这两组的分析表明,我们的主要阅读内容包括教科书和科幻
通过找到密切相关的点对可以创建两个聚类组
聚类组的数量是一个超参数,这意味着定义它的不是计算机,而是预先定义的常量。选择正确数量的集群(即聚类组)至关重要。下图用一个、两个和四个聚类分析数据,以显示变量数字的影响。
通过向数据添加 1、2 、3、 4 个集群提供的信息
一个集群告诉我们,读者喜欢书籍,这可能对我们正在制作一个关于分析书籍偏好的应用程序没有太大帮助。四个集群向我们展示了读者喜欢 A、B、C 和 D 类型的书,但对推荐同一组中的新书贡献不大。两个集群更适合这种情况,因为它们提供的信息表明教科书和奇幻书籍是阅读最多的书籍。
上一个示例中的四个集群太多,无法提取有用信息。在此示例中,需要四个集群才能正确理解数据。没有完美的集群数量,它都是特定于应用程序的。
通常用于聚类的两种方法是k-means 聚类和hierarchical聚类。
K-means 聚类
K-means 聚类中的“K”定义了聚类的数量。K=2 表示必须在数据中找到两个簇,K=4 表示必须在数据中找到四个簇。“平均值”定义了每个集群如何成为其组的平均值,将其置于其组的中心。
一个簇通过在同一空间中放置一个新点来表示数据的一部分。新点现在可以代表这部分数据。
将集群作为代表数据部分的新数据点放置到空间中
K-means 的目标是为每个集群找到最佳位置。放置一个集群并不像上面那样简单,每个集群都位于彩色圆圈的中心。
vec_a = [2, 3]
vec_b = [3, 1]
vec_c = [7, 5]
vec_d = [8, 7]
vec_e = [3, 8]
vec_f = [4, 9]
vec_g = [9, 2]
vec_h = [10, 1.8]
data_points = [vec_a, vec_b, vec_c, vec_d, vec_e, vec_f, vec_g, vec_h]
寻找 K 簇的第一步是将 K个 点随机放入空间中。使用随机点可能看起来违反直觉,因为为什么不将它们等距放置在空间中呢?主要原因是所有数据看起来都不一样,这通常会导致等间距的点没有放在实际组的中心。如果一切顺利,实际组是我们希望在数据中找到的组。K-means 聚类并不能确保我们找到可能的最佳聚类,只能确保我们找到靠近放置点的最佳聚类。随机点并不能确保良好的表示,但是如果多次执行,在某个点随机放置点很有可能会产生良好的结果。
集群的不同起始位置会产生不同的结果
因此,我们将随机点放入坐标空间中。没有理由将它们放在现有数据点的最小值和最大值之外,所以介于两者之间。
随机生成的聚类点在现有点的范围内生成
import random
import numpy
x_coor = [data_point[0] for data_point in data_points]
range_x = (min(x_coor), max(x_coor))
y_coor = [data_point[1] for data_point in data_points]
range_y = (min(y_coor), max(y_coor))
print(f"range X: {range_x}")
print(f"range Y: {range_y}")
ranges = [range_x, range_y]
n_clusters = 2
n_dimensions = len(ranges)
random_cluster_points = numpy.random.rand(n_dimensions, n_clusters)
for index, cluster_point in enumerate(random_cluster_points):
range_diff = ranges[index][1] - ranges[index][0]
random_cluster_points[index] = cluster_point*range_diff + ranges[index][0]
print(f"Clusters: {clusters}")
下一步是在集群之间分配每个原始数据点。数据点属于最能代表它的集群。最好的表示是与数据点最相似的集群,并使用相似性方法进行测量。在这个例子中,我们将使用欧几里得。
通过计算到每个点的距离并选择最接近的一个来确定每个点与哪个集群最相似
import numpy
cluster_data_points = [[] for _ in clusters]
for data_point in data_points:
distance_to_clusters = [dist_func(cluster, numpy.transpose(data_point)) for cluster in clusters]
closest_cluster_index = distance_to_clusters.index(min(distance_to_clusters))
cluster_data_points[closest_cluster_index] += [data_point]
计算每个数据点最接近哪个集群
在分布数据点之后是 K-means 聚类的“均值”部分。“平均值”是指一个集群应该如何成为它所代表的数据点的平均值。聚类可能不是分布后的平均值,因为它们仅代表最近的数据点。因此,有必要移动每个集群,将其位置更改为其数据点的平均值。
每个集群都更新为最接近它的数据点的“平均值”
计算集群 j 的平均值的公式,其中包含最接近它的点。
import numpy
cluster_mean = [numpy.mean(cluster_data_points, axis=0) for cluster_data_points in clusters_data_points]
代码计算每个集群的新位置作为最接近它的数据点的平均值。
一个簇可能更靠近其新位置的其他数据点。再次计算分布对于确保每个集群代表正确的数据点是必要的。
重新计算哪个点属于哪个集群并将集群移动到它们的新均值
while True
clusters_data_points = split_data_points_between_clusters(clusters, data_points, Similarity.Euclidean)
new_clusters = calc_mean_clusters(clusters_data_points)
if clusters == new_clusters:
break
clusters = new_clusters
print(f"Clusters: {clusters}")
K-means 聚类是一个迭代过程。这意味着我们无法在一次计算中找到每个集群的完美位置。它需要我们多次计算。这个迭代过程一直持续到集群不移动或直到它低于阈值。阈值确保该过程不会无限期地继续。
为了简易计算,SK-Learn 发布了一个强大的 K-means 聚类实现:
from sklearn import cluster
clusters = cluster.KMeans(n_clusters=n_clusters).fit(data_points).cluster_centers_
print(clusters)
搜索小程序:AI人工智能工具,体验不一样的AI工具