Алгоритм группировки неструктурированного текста - PullRequest
0 голосов
/ 02 августа 2020

У меня много неструктурированных книжных данных, таких как:

Властелин колец Дж. Р. Р. Толкин

Толкин Властелин колец Хорошее состояние

Очень хорошее состояние Властелин колец младший Толкин

Гарри Поттер и волшебный камень в твердом переплете

Дж. К. Роулинг Гарри Поттер и волшебный камень

Камень Колдуна Боба Смита

Я пытаюсь выяснить, какие предложения представляют одну и ту же книгу. Например, первые 3 строки должны быть сгруппированы вместе («Властелин колец»), следующие 2 должны быть сгруппированы вместе (Гарри Поттер), а последняя строка - это отдельная группа («Камень чародея» Боба Смита). Какой хороший алгоритм для этого?

(Я добавил «Камень чародея Боба Смита» после первоначального вопроса, чтобы подчеркнуть, что простое сопоставление двух слов недостаточно различимо)

Ответы [ 3 ]

0 голосов
/ 03 августа 2020

Возможно это.

from gensim.models import Word2Vec
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd
from sklearn import cluster
from sklearn import metrics
from sklearn.decomposition import PCA
from scipy.cluster import hierarchy
from sklearn.cluster import AgglomerativeClustering

    
sentences = [["The Lord of the Rings J.R.R Tolkien"],
            ["Lord of the Rings Good condition"],
            ["Very good condition Lord of the Rings jrr Tolkien"],
            ["harry potter and the sorcerer's stone hardcover"],
            ["JK rowling harry potter and the sorcerer's stone"]]



m = Word2Vec(sentences, size=50, min_count=1, sg=1)

def vectorizer(sent, m):
    vec=[]
    numw=0
    for w in sent:
        try:
            if numw == 0:
                vec = m[w]
            else:
                vec = np.add(vec, m[w])
            numw += 1 
        except:
            pass
    return np.asarray(vec)/numw

l=[]
for i in sentences:
    l.append(vectorizer(i,m))
X=np.array(l)


n_clusters = 2
clf = KMeans(n_clusters=n_clusters,
             max_iter=100,
             init='k-means++',
             n_init=1)
labels=clf.fit_predict(X)
print(labels)
for index, sentence in enumerate(sentences):
    print(str(labels[index]) + ":" + str(sentence))

Результат:

0:['The Lord of the Rings J.R.R Tolkien']
0:['Lord of the Rings Good condition']
1:['Very good condition Lord of the Rings jrr Tolkien']
0:["harry potter and the sorcerer's stone hardcover"]
1:["JK rowling harry potter and the sorcerer's stone"]

KMeans почти наверняка не лучший способ кластеризации любых текстовых данных. Вы можете также взглянуть на другие алгоритмы кластеризации. В этом случае агломеративная кластеризация может быть более надежной.

Это интересно.

Например, если я изменю это ...

for index, metric in enumerate(["cosine", "euclidean", "cityblock"]):
    clf = AgglomerativeClustering(n_clusters=n_clusters,
                                    linkage="average", affinity=metric)

Я понял это .. .

1:['The Lord of the Rings J.R.R Tolkien']
0:['Lord of the Rings Good condition']
0:['Very good condition Lord of the Rings jrr Tolkien']
0:["harry potter and the sorcerer's stone hardcover"]
0:["JK rowling harry potter and the sorcerer's stone"]
0 голосов
/ 04 августа 2020

Если вас не беспокоит производительность (т.е. это может занять некоторое время), вы можете сравнить каждую строку друг с другом O (n ^ 2) и сгенерировать следующее:

  • самый длинный последовательный символ соответствует между 2 строками, игнорируя знаки препинания и заглавные буквы (т. е. сравнивать только [0-9A-Za-z], пропуская все остальные символы). (ключ)
  • длина указанной выше переменной. (оценка) Затем оценка будет определять, какие из «самых длинных совпадений строк» ​​оставить, а какие отбросить.

Учитывая ваш список книг:

  1. harry гончар и волшебный камень в твердом переплете
  2. Дж. К. Роулинг Гарри Поттер и волшебный камень
  3. Камень чародея Боба Смита

Книги 1 и 2 разделяют: " Гарри Поттер и камень волшебников "Книга 1 и 3 разделяют:" Колдун "Поскольку первая длиннее второй, книга 1 хранит только индексный ключ" Гарри Поттер и камень волшебников ".

Тогда мы сгруппируйте данные по этому ключу. Это будет довольно медленно (очень медленно для большого набора данных), но должно дать вам приличную точность.

0 голосов
/ 03 августа 2020

Я бы отфильтровал нейтральные слова (очень, хорошо, состояние, ...) и сопоставил названия на основе количества общих слов. Если вы определили инициалы, удалите точки. Для эффективного сравнения отсортируйте слова по алфавиту. Также все строчные буквы.

jrr lord rings tolkien

lord rings tolkien 

jrr lord rings tolkien

harry potter sorcerer stone

harry jk potter rowling sorcerer

Как минимум два слова должны совпадать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...