Классификация текстов на основе символов с тройной потерей - PullRequest
1 голос
/ 25 мая 2020

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

Для встраивания я следовал этому учебнику , а архитектура NN основана на этой статье .

Я создаю свои кодировки, используя:

max_char_len = 20
group_numbers = range(0, len(job_groups))
char_vocabulary = {'PAD':0}
X_char = []
y_temp = []
i = 1
for group, number in zip(job_groups, group_numbers):
   for job in group:
      job_cleaned = some_cleaning_function(job)
      job_enc = []
      for c in job_cleaned:
         if c in char_vocabulary.keys():
            job_enc.append(char_vocabulary[c])
         else:
            char_vocabulary[c] = i
            job_enc.append(char_vocabulary[c])
            i+=1
      X_char.append(job_enc)
      y_temp.append(number)
X_char = pad_sequences(X_char, maxlen = max_char_length, truncating='post')

Моя нейронная сеть настроена следующим образом:

def create_base_model():
  char_in = Input(shape=(max_char_length,), name='Char_Input')
  char_enc = Embedding(input_dim=len(char_vocabulary)+1, output_dim=20, mask_zero=True,name='Char_Embedding')(char_in)
  x = Bidirectional(LSTM(64, return_sequences=True, recurrent_dropout=0.2, dropout=0.4))(char_enc)
  x = Bidirectional(LSTM(64, return_sequences=True, recurrent_dropout=0.2, dropout=0.4))(x)
  x = Bidirectional(LSTM(64, return_sequences=True, recurrent_dropout=0.2, dropout=0.4))(x)
  x = Bidirectional(LSTM(64, return_sequences=False, recurrent_dropout=0.2, dropout=0.4))(x)
  out = Dense(128, activation = "softmax")(x)
  return Model(char_in, out)

def get_siamese_triplet_char():
  anchor_input_c = Input(shape=(max_char_length,),name='Char_Input_Anchor')
  pos_input_c = Input(shape=(max_char_length,),name='Char_Input_Positive')
  neg_input_c = Input(shape=(max_char_length,),name='Char_Input_Negative')

  base_model = create_base_model(encoding_generator)
  encoded_anchor = base_model(anchor_input_c)
  encoded_positive = base_model(pos_input_c)
  encoded_negative = base_model(neg_input_c)

  inputs = [anchor_input_c, pos_input_c, neg_input_c]
  outputs = [encoded_anchor, encoded_positive, encoded_negative]

  siamese_triplet = Model(inputs, outputs)
  siamese_triplet.add_loss((triplet_loss(outputs)))

  siamese_triplet.compile(loss=None, optimizer='adam')
  return siamese_triplet, base_model

Потеря триплета определяется следующим образом:

def triplet_loss(inputs):
   anchor, positive, negative = inputs
   positive_distance = K.square(anchor - positive)
   negative_distance = K.square(anchor - negative)
   positive_distance = K.sqrt(K.sum(positive_distance, axis=-1, keepdims = True))
   negative_distance = K.sqrt(K.sum(negative_distance, axis=-1, keepdims = True))
   loss = positive_distance - negative_distance
   loss = K.maximum(0.0, 1 + loss)
   return K.mean(loss)

Затем модель обучается с помощью:

    siamese_triplet_char.fit(x=
              [Anchor_chars_train, 
               Positive_chars_train, 
               Negative_chars_train],
              shuffle=True, batch_size=8, epochs=22, verbose=1)

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

Моя общая проблема заключается в том, что даже первая фаза показывает снижение стоимости, она превышает , и результаты проверки меняются, а вторая фаза терпит неудачу, как я ' m не может обучить модель классифицировать.

Мои вопросы следующие:

  1. Может ли кто-нибудь объяснить архитектуру встраивания? На что ссылается выходное измерение? Отдельные персонажи? Будет ли это вообще иметь смысл? Или есть лучший способ кодирования входных данных?
  2. Как я могу добавить validation_data в сеть, которая не содержит помеченных данных? Я мог бы использовать validation_split, но я бы предпочел передавать данные c для проверки, поскольку мои данные стратифицированы.
  3. Есть ли причина, по которой классификация не работает? Применение простого алгоритма K-Nearest Neighbor в лучшем случае дает точность 0,5! Это из-за данных? Или в моей системе есть систематическая ошибка c?

Мы очень ценим все идеи и предложения!

...