Сравнение двух матриц переходов
Есть текст: "аааааааааа аааааааааа аааааааааа аааааааааа аааааааааа аааааааааа аааааааааа аааааааааа аааааааааа аааааааааа вввввввввв вввввввввв вввввввввв вввввввввв вввввввввв вввввввввв вввввввввв вввввввввв вввввввввв вввввввввв".
Составляю матрицу переходов, которая имеет вид (далее именую - Исходная матрица):
state2 а в а аа в вв
state1
а 0.000000 0.000000 0.000000 0.046296 0.000000 0.000000
в 0.000000 0.000000 0.000000 0.000000 0.000000 0.046296
а 0.000000 0.000000 0.000000 0.037037 0.000000 0.009259
аа 0.046296 0.000000 0.046296 0.324074 0.000000 0.000000
в 0.000000 0.000000 0.000000 0.000000 0.000000 0.037037
вв 0.000000 0.046296 0.000000 0.000000 0.037037 0.324074
Тестируемые матрицы:
state2 а в а аа в вв
state1
а 0.000000 0.000000 0.000000 0.046296 0.000000 0.000000
в 0.000000 0.000000 0.000000 0.000000 0.000000 0.046296
а 0.000000 0.000000 0.000000 0.009259 0.000000 0.037037
аа 0.018519 0.018519 0.046296 0.287037 0.000000 0.000000
в 0.000000 0.000000 0.000000 0.018519 0.000000 0.018519
вв 0.027778 0.027778 0.000000 0.000000 0.037037 0.361111
state2 в г в вв г гг
state1
в 0.000000 0.000000 0.000000 0.037736 0.00000 0.000000
г 0.000000 0.000000 0.000000 0.000000 0.00000 0.056604
в 0.000000 0.000000 0.000000 0.028302 0.00000 0.000000
вв 0.018868 0.047170 0.028302 0.377358 0.00000 0.000000
г 0.000000 0.000000 0.000000 0.037736 0.00000 0.009434
гг 0.018868 0.009434 0.000000 0.000000 0.04717 0.283019
Здесь учитываются не только пары букв 'вв', 'aa', но также одиночные буквы с пробелом ' а', 'а '. Предположим, что у меня есть еще несколько подобных матриц созданных из других строк, например: "авававав ааа ввввв ава в ав ав ав авававааааа аааааааа вввввв" и т.д., назовем их матрицы для тестирования.
Вопрос, как найти одну из тестируемых матриц более "схожую" с исходной матрицей?
Не знаю как объяснить, но на выходе хотелось бы получить: 1 (тестируемая) матрица соответствует исходной на 30 %, 2 соответствует исходной на 15%. Если такое возможно. Или есть другие варианты.
Ответы (1 шт):
Предлагаю сначала привести все матрицы к единому векторному пространству (одинаковый набор столбцов), а потом посчитать косинусную схожесть полученных матриц.
Примеры входных данных (NOTE: в Pandas неудобно работать со столбцами, наимеование которых имеют пробелы в начале или в конце):
In [43]: a
Out[43]:
space_а space_в а_space аа в_space вв
space_а 0.000000 0.000000 0.000000 0.046296 0.000000 0.000000
space_в 0.000000 0.000000 0.000000 0.000000 0.000000 0.046296
а_space 0.000000 0.000000 0.000000 0.009259 0.000000 0.037037
аа 0.018519 0.018519 0.046296 0.287037 0.000000 0.000000
в_space 0.000000 0.000000 0.000000 0.018519 0.000000 0.018519
вв 0.027778 0.027778 0.000000 0.000000 0.037037 0.361111
In [44]: b
Out[44]:
space_в space_г в_space вв г_space гг
space_в 0.000000 0.000000 0.000000 0.037736 0.00000 0.000000
space_г 0.000000 0.000000 0.000000 0.000000 0.00000 0.056604
space_в 0.000000 0.000000 0.000000 0.028302 0.00000 0.000000
вв 0.018868 0.047170 0.028302 0.377358 0.00000 0.000000
г_space 0.000000 0.000000 0.000000 0.037736 0.00000 0.009434
гг 0.018868 0.009434 0.000000 0.000000 0.04717 0.283019
Вариант решения:
In [48]: a1 = a.assign(**dict.fromkeys(b.columns.difference(a.columns), 0)).sort_index(axis="columns")
In [49]: b1 = b.assign(**dict.fromkeys(a.columns.difference(b.columns), 0)).sort_index(axis="columns")
получили матрицы в едином векторном пространстве:
In [50]: a1
Out[50]:
space_а space_в space_г а_space аа в_space вв г_space гг
space_а 0.000000 0.000000 0 0.000000 0.046296 0.000000 0.000000 0 0
space_в 0.000000 0.000000 0 0.000000 0.000000 0.000000 0.046296 0 0
а_space 0.000000 0.000000 0 0.000000 0.009259 0.000000 0.037037 0 0
аа 0.018519 0.018519 0 0.046296 0.287037 0.000000 0.000000 0 0
в_space 0.000000 0.000000 0 0.000000 0.018519 0.000000 0.018519 0 0
вв 0.027778 0.027778 0 0.000000 0.000000 0.037037 0.361111 0 0
In [51]: b1
Out[51]:
space_а space_в space_г а_space аа в_space вв г_space гг
space_в 0 0.000000 0.000000 0 0 0.000000 0.037736 0.00000 0.000000
space_г 0 0.000000 0.000000 0 0 0.000000 0.000000 0.00000 0.056604
space_в 0 0.000000 0.000000 0 0 0.000000 0.028302 0.00000 0.000000
вв 0 0.018868 0.047170 0 0 0.028302 0.377358 0.00000 0.000000
г_space 0 0.000000 0.000000 0 0 0.000000 0.037736 0.00000 0.009434
гг 0 0.018868 0.009434 0 0 0.000000 0.000000 0.04717 0.283019
теперерь их можно сравнить:
In [52]: from sklearn.metrics.pairwise import cosine_similarity
In [53]: cs = cosine_similarity(a1, b1)
результат:
In [54]: cs
Out[54]:
array([[0. , 0. , 0. , 0. , 0. , 0. ],
[1. , 0. , 1. , 0.9883323 , 0.9701425 , 0. ],
[0.97014404, 0. , 0.97014404, 0.95882469, 0.94117797, 0. ],
[0. , 0. , 0. , 0.0031349 , 0. , 0.00416043],
[0.70710678, 0. , 0.70710678, 0.69885647, 0.68599434, 0. ],
[0.98900701, 0. , 0.98900701, 0.98874614, 0.95947774, 0.00498942]])
Идея косинусной схожести в измерении косинуса угла между двумя векторами (векторы могут быть многомерными). Как известно из курса школьной тригонометрии, косинус угла 0 градусов равен 1, а для угла 90 градусов - 0. Т.е. вектора, заданные координатами (в векторном или матричном виде) и такие, что у них совпадают все координаты дадут косинусное сходство - 1, а два вектора, у которых нет ни одного совпадения дадут косинусное сходство - 0. Чем больше сходство тем ближе косинусное сходство к единице, чем меньше - ближе к нулю.
PS если сравнивать много векторов/матриц, то сначала необходимо привести к единому векторному пространству все вектора.