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