本期文章,我們對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
相似性和向量化
相似性的目标是找到相似的數據,當然數據都是經過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)
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!