ИИ: глубокое обучение для обработки текста

искусственный интеллект

В другой статье, опубликованной вместе с этой статьей, BlueDot, компания, занимающаяся использованием искусственного интеллекта для защиты людей во всем мире от инфекционных заболеваний, выпустила раннее предупреждение за неделю, когда вспышка еще не привлекла пристального внимания. Какая драгоценная неделя!

Их система раннего предупреждения ИИ использует глубокое обучение для обработки текста.Эта система фиксирует сотни тысяч информации, полученной из большого количества новостей, публичных заявлений и т. д. в Интернете, и обрабатывает естественный язык.Сегодня мы поговорим о глубине. как делать простые манипуляции с текстом.

Text, String или Text — это последовательность символов или последовательность слов, и наиболее распространенным является обработка слов (китайский язык мы пока не рассматриваем, понимание и обработка китайского языка намного сложнее, чем понимание и обработка китайского языка). Английский). Компьютеры — это затвердевшая математика, а обработка текста — это, по сути, затвердевшая статистика Таким образом, многие простые задачи могут быть решены с помощью статистических моделей. Давайте начнем.

Обработка текстовых данных

В соответствии с предыдущим, если исходные данные для обучения не являются вектором, нам нужно векторизовать текст, Есть несколько способов:

  • разделить по словам
  • Разделить по символам
  • Извлечь n-грамм слов

Я люблю есть огонь... угадай, что я скажу дальше? 1-грамм может дальше сказать что угодно, и это слово не имеет ничего общего с предыдущим текстом; 2-грамм может сказать "рука, дрова, пламя" и т. д., чтобы образовать слова "факел, спичка, пламя"; 3- грамм может сказать «горшок», образуя «поедание горячего горшка», эта вероятность выше. Давайте поймем это просто, n-грамма связана с первыми n-1 словами.

Сегодня мы засыпаем яму, выкопанную ранее.В то время мы говорили, что в будущем будет введено одно горячее.Сейчас самое время.

однократное кодирование

def one_hot():
​    samples = ['The cat sat on the mat', 'The dog ate my homework']
    token_index = {}
    # 分割成单词
    for sample in samples:
        for word in sample.split():
            if word not in token_index:
                token_index[word] = len(token_index) + 1
    # {'The': 1, 'cat': 2, 'sat': 3, 'on': 4, 'the': 5, 'mat.': 6, 'dog': 7, 'ate': 8, 'my': 9, 'homework.': 10}
    print(token_index)
 
    max_length = 8
    results = np.zeros(shape=(len(samples), max_length, max(token_index.values()) + 1))
    for i, sample in enumerate(samples):
        for j, word in list(enumerate(sample.split()))[:max_length]:
            index = token_index.get(word)
            results[i, j, index] = 1.
​
    print(results)

结果

Мы видим, что эти данные не очень хороши. И мат, и домашнее задание сопровождаются английским предложением '.'. Хотите показать свои навыки и написать сложное регулярное выражение для соответствия этому необъяснимому символу? Конечно нет, да, в Keras есть встроенные методы.

def keras_one_hot():
    samples = ['The cat sat on the mat.', 'The dog ate my homework.']
    tokenizer = Tokenizer(num_words=1000)
    tokenizer.fit_on_texts(samples)
    sequences = tokenizer.texts_to_sequences(samples)
    print(sequences)
    one_hot_results = tokenizer.texts_to_matrix(samples, mode='binary')
    print(one_hot_results)
    word_index = tokenizer.word_index
    print(word_index)
    print('Found %s unique tokens.' % len(word_index))

结果

num_words здесь и max_length выше используются для указания количества наиболее часто используемых слов. Управление этим может значительно сократить объем вычислений и время обучения и даже на некоторое время повысить точность. Я надеюсь привлечь некоторое внимание. Мы также видим, что большая часть полученного закодированного вектора равна 0, что недостаточно компактно, что приведет к большому объему использования памяти.Неплохо, какие еще есть решения? Ответ положительный.

вложение слов

Также называется вектором слов. Вложения слов обычно плотные и низкоразмерные (256, 512, 1024). Так что же такое встраивание слов?

Наша тема в этой статье-обработка текстовой информации.Текстовая информация имеет семантику.Мы ничего не можем сделать с текстами без семантики.Однако наш предыдущий метод обработки на самом деле статистика вероятности,которая представляет собой простое вычисление.понимаем смысл( или очень мало), но, учитывая реальную ситуацию, значения «очень хорошо» и «отлично» схожи, они противоположны «очень плохо», поэтому мы хотим преобразовать в вектор Когда расстояние между первым два вектора малы, расстояние от последнего вектора велико. Итак, посмотрите на следующую картинку, легко ли ее понять:

image

Вам может быть сложно реализовать эту функцию напрямую. К счастью, Keras упрощает эту проблему. Встраивание — это встроенный сетевой уровень, который может завершить это сопоставление. Теперь, когда мы понимаем эту концепцию, давайте взглянем на проблему IMDB (прогнозирование настроений в обзорах фильмов). Код прост, и точность почти 75% может быть достигнута:

def imdb_run():
    max_features = 10000
    maxlen = 20
    (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
    x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)
    model = Sequential()
    model.add(Embedding(10000, 8, input_length=maxlen))
    model.add(Flatten())
    model.add(Dense(1, activation='sigmoid'))
    model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
    model.summary()
    history = model.fit(x_train, y_train, epochs=10, batch_size=32, validation_split=0.2)

