我希望能够使用最近邻来尝试在具有连续、分类和文本特征的数据集中找到与样本子类(认为已处理与未处理)最相似的样本。
玩具数据集:
import numpy as np
import pandas as pd
from sklearn.preprocessing import OneHotEncoder, QuantileTransformer
from sklearn.neighbors import NearestNeighbors
from sklearn.compose import ColumnTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.decomposition import TruncatedSVD
np.set_printoptions(suppress=True)
a = [20, 100, 10000, 500]
b = [1, 2, 3, 2]
c = ['dog', 'cat', 'foo', 'cat']
d = ['apple apple fruit',
'mercedes bmw chevrolet',
'monster dragon snake',
'mercedes chevrolet bmw buick']
z = [a,b,c,d]
names = {0: 'col1', 1:'col2', 2:'col3', 3:'col4'}
X = pd.DataFrame(z).T
X = X.rename(names, axis='columns')
X
将创建:
col1 col2 col3 col4
0 20 1 dog apple apple fruit
1 100 2 cat mercedes bmw chevrolet
2 10000 3 foo monster dragon snake
3 500 2 cat mercedes chevrolet bmw buick
正如我们所见,样本 1 和 3 是最相关的。它们有许多相同的词汇表,共享两个标签(col2 + col3),并且考虑到 col1 的分布,它们非常接近。我们将它们转换为特征数组并要求最近的邻居,如下所示:
numeric = ['col1']
numeric_transformer = Pipeline(steps=[('scaler', QuantileTransformer())])
cat = ['col2', 'col3']
cat_transformer = Pipeline(steps=[('onehot', OneHotEncoder())])
text = ['col4']
text_transformer = Pipeline(steps=[('tfidf', TfidfVectorizer()),
('svd', TruncatedSVD(n_components=2))])
prep = ColumnTransformer(transformers=[('num', numeric_transformer, numeric),
('cat', cat_transformer, cat),
('text', text_transformer, 'col4')], sparse_threshold=0)
X_transformed = prep.fit_transform(X)
nn = NearestNeighbors(n_neighbors=2)
nn.fit(X_transformed)
d, i = nn.kneighbors(X_transformed[1].reshape(1,-1))
i
正确返回array([[1, 3]], dtype=int64)1 表示自匹配,3 表示最近的邻居。
但是在跨越 100 多个维度的真实数据集上,我应该使用自定义距离函数吗?对于使用 sklearn 的最近邻居,如果该列是文本列之一,我们可以使用余弦距离,另一个跨高维热编码变量的距离,以及另一个使用实际连续变换变量 (col1) 的距离计算。
但这是.... hacky吗?没有这个,有没有办法处理最近邻居搜索的异构数据?我担心我关于如何对这三种变量中的每一种进行加权的决定会使最终结果非常主观并容易受到批评。