Saat ini, berbicara dengan agen percakapan menjadi rutinitas sehari-hari, dan sangat penting bagi sistem dialog untuk menghasilkan respons semanusiawi mungkin. Sebagai salah satu aspek utama, perhatian utama harus diberikan untuk memberikan tanggapan yang sadar secara emosional kepada pengguna. Dalam artikel ini, kita akan menggambarkan
arsitektur jaringan saraf berulang untuk deteksi emosi dalam percakapan tekstual , yang berpartisipasi dalam
SemEval-2019 Tugas 3 "EmoContext" , yaitu, lokakarya tahunan tentang evaluasi semantik. Tujuan tugas adalah untuk mengklasifikasikan emosi (yaitu bahagia, sedih, marah, dan lain-lain) dalam kumpulan data percakapan 3 putaran.
Sisa artikel ini disusun sebagai berikut. Bagian 1 memberikan gambaran singkat tentang tugas EmoContext dan data yang disediakan. Bagian 2 dan 3 fokus pada teks pra-pemrosesan dan embeddings kata, akibatnya. Pada bagian 4, kami menggambarkan arsitektur model LSTM yang digunakan dalam pengiriman kami. Sebagai kesimpulan, kinerja akhir dari sistem kami dan kode sumber disajikan. Model ini diimplementasikan dalam Python menggunakan perpustakaan Keras.
1. Data Pelatihan
SemEval-2019 Tugas 3 "EmoContext" difokuskan pada deteksi emosi kontekstual dalam percakapan tekstual. Dalam EmoContext, diberi ucapan pengguna tekstual bersama dengan 2 putaran konteks dalam percakapan, kita harus mengklasifikasikan apakah emosi ucapan pengguna berikutnya adalah "bahagia", "sedih", "marah" atau "orang lain" (Tabel 1). Hanya ada dua peserta percakapan: orang anonim (Tuen-1 dan Turn-3) dan chatbot
Ruuh berbasis
AI (Turn-2). Untuk deskripsi terperinci, lihat (
Chatterjee et al., 2019 ).
Tabel 1. Contoh yang menunjukkan dataset EmoContext ( Chatterjee et al., 2019 )Selama kompetisi, kami memiliki akses ke 30160 teks berlabel manusia yang disediakan oleh penyelenggara tugas, di mana masing-masing sekitar 5000 sampel dari kelas "angry", "sad", "happy" dan 15000 untuk kelas "others" (Tabel 2). Set Dev dan tes, yang juga disediakan oleh penyelenggara, berbeda dengan set kereta, memiliki distribusi kehidupan nyata, yaitu sekitar 4% untuk setiap kelas emosional dan sisanya untuk kelas "lain-lain". Data disediakan oleh Microsoft dan dapat ditemukan di
grup LinkedIn resmi .
Tabel 2. Distribusi label kelas emosi dalam kumpulan data ( Chatterjee et al., 2019 ).Selain data ini, kami mengumpulkan 900k tweet bahasa Inggris untuk membuat dataset jauh 300k tweet untuk setiap emosi. Untuk membentuk dataset yang jauh, kami berdasarkan pada strategi Go et al. (2009), di mana kami hanya mengasosiasikan tweet dengan kehadiran kata-kata yang berhubungan dengan emosi seperti '#angry', '#annoyed', '#happy', '#sad,' #surprised ', dll. Daftar istilah kueri didasarkan pada istilah kueri dari SemEval-2018 AIT DISC (
Duppada et al., 2018 ).
Metrik kinerja utama EmoContext adalah skor F1 mikro-rata-rata untuk tiga kelas emosi, yaitu 'sedih', 'bahagia', dan 'marah'.
def preprocessData(dataFilePath, mode): conversations = [] labels = [] with io.open(dataFilePath, encoding="utf8") as finput: finput.readline() for line in finput: line = line.strip().split('\t') for i in range(1, 4): line[i] = tokenize(line[i]) if mode == "train": labels.append(emotion2label[line[4]]) conv = line[1:4] conversations.append(conv) if mode == "train": return np.array(conversations), np.array(labels) else: return np.array(conversations) texts_train, labels_train = preprocessData('./starterkitdata/train.txt', mode="train") texts_dev, labels_dev = preprocessData('./starterkitdata/dev.txt', mode="train") texts_test, labels_test = preprocessData('./starterkitdata/test.txt', mode="train")
2. Teks Pra-Pemrosesan
Sebelum tahap pelatihan apa pun, teks sudah diproses terlebih dahulu oleh alat teks Ekphrasis (Baziotis et al., 2017). Alat ini membantu untuk melakukan koreksi ejaan, normalisasi kata, segmentasi, dan memungkinkan untuk menentukan token mana yang harus dihilangkan, dinormalisasi atau dijelaskan dengan tag khusus. Kami menggunakan teknik berikut untuk tahap pra-pemrosesan.
- URL, email, tanggal dan waktu, nama pengguna, persentase, mata uang, dan angka diganti dengan tag yang sesuai.
- Istilah yang berulang, disensor, memanjang, dan bermodal diberi keterangan dengan tag yang sesuai.
- Kata-kata yang memanjang secara otomatis diperbaiki berdasarkan pada corpus statistik kata bawaan.
- Hashtag dan kontraksi membongkar (yaitu segmentasi kata) dilakukan berdasarkan built-in statistik kata corpus.
- Kamus yang dibuat secara manual untuk mengganti istilah yang diekstrak dari teks digunakan untuk mengurangi beragam emosi.
Selain itu, Penekanan menyediakan tokenizer yang mampu mengidentifikasi sebagian besar emoji, emotikon, dan ekspresi rumit seperti kata yang disensor, ditekankan dan memanjang serta tanggal, waktu, mata uang, dan akronim.
Tabel 3. Contoh-contoh pra-pemrosesan teks. from ekphrasis.classes.preprocessor import TextPreProcessor from ekphrasis.classes.tokenizer import SocialTokenizer from ekphrasis.dicts.emoticons import emoticons import numpy as np import re import io label2emotion = {0: "others", 1: "happy", 2: "sad", 3: "angry"} emotion2label = {"others": 0, "happy": 1, "sad": 2, "angry": 3} emoticons_additional = { '(^γ»^)': '<happy>', ':βc': '<sad>', '=βd': '<happy>', ":'β)": '<happy>', ':βd': '<laugh>', ':β(': '<sad>', ';β)': '<happy>', ':β)': '<happy>', ':\\/': '<sad>', 'd=<': '<annoyed>', ':β/': '<annoyed>', ';β]': '<happy>', '(^ ^)': '<happy>', 'angru': 'angry', "dβ':": '<annoyed>', ":'β(": '<sad>', ":β[": '<annoyed>', '( ? )': '<happy>', 'xβd': '<laugh>', } text_processor = TextPreProcessor(
3. Word Embeddings
Word embeddings telah menjadi bagian penting dari setiap pendekatan pembelajaran mendalam untuk sistem NLP. Untuk menentukan vektor yang paling cocok untuk tugas pendeteksian emosi, kami mencoba Word2Vec (
Mikolov et al., 2013 ), GloVe (
Pennington et al., 2014 ) dan model FastText (
Joulin et al., 2017 ) serta DataStories yang sudah dilatih sebelumnya. kata vektor (
Baziotis et al., 2017 ). Konsep kunci dari Word2Vec adalah untuk menemukan kata-kata, yang berbagi konteks umum dalam corpus pelatihan, dalam jarak dekat dalam ruang vektor. Baik model Word2Vec dan Glove mempelajari pengkodean geometris kata-kata dari informasi yang terjadi bersamaan, tetapi pada dasarnya yang pertama adalah model yang dapat diprediksi, dan yang kedua adalah model yang berdasarkan hitungan. Dengan kata lain, sementara Word2Vec mencoba untuk memprediksi kata target (arsitektur CBOW) atau konteks (arsitektur Lewati-gram), yaitu untuk meminimalkan fungsi kerugian, GloVe menghitung vektor kata yang melakukan pengurangan dimensionalitas pada matriks penghitungan kejadian bersama. FastText sangat mirip dengan Word2Vec kecuali untuk fakta bahwa ia menggunakan karakter n-gram untuk mempelajari vektor kata, sehingga ia dapat memecahkan masalah kosakata yang tidak tersedia.
Untuk semua teknik yang disebutkan di atas, kami menggunakan kereta bayi pelatihan standar yang disediakan oleh penulis. Kami melatih model LSTM sederhana (dim = 64) berdasarkan masing-masing embeddings ini dan membandingkan efektivitas menggunakan cross-validation. Menurut hasil, embeddings pra-pelatihan DataStories menunjukkan skor rata-rata F1 terbaik.
Untuk memperkaya embedding kata yang dipilih dengan polaritas emosional dari kata-kata tersebut, kami mempertimbangkan untuk melakukan frase pra-pelatihan yang jauh dengan menyelaraskan embeddings pada dataset jauh yang berlabel secara otomatis. Pentingnya menggunakan pra-pelatihan ditunjukkan dalam (
Deriu et al., 201 7). Kami menggunakan dataset jauh untuk melatih jaringan LSTM sederhana untuk mengklasifikasikan tweet yang marah, sedih, dan bahagia. Lapisan embeddings dibekukan untuk zaman pelatihan pertama untuk menghindari perubahan yang signifikan dalam bobot embeddings, dan kemudian dibekukan untuk 5 epos berikutnya. Setelah tahap pelatihan, embeddings yang telah disesuaikan disimpan untuk fase pelatihan selanjutnya dan
tersedia untuk umum .
def getEmbeddings(file): embeddingsIndex = {} dim = 0 with io.open(file, encoding="utf8") as f: for line in f: values = line.split() word = values[0] embeddingVector = np.asarray(values[1:], dtype='float32') embeddingsIndex[word] = embeddingVector dim = len(embeddingVector) return embeddingsIndex, dim def getEmbeddingMatrix(wordIndex, embeddings, dim): embeddingMatrix = np.zeros((len(wordIndex) + 1, dim)) for word, i in wordIndex.items(): embeddingMatrix[i] = embeddings.get(word) return embeddingMatrix from keras.preprocessing.text import Tokenizer embeddings, dim = getEmbeddings('emosense.300d.txt') tokenizer = Tokenizer(filters='') tokenizer.fit_on_texts([' '.join(list(embeddings.keys()))]) wordIndex = tokenizer.word_index print("Found %s unique tokens." % len(wordIndex)) embeddings_matrix = getEmbeddingMatrix(wordIndex, embeddings, dim)
4. Arsitektur Jaringan Saraf Tiruan
Jaringan saraf berulang (RNN) adalah keluarga jaringan saraf tiruan yang khusus menangani pemrosesan data sekuensial. Berbeda dengan jaringan saraf tradisional, RRN dirancang untuk menangani data sekuensial dengan berbagi bobot internal mereka yang memproses urutan. Untuk tujuan ini, grafik perhitungan RRN mencakup siklus, mewakili pengaruh informasi sebelumnya pada yang sekarang. Sebagai perpanjangan dari RNNs, jaringan Memori Jangka Pendek (LSTM) telah diperkenalkan pada tahun 1997 (
Hochreiter dan Schmidhuber, 1997 ). Dalam LSTM sel berulang dihubungkan dengan cara tertentu untuk menghindari menghilang dan meledaknya masalah gradien. LSTM tradisional hanya menyimpan informasi dari masa lalu karena mereka memproses urutan hanya dalam satu arah. LSTM dua arah menggabungkan output dari dua lapisan LSTM tersembunyi yang bergerak dalam arah yang berlawanan, di mana satu bergerak maju melalui waktu, dan yang lain bergerak mundur melalui waktu, sehingga memungkinkan untuk menangkap informasi dari kedua negara masa lalu dan masa depan secara bersamaan (
Schuster dan Paliwal, 1997 ).
Gambar 1: Arsitektur versi yang lebih kecil dari arsitektur yang diusulkan. Unit LSTM untuk belokan pertama dan belokan ketiga memiliki bobot yang dibagi.Tinjauan tingkat tinggi dari pendekatan kami disediakan pada Gambar 1. Arsitektur yang diusulkan dari jaringan saraf terdiri dari unit embedding dan dua unit LSTM dua arah (redup = 64). Mantan unit LSTM dimaksudkan untuk menganalisis ucapan pengguna pertama (yaitu giliran pertama dan putaran ketiga dari percakapan), dan yang terakhir dimaksudkan untuk menganalisis ucapan pengguna kedua (yaitu giliran kedua). Kedua unit ini tidak hanya mempelajari representasi fitur semantik dan sentimen, tetapi juga cara menangkap fitur percakapan khusus pengguna, yang memungkinkan pengelompokan emosi secara lebih akurat. Pada langkah pertama, setiap ucapan pengguna dimasukkan ke dalam unit LSTM dua arah yang sesuai menggunakan embeddings kata yang sudah dilatih sebelumnya. Selanjutnya, ketiga peta fitur ini disatukan dalam vektor fitur yang rata dan kemudian diteruskan ke lapisan tersembunyi yang sepenuhnya terhubung (dim = 30), yang menganalisis interaksi antara vektor yang diperoleh. Akhirnya, fitur-fitur ini melanjutkan melalui lapisan output dengan fungsi aktivasi softmax untuk memprediksi label kelas akhir. Untuk mengurangi overfitting, lapisan regularisasi dengan noise Gaussian ditambahkan setelah lapisan embedding, lapisan dropout (
Srivastava et al., 2014 ) ditambahkan pada setiap unit LSTM (p = 0,2) dan sebelum lapisan yang terhubung sepenuhnya tersembunyi (p = 0,1).
from keras.layers import Input, Dense, Embedding, Concatenate, Activation, \ Dropout, LSTM, Bidirectional, GlobalMaxPooling1D, GaussianNoise from keras.models import Model def buildModel(embeddings_matrix, sequence_length, lstm_dim, hidden_layer_dim, num_classes, noise=0.1, dropout_lstm=0.2, dropout=0.2): turn1_input = Input(shape=(sequence_length,), dtype='int32') turn2_input = Input(shape=(sequence_length,), dtype='int32') turn3_input = Input(shape=(sequence_length,), dtype='int32') embedding_dim = embeddings_matrix.shape[1] embeddingLayer = Embedding(embeddings_matrix.shape[0], embedding_dim, weights=[embeddings_matrix], input_length=sequence_length, trainable=False) turn1_branch = embeddingLayer(turn1_input) turn2_branch = embeddingLayer(turn2_input) turn3_branch = embeddingLayer(turn3_input) turn1_branch = GaussianNoise(noise, input_shape=(None, sequence_length, embedding_dim))(turn1_branch) turn2_branch = GaussianNoise(noise, input_shape=(None, sequence_length, embedding_dim))(turn2_branch) turn3_branch = GaussianNoise(noise, input_shape=(None, sequence_length, embedding_dim))(turn3_branch) lstm1 = Bidirectional(LSTM(lstm_dim, dropout=dropout_lstm)) lstm2 = Bidirectional(LSTM(lstm_dim, dropout=dropout_lstm)) turn1_branch = lstm1(turn1_branch) turn2_branch = lstm2(turn2_branch) turn3_branch = lstm1(turn3_branch) x = Concatenate(axis=-1)([turn1_branch, turn2_branch, turn3_branch]) x = Dropout(dropout)(x) x = Dense(hidden_layer_dim, activation='relu')(x) output = Dense(num_classes, activation='softmax')(x) model = Model(inputs=[turn1_input, turn2_input, turn3_input], outputs=output) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc']) return model model = buildModel(embeddings_matrix, MAX_SEQUENCE_LENGTH, lstm_dim=64, hidden_layer_dim=30, num_classes=4)
5. Hasil
Dalam proses mencari arsitektur yang optimal, kami bereksperimen tidak hanya dengan jumlah sel dalam lapisan, fungsi aktivasi dan parameter regularisasi tetapi juga dengan arsitektur jaringan saraf. Info terperinci tentang frasa ini dapat ditemukan di
koran aslinya .
Model yang dijelaskan pada bagian sebelumnya menunjukkan skor terbaik pada dataset dev, sehingga digunakan pada tahap evaluasi akhir kompetisi. Pada dataset tes akhir, itu mencapai 72,59% skor rata-rata mikro F1 untuk kelas emosional, sedangkan skor maksimum di antara semua peserta adalah 79,59%. Namun, ini jauh di atas garis dasar resmi yang dirilis oleh pengatur tugas, yaitu 58,68%.
Kode sumber model dan embedding kata tersedia di GitHub.
Versi lengkap artikel dan
makalah uraian tugas dapat ditemukan di ACL Anthology.
Dataset pelatihan terletak di grup kompetisi resmi di LinkedIn.
Kutipan:
@inproceedings{smetanin-2019-emosense, title = "{E}mo{S}ense at {S}em{E}val-2019 Task 3: Bidirectional {LSTM} Network for Contextual Emotion Detection in Textual Conversations", author = "Smetanin, Sergey", booktitle = "Proceedings of the 13th International Workshop on Semantic Evaluation", year = "2019", address = "Minneapolis, Minnesota, USA", publisher = "Association for Computational Linguistics", url = "https://www.aclweb.org/anthology/S19-2034", pages = "210--214", }