在数据科学领域,经常需要在一组向量中选择一个子集进行操作或分析。这种操作通常称为“打包”。为了在数学上充分描述打包的过程,我们需要引入一个名为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/