· 6 years ago · Mar 15, 2020, 10:06 AM
1import numpy as np
2import re
3
4import nltk
5from nltk.tokenize import word_tokenize
6from nltk.corpus import stopwords
7import enchant
8import pymorphy2
9
10nltk.download('stopwords')
11nltk.download('punkt')
12
13import gensim
14import gensim.downloader as api
15from gensim.models import Word2Vec
16
17from tqdm import tqdm
18
19#morph_analyzer = MorphAnalyzer()
20#model_ruscorpora = api.load('word2vec-ruscorpora-300')
21
22def get_word_embedding(word):
23 if word in model.wv.vocab: return model.wv[word]
24 else: return np.nan
25def get_word_embedding_ruscorpora(word):
26 if word in model_ruscorpora.vocab: return model_ruscorpora[word]
27 else: return np.nan
28
29class GetModel:
30 def __init__(self, model):
31 self.model = model # Сюда грузить модель
32
33 # Представление слова в виде вектора w2v
34 def get_word_embedding(self, word):
35 if word in self.model.wv.vocab: return np.array(model.wv[word])
36 else: return np.nan
37
38 # Представление слова в виде вектора ruscorpora
39 def get_word_embedding_ruscorpora(self, word):
40 if word in self.model.vocab: return np.array(model[word])
41 else: return np.nan
42
43 # получение среднего вектора сообщения
44 def __get_avg_vector(self, msg):
45 vectors = []
46 try:
47 for word in msg:
48 vectors.append(self.get_word_embedding(word))
49 except:
50 for word in msg:
51 vectors.append(self.get_word_embedding_ruscorpora(word))
52
53 vectors = np.array(vectors)
54 vectors = vectors[vectors != np.nan]
55 msg_vector = vectors.mean()
56
57 return msg_vector
58
59 # загрузка классов действий действий
60 def get_actions_vectors(self, actions):
61 self.actions = {}
62 for key, items in actions.items():
63 arr = []
64 for item in items:
65 print(item)
66 arr.append(self.__get_avg_vector([word for word in self.__preprocess_messages(item)]))
67 self.actions[key] = arr
68 print('Ok')
69
70
71 def __calculate_euclidean(self, v1, v2):
72 return ((v1-v2)**2).sum()
73
74 # нахождение наилучшего сходства
75 def get_closest_class(self, msg):
76 closest_table = {}
77 msg = self.__get_avg_vector(msg)
78 for key, items in self.actions.items():
79 for i, item in enumerate(items):
80 closest_table[key+'_'+str(i)] = self.__calculate_euclidean(item, msg)
81
82 least = 9999999999999
83 least_key = ''
84 for key, item in closest_table.items():
85 if item < least:
86 least = item
87 least_key = key
88 return least_key.split('_')[0]
89
90
91 def __lemmatize(self, word): #приводим слова в нормальную форму
92 morph = pymorphy2.MorphAnalyzer()
93 parse = morph.parse(word)[0]
94 return(parse.normal_form)
95
96 def __tokenize(self, text): #разбиваем текст на слова
97 if type(text) == str:
98 sentences = nltk.sent_tokenize(text)
99 words = []
100 for sentence in sentences:
101 words.extend(nltk.word_tokenize(sentence))
102 return words
103 else: return ''
104
105 # Полная обработка текста
106 def __preprocess_messages(self, batch):
107 stop_words = set(stopwords.words("russian"))
108 without_stop_words = [self.__lemmatize(word) for word in self.__tokenize(batch) if not word in stop_words and word.isalnum()]
109 out = self.__check_grammar(without_stop_words)
110 return out
111
112 # Проверяет грамматику слов в массиве
113 def __check_grammar(self, batch):
114 d = enchant.Dict('ru_RU')
115 for i in range(len(batch)):
116 if(not d.check(batch[i])):
117 batch[i] = d.suggest(batch[i])[0]
118 return batch
119
120
121actions = {
122 'перевод_токенов':['перевод токенов'],
123 'баланс':['баланс', 'сколько денег'],
124 'перевод_суммы':['перевести сумму'],
125 'сжечь':['сжечь', 'удали все деньги'],
126 'thrash':['какая погода', 'как дела', 'что делаешь', 'как зовут']
127 }
128
129
130text_model = api.load('word2vec-ruscorpora-300')
131msg = 'сколько у меня денег'
132obj = GetModel(text_model)
133obj.get_actions_vectors(actions)
134obj.get_closest_class(msg)