Скажем, у меня есть список списков слов, например
[['apple','banana'],
['apple','orange'],
['banana','orange'],
['rice','potatoes','orange'],
['potatoes','rice']]
Набор намного больше. Я хочу сгруппировать слова, которые, как правило, существуют вместе, будут иметь один и тот же кластер. Таким образом, в этом случае кластеры будут ['apple', 'banana', 'orange']
и ['rice','potatoes']
.
Каков наилучший подход к архивированию такого рода кластеризации?
Итак, после многих проблем в Googling, я понял, что я, по сути, не могу использовать методы кластеризации, потому что мне не хватает функциональных переменных, на которых я могу скопировать слова. Если я создаю таблицу, где я отмечаю, как часто каждое слово существует с другими словами (фактически декартовым произведением), на самом деле является матрицей смежности, и кластеризация на нем не работает.
Итак, решение, которое я искал, - это обнаружение сообщества. Я использовал библиотеку igraph (или python python-ipgraph wrapper), чтобы найти кластеры, и она работает очень хорошо и быстро.
Дополнительная информация:
Я думаю, что более естественно думать о проблеме как о графике.
Например, вы можете предположить, что apple
- это узел 0, а banana
- это узел 1, а первый список указывает, что существует край от 0 до 1.
поэтому сначала преобразуйте метки в числа:
from sklearn.preprocessing import LabelEncoder
le=LabelEncoder()
le.fit(['apple','banana','orange','rice','potatoes'])
сейчас:
l=[['apple','banana'],
['apple','orange'],
['banana','orange'],
['rice','potatoes'], #I deleted orange as edge is between 2 points, you can transform the triple to 3 pairs or think of different solution
['potatoes','rice']]
преобразовать метки в числа:
edges=[le.transform(x) for x in l]
>>edges
[array([0, 1], dtype=int64),
array([0, 2], dtype=int64),
array([1, 2], dtype=int64),
array([4, 3], dtype=int64),
array([3, 4], dtype=int64)]
теперь начните строить график и добавьте ребра:
import networkx as nx #graphs package
G=nx.Graph() #create the graph and add edges
for e in edges:
G.add_edge(e[0],e[1])
теперь вы можете использовать функцию connected_component_subgraphs
для анализа связанных вершин.
components = nx.connected_component_subgraphs(G) #analyze connected subgraphs
comp_dict = {idx: comp.nodes() for idx, comp in enumerate(components)}
print(comp_dict)
выход:
{0: [0, 1, 2], 1: [3, 4]}
или же
print([le.inverse_transform(v) for v in comp_dict.values()])
выход:
[array (['apple', 'banana', 'orange']), array (['potatoes', 'rice'])]
и это ваши 2 кластера.
Будет более целесообразным искать частые наборы предметов вместо этого.
Если вы скопируете такие короткие слова, все будет соединено, как правило, несколькими уровнями: ничего общего, один общий элемент, два общих элемента. Это слишком грубо, чтобы его можно было использовать для кластеризации. Вы получите все или ничего не связанное, и результаты могут быть очень чувствительны к изменениям и упорядочению данных.
Таким образом, отказавшись от парадигмы разделения данных, вместо этого обратите внимание на частые комбинации.