Кластеризация текста в MATLAB

Я хочу выполнить иерархическую агломеративную кластеризацию текстов в MATLAB. Скажем, у меня есть четыре предложения,

I have a pen.
I have a paper. 
I have a pencil.
I have a cat. 

Я хочу сгруппировать приведенные выше четыре предложения, чтобы увидеть, какие из них более похожи. Я знаю, что в наборе инструментов Statistic есть такая команда, как pdist для измерения попарных расстояний, linkage для вычисления сходства кластеров и т. д. Простой код, например:

X=[1 2; 2 3; 1 4];
Y=pdist(X, 'euclidean');
Z=linkage(Y, 'single');
H=dendrogram(Z)

отлично работает и возвращает дендрограмму.

Интересно, могу ли я использовать эту команду для текстов, как я упоминал выше. Есть предположения ?


ОБНОВЛЕНИЯ:

Спасибо Амро. Читать Понял и вычислил расстояние между строками. Код следует:

clc
S1='I have a pen'; % first String

f_id=fopen('events.txt','r'); %saved strings to compare with
events=textscan(f_id, '%s', 'Delimiter', '\n');
fclose(f_id); %close file.
events=events{1}; % saving the text read.

ii=numel(events); % selects one text randomly.
% store the texts in a cell array

for kk=1:ii

   S2=events(kk);
   S2=cell2mat(S2);
   Z=levenshtein_distance(S1,S2);
   X(kk)=Z;

end 

Я ввел строку, и у меня было 4 сохраненных строки. Теперь я вычислил попарное расстояние, используя функцию levenshtein_distance. Он возвращает матрицу X=[ 17 0 16 18 16].

** Думаю, это моя парная матрица расстояний. Подобно тому, что делает pdist. Это ?

** Теперь я пытаюсь ввести X, чтобы вычислить связь, например