Наш объем данных немного мал, что нам делать? В предыдущем разделе, когда мы обрабатывали изображения, использовался метод использования предварительно обученной сети, Здесь мы используем аналогичный метод, используя предварительно обученные вложения слов. Двумя наиболее популярными вложениями слов являются GloVe и Word2Vec, которые мы рассмотрим отдельно, когда это будет уместно. Сегодня мы используем метод GloVe, и я написал конкретный метод в комментариях к коду. Мы по-прежнему сначала смотрим на результаты, а код по-прежнему находится в конце:

image

Скоро переобучение.Вы можете подумать, что точность проверки близка к 60%.Учитывая, что обучающих выборок всего 200,это действительно хороший результат.Вы,конечно,можете не верить.Тогда я приведу два набора сравнения диаграммы. , группа без вложений слов:

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от пиявки, рекомендуется сохранить изображение и загрузить его напрямую (img-Uem4R2hO-1583414769394) (upload-images.Краткое описание.IO/upload_IM Расшаривает…)]

Точность проверки явно низкая, и приведены данные 2000 обучающих наборов:

image

Эта точность намного выше. Преследовать этот уровень не является нашей целью. Наша цель — показать, что встраивание слов эффективно. Мы достигли этой цели. Что ж, давайте посмотрим на код:

#!/usr/bin/env python3
​
import os
import time
​
import matplotlib.pyplot as plt
import numpy as np
from keras.layers import Embedding, Flatten, Dense
from keras.models import Sequential
from keras.preprocessing.sequence import pad_sequences
from keras.preprocessing.text import Tokenizer
​
​
def deal():
    # http://mng.bz/0tIo
    imdb_dir = '/Users/renyuzhuo/Documents/PycharmProjects/Data/aclImdb'
    train_dir = os.path.join(imdb_dir, 'train')
    labels = []
    texts = []
    # 读出所有数据
    for label_type in ['neg', 'pos']:
        dir_name = os.path.join(train_dir, label_type)
        for fname in os.listdir(dir_name):
            if fname[-4:] == '.txt':
                f = open(os.path.join(dir_name, fname))
                texts.append(f.read())
                f.close()
                if label_type == 'neg':
                    labels.append(0)
                else:
                    labels.append(1)
​
    # 对所有数据进行分词
    # 每个评论最多 100 个单词
    maxlen = 100
    # 训练样本数量
    training_samples = 200
    # 验证样本数量
    validation_samples = 10000
    # 只取最常见 10000 个单词
    max_words = 10000
    # 分词,前文已经介绍过了
    tokenizer = Tokenizer(num_words=max_words)
    tokenizer.fit_on_texts(texts)
    sequences = tokenizer.texts_to_sequences(texts)
    word_index = tokenizer.word_index
    print('Found %s unique tokens.' % len(word_index))
    # 将整数列表转换成张量
    data = pad_sequences(sequences, maxlen=maxlen)
    labels = np.asarray(labels)
    print('Shape of data tensor:', data.shape)
    print('Shape of label tensor:', labels.shape)
    # 打乱数据
    indices = np.arange(data.shape[0])
    np.random.shuffle(indices)
    data = data[indices]
    labels = labels[indices]
    # 切割成训练集和验证集
    x_train = data[:training_samples]
    y_train = labels[:training_samples]
    x_val = data[training_samples: training_samples + validation_samples]
    y_val = labels[training_samples: training_samples + validation_samples]
​
    # 下载词嵌入数据,下载地址:https: // nlp.stanford.edu / projects / glove
    glove_dir = '/Users/renyuzhuo/Documents/PycharmProjects/Data/glove.6B'
    embeddings_index = {}
    f = open(os.path.join(glove_dir, 'glove.6B.100d.txt'))
    # 构建单词与其x向量表示的索引
    for line in f:
        values = line.split()
        word = values[0]
        coefs = np.asarray(values[1:], dtype='float32')
        embeddings_index[word] = coefs
    f.close()
    print('Found %s word vectors.' % len(embeddings_index))
​
    # 构建嵌入矩阵
    embedding_dim = 100
    embedding_matrix = np.zeros((max_words, embedding_dim))
    for word, i in word_index.items():
        if i < max_words:
            embedding_vector = embeddings_index.get(word)
            if embedding_vector is not None:
                embedding_matrix[i] = embedding_vector
​
    # 构建模型
    model = Sequential()
    model.add(Embedding(max_words, embedding_dim, input_length=maxlen))
    model.add(Flatten())
    model.add(Dense(32, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    model.summary()
​
    # 将 GloVe 加载到 Embedding 层,且将其设置为不可训练
    model.layers[0].set_weights([embedding_matrix])
    model.layers[0].trainable = False
​
    # 训练模型
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['acc'])
    history = model.fit(x_train, y_train,
                        epochs=10,
                        batch_size=32,
                        validation_data=(x_val, y_val))
    model.save_weights('pre_trained_glove_model.h5')
​
    # 画图
    acc = history.history['acc']
    val_acc = history.history['val_acc']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    epochs = range(1, len(acc) + 1)
    plt.plot(epochs, acc, 'bo', label='Training acc')
    plt.plot(epochs, val_acc, 'b', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend()
    plt.show()
​
    plt.figure()
    plt.plot(epochs, loss, 'bo', label='Training loss')
    plt.plot(epochs, val_loss, 'b', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend()
    plt.show()
​
​
if __name__ == "__main__":
    time_start = time.time()
    deal()
    time_end = time.time()
    print('Time Used: ', time_end - time_start)

Эта статья была впервые опубликована из публичного аккаунта:RAIS