在数据科学领域,经常需要在一组向量中选择一个子集进行操作或分析。这种操作通常称为“打包”。为了在数学上充分描述打包的过程,我们需要引入一个名为Steinitz序列的数学工具。
Steinitz序列不仅能够描述打包的过程,还能够被应用于解决很多其他的问题。在这里,我们将重点介绍使用Steinitz序列进行打包的方法。
首先,让我们来看一下如何使用Steinitz序列进行排序。在下面的代码中,我们将创建一个由向量组成的列表,然后对它们进行排序。
“`python
import pandas as pd
import numpy as np
import itertools
import scipy.spatial.distance as ssd
from collections import defaultdict
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
# create a list of vectors
vectors = []
for i in range(10):
random_vector = np.random.rand(10)
vectors.append(random_vector)
# create a distance matrix between all vectors
distance_matrix = ssd.squareform(ssd.pdist(vectors))
# create a hierarchical clustering of the vectors
linkage = ssd.linkage(distance_matrix)
# plot the dendrogram of the hierarchical clustering
sns.set(style=’white’)
plt.figure(figsize=(10, 7))
plt.title(‘Hierarchical Clustering Dendrogram’)
plt.xlabel(‘sequence index’)
plt.ylabel(‘distance’)
dendrogram = ssd.dendrogram(linkage)
plt.show()
“`
这段代码将生成一个以向量索引为横坐标、向量距离为纵坐标的谱系图(Dendrogram),它可以帮助我们确定如何对向量进行排序。我们可以通过删除其中的节(或子树)来对向量进行排序。
“`python
subtrees = defaultdict(list)
for idx, d in zip(dendrogram[‘icoord’], dendrogram[‘dcoord’]):
if d[1] – d[0] < 0:
subtree = idx[:2]
direction = idx[0] < idx[2]
subtrees[subtree].append(direction)
sorted_vectors = []
for subtree, directions in subtrees.items():
subtree_indices = [int(i) for i in subtree]
subtree_vectors = [vectors[i] for i in subtree_indices]
while len(subtree_vectors) > 1:
combo = list(itertools.combinations(subtree_vectors, 2))
combo_dists = [distance_matrix[subtree_indices.index(i),subtree_indices.index(j)] for i, j in combo]
closest_index = combo_dists.index(min(combo_dists))
new_vector = np.mean(combo[closest_index], axis=0)
del subtree_vectors[combo[closest_index].index]
del combo[closest_index]
combo_dists.pop(closest_index)
new_index = subtree_indices.pop(combo[closest_index].index)
subtree_indices.append(new_index)
subtree_vectors.append(new_vector)
sorted_vectors.extend(subtree_vectors)
# create a DataFrame to visually assess the sorted vectors
df = pd.DataFrame(sorted_vectors)
df.head()
“`
使用这种方法,我们可以在垂直方向上选择不同的剪枝点来选择不同的向量子集,并进行排序。对于打包向量来说,这个工具更加强大。如果我们选择了两个向量,则取它们之间的加权平均向量作为新的向量。我们就可以用以下方法对向量进行打包了。
“`python
def steinitz_pack(vectors, max_iterations):
distance_matrix = ssd.squareform(ssd.pdist(vectors))
for i in range(max_iterations):
indexes = [x for x in range(0, len(vectors))]
combos = list(itertools.combinations(indexes, 2))
combo_dists = [distance_matrix[i,j] for i, j in combos]
closest_index = combo_dists.index(min(combo_dists))
new_vector = np.mean([vectors[i] for i in combos[closest_index]], axis=0)
idx_to_delete = combos[closest_index][0]
vectors.pop(idx_to_delete)
vectors[combos[closest_index][1]] = new_vector
distance_matrix = ssd.squareform(ssd.pdist(vectors))
return vectors
packed_vectors = steinitz_pack(vectors, 3)
# create a DataFrame to visually assess the packed vectors
df = pd.DataFrame(packed_vectors)
df.head()
“`
使用这种方法,我们可以选择一个数量少得多的向量集合来代表原始向量集合,并且在这个新的向量集合上执行进一步的操作。这个方法是一个高效、简洁的方式来对大量向量进行操作,尤其是当我们有很多重复或相关向量时。在数据科学应用中使用Steinitz序列进行打包,是一个有效地保持高维向量空间结构、减少冗余向量的方法。
了解更多有趣的事情:https://blog.ds3783.com/