Z=linkage(X, 'single);

Вывод, который я получаю:

Ошибка при использовании связи ==> в 93. Размер Y несовместим с выходными данными функции PDIST.

Ошибка в ==> Untitled2 в 20 Z=linkage(X,'single') .

Почему так ? Можно ли вообще использовать функцию связи? Помощь приветствуется.

ОБНОВЛЕНИЕ 2

clc
S1='I have a pen';

f_id=fopen('events.txt','r');
events=textscan(f_id, '%s', 'Delimiter', '\n');
fclose(f_id); %close file.
events=events{1}; % saving the text read.

ii=numel(events)+1; % total number of strings in the comparison

D=zeros(ii, ii); % initialized distance matrix;
for kk=1:ii 

    S2=events(kk);

    %S2=cell2mat(S2);

    for jk=kk+1:ii

  D(kk,jk)= levenshtein_distance(S1{kk},S2{jk});

    end

end

D = D + D';       %'# symmetric distance matrix

%# linkage expects the output format to match that of pdist,
%# so we convert D to a row vector (lower/upper part of matrix)
D = squareform(D, 'tovector');

T = linkage(D, 'single');
dendrogram(T).

Ошибка: ??? Ссылка на содержимое ячейки из объекта массива, не являющегося ячейкой. Ошибка в ==> Untitled2 на 22 D(kk,jk)= levenshtein_distance(S1{kk},S2{jk});

Кроме того, почему я читаю событие из файла внутри первого цикла? Не кажется логичным. Немного запутался, могу ли я работать таким образом, или единственное решение - ввести все строки внутри кода. Помощь очень ценится.

ОБНОВЛЕНИЕ

код для сравнения двух предложений:

clc
    str1 = 'Fire in NY';
    str2= 'Jeff is sick';

D=levenshtein_distance(str1,str2);
D = D + D';       %'# symmetric distance matrix

%# linkage expects the output format to match that of pdist,
%# so we convert D to a row vector (lower/upper part of matrix)

%D = squareform(D, 'tovector');

T = linkage(D, 'complete');
[H,P] = dendrogram(T,'colorthreshold','default');  

Выход D=18.

С разными строками:

clc
str1 = 'Fire in NY';
str2= 'NY catches fire';

D=levenshtein_distance(str1,str2);
D = D + D';       %'# symmetric distance matrix

%# linkage expects the output format to match that of pdist,
%# so we convert D to a row vector (lower/upper part of matrix)

%D = squareform(D, 'tovector');

T = linkage(D, 'complete');
[H,P] = dendrogram(T,'colorthreshold','default'); 

D=28.

В зависимости от расстояния абсолютно разные предложения выглядят одинаково. Что я пытаюсь сделать? Если я сохранил Fire в Нью-Йорке, я не буду хранить NY catches fire. Однако для первого случая я бы сохранил, поскольку информация новая.

Достаточно ли LD для этого? Помощь приветствуется.


person Tinglin    schedule 05.09.2010    source источник
comment
Все еще ищу и читаю, чтобы сделать код. Я понял, что A=double(B), преобразует строку B в ее эквивалентные векторы A. Итак, я создал векторы для предложений и, наконец, поместил их все в матрицу. Теперь я мог использовать команды Matlab.   -  person Tinglin    schedule 05.09.2010
comment
О, парень ! Работает только тогда, когда предложения имеют одинаковую длину. Не могу вспомнить, как заставить все матрицы иметь одинаковый размер с нулевым заполнением.   -  person Tinglin    schedule 05.09.2010
comment
пожалуйста, найдите время, чтобы правильно отформатировать код (когда вы редактируете вопрос, выделите часть кода и нажмите кнопку образца кода [ту, что с 0 и 1])   -  person Amro    schedule 06.09.2010
comment
@ Амро. Спасибо за совет по редактированию. Теперь выглядит намного лучше. Просто рад узнать так много вещей.   -  person Tinglin    schedule 06.09.2010


Ответы (1)


Что вам нужно, так это функция расстояния, которая может обрабатывать строки. Проверьте расстояние Левенштейна (изменить расстояние). Существует множество реализаций:

В качестве альтернативы вы должны извлечь некоторые интересные функции (например, количество гласных, длину строки и т. д.), чтобы построить представление векторного пространства, а затем вы можете применить любую из обычных мер расстояния (евклидово, ...) к новому представление.


ИЗМЕНИТЬ

Проблема с вашим кодом заключается в том, что LINKAGE ожидает, что формат входных расстояний будет соответствует PDIST, а именно вектору-строке, соответствующему к парам наблюдений в порядке 1-против-2, 1-против-3, 2-против-3 и т. д., что в основном является нижней половиной полной матрицы расстояний (поскольку предполагается, что она симметрична как dist(1,2) == dist(2,1))

%# instances
str = {'I have a pen.'
    'I have a paper.'
    'I have a pencil.'
    'I have a cat.'};
numStr = numel(str);

%# create and fill upper half only of distance matrix
D = zeros(numStr,numStr);
for i=1:numStr
    for j=i+1:numStr
        D(i,j) = levenshtein_distance(str{i},str{j});
    end
end
D = D + D';       %'# symmetric distance matrix

%# linkage expects the output format to match that of pdist,
%# so we convert D to a row vector (lower/upper part of matrix)
D = squareform(D, 'tovector');

T = linkage(D, 'single');
dendrogram(T)

Пожалуйста, обратитесь к документации по рассматриваемым функциям для получения дополнительной информации...

person Amro    schedule 05.09.2010
comment
L.distance отличается от HAC, не так ли? Я ищу только HAC. Я не смог найти, извлекает ли HAC вектор с помощью какой-либо специальной функции. Могу ли я конвертировать тексты в вектор (все без символов)? Любые подсказки о том, как построить векторное пространство? - person Tinglin; 05.09.2010
comment
Расстояние Левенштейна — это не алгоритм кластеризации, а функция расстояния между двумя строками. Это необходимо, потому что иерархическая кластеризация начинается с вычисления матрицы расстояний между всеми парами экземпляров PDIST, а затем начинается их объединение в восходящем подходе (агломеративном) LINKAGE - person Amro; 05.09.2010
comment
Я просто читаю ссылку, которую вы дали. будет обновлять на то, что я мог бы сделать. Спасибо Амро. - person Tinglin; 05.09.2010
comment
Просто прочитал документы и понял. скопировал код и запустил тоже. Если я правильно понимаю, первый цикл принимает одну строку за раз, а второй цикл сравнивает ее с остальными. Я определил одну строку как S1 и хочу прочитать другие из файла. Я обновляю код, который я только что отредактировал в соответствии с вашим кодом. У меня ошибка, и мне интересно, могу ли я сделать это или нет. Большое спасибо и помощь приветствуется. - person Tinglin; 06.09.2010
comment
@Tinglin: что ты пытаешься сделать? иерархическая кластеризация берет все экземпляры и вычисляет их расстояния друг от друга (а не один в частности против всех остальных), а затем группирует похожие экземпляры вместе, чтобы сформировать кластеры. Что касается цикла, он будет сравнивать экземпляр в порядке, который я объяснил ранее: 1-против-2, 1-против-3, 1-против-4, 2-против-3, 2-против-4 и 3-против-4 (в основном все возможные неупорядоченные пар) - person Amro; 06.09.2010
comment
@ Амро. Я ясно понял, что вы объяснили. Я просто пытаюсь сказать: у меня есть одна строка (S1). В файле я предварительно сохранил 4 строки (S2, S3, S4, S5). Предположим, что они не могли быть сгруппированы ранее или могут быть сгруппированы. Я хотел бы сравнить (S1-S2) (S1-S3) (S1-S4) (S1-S5), чтобы увидеть, может ли S1 быть кластером с любой из четырех строк. Если да, я бы заменил, скажем, S2 на S1 и сохранил файл. возможный ? Пример: У меня ручка заменит предыдущий у меня карандаш. или крах фондовой биржи заменит крах фондовой биржи. Или вся концепция неверна? Большое спасибо. - person Tinglin; 06.09.2010
comment
@Tinglin: Боюсь, я не понимаю твоей логики. Весь смысл кластеризации в том, что она обнаруживает внутреннюю группировку ваших данных. Это означает, что при наличии набора экземпляров (в вашем случае строк) он сгруппирует их для вас таким образом, что похожие экземпляры будут размещены вместе (или, в данном случае, иерархия групп). Может быть полезно, если вы прочитаете дополнительную информацию по этому вопросу: en.wikipedia.org/wiki/Cluster_analysis# Иерархическая_кластеризация - person Amro; 06.09.2010
comment
@ Амро. Я прочитал все документы, которые у меня были, и вики. Я думаю, что мне нужно изменить то, что я пытаюсь сделать, и вот оно: я получил информацию S1 = «У меня есть ручка». Я сохранил его в компьютере. Теперь я получил новую информацию S2='У меня есть карандаш'. Прежде чем сохранить S2, я хочу определить, является ли S2 таким же/похожим на S1? Если да, я либо хочу урезать S2, либо заменить S1 на S2. Но если я нахожу, что S2 сильно отличается от S1. Я тоже храню S2. HAC группирует похожие элементы, но я не думаю, что это подходит для моего сценария. также ЛД. Посмотрите на код. Спасибо. - person Tinglin; 06.09.2010
comment
@Tinglin: Очевидно, что кластеризация не подходит для вашей проблемы. Тем не менее, это слишком расплывчато: как бы вы определили, похожи/различны ли две строки? Возможно, вам следует опубликовать новый вопрос, но обязательно четко объясните задачу, которую вы пытаетесь выполнить (основываясь на вашем описании, я подозреваю, что вы сами не уверены в концепции!) - person Amro; 06.09.2010
comment
@ Амро, ты совершенно прав. Я все еще обдумываю концепцию и дорабатываю. Я придумал достойный и разместил новый Вопрос. LD работает до некоторой степени, хотя. Еще раз спасибо. - person Tinglin; 07.09.2010
comment
Я ссылаюсь на ваш новый вопрос для потомков: stackoverflow.com/questions/3655612/ - person Amro; 07.09.2010