Код от Су Цзяньлиня
# - * - Кодирование:. 8 UTF - - * - от keras.layers Импорт слоя Импорт keras.backend K АС класса КРФ (слой): «» " чистый слой Keras для достижения CRF потери, по существу , слой с параметрами подготовки КРФ рассчитывается слой, слой CRF используется только для обучения модели, и вам необходимо создать прогностические модели, но все же обучен использовать матрицу передачи «» « DEF __init__ (Самостоятельно, ignore_last_label = False, ** kwargs): » «» ignore_last_label : определение того или не обращать внимания на последнюю метку, играть эффект маски «» " self.ignore_last_label = 1 IF ignore_last_label еще 0 Супер (CRF, Self).__init__ (** kwargs) ЗащитаПостроить (Self, input_shape): self.num_labels = input_shape [-1] - self.ignore_last_label self.trans = self.add_weight (имя = ' crf_trans ' , Shape = (self.num_labels, self.num_labels), инициализатор = ' glorot_uniform ' , обучаемый = True) DEF log_norm_step (Self, входы, государство): "" " рекурсивные вычисления нормализация фактор точка: 1, рекуррентное вычисление; 2, с переливом logsumexp избежать. советы: по expand_dims для выравнивания тензора. " "" Государства = K.expand_dims (государство [0], 2) # Предыдущих входы = K.expand_dims (входы, 2) # Это партитура времени метки, эмиссионный забьют Trans = K.expand_dims (self.trans, 0) # матрица передачи Выход = K.logsumexp (входы Штаты + Транс ,. 1) # индекс Х суммирований, журнал предотвратить переполнение обратного выхода, [выход] DEF path_score (Self, входы, этикетка): «» " целевые относительный путь вычисление вероятность (не нормируется) Основные моменты: счет-по-метка, вместе с вероятностью перехода баллом. Подсказка: используйте «предсказание» точку «цель» извлеченный пути забить гол. «» " # относится к метке в CRF оценка плюс вероятности перехода, и это оценка точки является эквивалент оценки тега (в том случае , действительно маркировать , чтобы просмотреть прогноз для реальных мест тегов общего балла) в качестве меток формы является [B, T, N], а в N этот размер составляет один горячий, # Здесь умножается на Pred, где это метка , соответствующее наличие выигрыша, остальные равна 0, а затем добавить второе измерение представляет собой значение 0 удаляется, а затем добавить метку указует на нахождение общего балла point_score = K.sum (K.sum (входы * метки, 2) ,. 1, keepdims = True) # по закладке балла, Shape [B] 1 ,. labels1 = K.expand_dims (метки [:, -1] ,. 3) # Shape [B ,. 1-Т, Н ,. 1] labels2 = K.expand_dims (Этикетки [: 1:.], 2) # Форма [. Б, Т - 1 ,. 1, N] , # здесь соответствует объекту , умноженное текущее время к времени передачи, которая определяется , что текущий момент времени от передачи этикетки с течением времени, поскольку метки в виде одной-горячей, так что только два измерения в конечный элемент равен 1, все остальные равно 0, флаг означает переход Этикетка = labels1 labels2 * # два смещение метки, ответственную за принятие формы целевого переноса оценки [B, T-1, N, N] из матрицы переноса транса = K.expand_dims (K.expand_dims (self.trans, 0 ), 0) #K.sum (транс * этикетка, [2 , 3]), так как в результате транс * этикетка [В, Т-1, N , N], но лишь позднее в двух измерениях со значением 1, оценка представляет собой передаточную trans_score K.sum = (K.sum (Trans * этикетки, [2 ,. 3]) ,. 1, keepdims = True) # получает вероятности все время переноса Т-1 Общий балл, K.sum (транс * этикетки, [ 2 3]), каждый раз , когда оценка представляет собой перенос возврата point_score + trans_score # две части партитуры и DEF вызовов (Self, входы): # сам CRF не изменяет выход, это только потеря возврата входы DEF Loss (Self, y_true, y_pred): # цель должна быть одна горячей y_pred формы маски 1-y_true =. [-1:., 1:,] ЕСЛИ self.ignore_last_label в остальном None y_true, y_pred =y_true [:,:,: self.num_labels], y_pred [:,:,: self.num_labels] init_states = [y_pred [: 0]] # начальное состояние log_norm, _, _ = K.rnn ( self.log_norm_step, y_pred [: 1:.], init_states, маска = маска) # вычисляет вектор Z (логарифмическая) Shape [batch_size, output_dim] log_norm = K.logsumexp (log_norm ,. 1, keepdims = True) # вычисляет Z (логарифмический) Форма [batch_size, 1] вычисляет общее path_score = self.path_score (y_pred, y_true) # вычисляет молекулу (логарифмический) обратный log_norm - path_score # т.е. лог (числитель / знаменатель) DEF Точность (Self, y_true, y_pred): # обучение процесс функция отображения кадра с точностью до кадра, исключая влияние маски маски = 1-y_true. [:,:, - 1.] ЕСЛИself.ignore_last_label остальное Отсутствует y_true, y_pred = y_true [:,:,: self.num_labels], y_pred [:,:,: self.num_labels] IsEqual = K.equal (K.argmax (y_true, 2), K.argmax (y_pred, 2 )) IsEqual = K.cast (IsEqual, ' float32 ' ) , если маска == Нет: вернуться K.mean (IsEqual) остальное : вернуть K.sum (IsEqual * маска) / K.sum (маска)