Difference between revisions of "Keras: Python Keras Text Classification"

From OnnoWiki
Jump to navigation Jump to search
 
(36 intermediate revisions by the same user not shown)
Line 176: Line 176:
 
[[File:Ann.png|center|200px|thumb]]
 
[[File:Ann.png|center|200px|thumb]]
  
 +
Kita mulai dengan memiliki lapisan neuron input tempat kita memberi masukan di feature vector kita dan nilai tersebut kemudian diumpankan (feed forward) ke lapisan tersembunyi. Pada setiap koneksi, kita memasukan nilai untuk dimajukan, kemudian nilai dikalikan dengan bobot dan ditambahkan bias. Ini terjadi pada setiap koneksi dan pada akhirnya kita mencapai lapisan output dengan satu atau lebih node output.
  
You start by having a layer of input neurons where you feed in your feature vectors and the values are then feeded forward to a hidden layer. At each connection, you are feeding the value forward, while the value is multiplied by a weight and a bias is added to the value. This happens at every connection and at the end you reach an output layer with one or more output nodes.
+
Jika kita ingin memiliki klasifikasi biner, kita dapat menggunakan satu simpul, tetapi jika kita memiliki beberapa kategori, kita harus menggunakan banyak simpul untuk setiap kategori.
  
If you want to have a binary classification you can use one node, but if you have multiple categories you should use multiple nodes for each category:
+
Kita dapat memiliki lapisan tersembunyi sebanyak yang kita inginkan. Sebetulnya, neural networks dengan lebih dari satu lapisan tersembunyi dianggap sebagai deep neural networks. Jangan khawatir: kita tidak akan sampai di sini ke kedalaman matematika tentang neural network. Tetapi jika kita ingin mendapatkan pemahaman visual intuitif tentang matematika yang terlibat, anda dapat melihat Playlist YouTube https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi oleh Grant Sanderson. Rumus dari satu layer ke yang berikutnya adalah persamaan pendek ini:
* neural network structure
 
* Neural network model
 
  
You can have as many hidden layers as you wish. In fact, a neural network with more than one hidden layer is considered a deep neural network. Don’t worry: I won’t get here into the mathematical depths concerning neural networks. But if you want to get an intuitive visual understanding of the math involved, you can check out the YouTube Playlist by Grant Sanderson. The formula from one layer to the next is this short equation:
+
[[File:Rumus-neural-network.png|center|400px|thumb]]
neural network formula
 
Neural network formula
 
  
Let’s slowly unpack what is happening here. You see, we are dealing here with only two layers. The layer with nodes a serves as input for the layer with nodes o. In order to calculate the values for each output node, we have to multiply each input node by a weight w and add a bias b.
+
Mari kita perlahan membongkar apa yang terjadi di sini. Kita lihat, kita berurusan di sini hanya dengan dua lapisan. Layer dengan node a berfungsi sebagai input untuk layer dengan node o. Untuk menghitung nilai untuk setiap simpul keluaran, kita harus mengalikan setiap simpul masukan dengan bobot w dan menambahkan bias b.
  
All of those have to be then summed and passed to a function f. This function is considered the activation function and there are various different functions that can be used depending on the layer or the problem. It is generally common to use a rectified linear unit (ReLU) for hidden layers, a sigmoid function for the output layer in a binary classification problem, or a softmax function for the output layer of multi-class classification problems.
+
Semua itu harus dijumlahkan dan diteruskan ke fungsi f. Fungsi ini dianggap sebagai fungsi aktivasi dan ada berbagai fungsi berbeda yang dapat digunakan tergantung pada lapisan atau masalahnya. Umumnya umum untuk menggunakan rectified linear unit (ReLU) untuk lapisan hidden, fungsi sigmoid untuk lapisan output dalam masalah klasifikasi biner, atau fungsi softmax untuk lapisan output dari masalah klasifikasi multi-kelas.
  
You might already wonder how the weights are calculated, and this is obviously the most important part of neural networks, but also the most difficult part. The algorithm starts by initializing the weights with random values and they are then trained with a method called backpropagation.
+
Kita mungkin sudah bertanya-tanya bagaimana bobot dihitung, dan ini jelas merupakan bagian terpenting dari neural networks, tetapi juga bagian yang paling sulit. Algoritma dimulai dengan menginisialisasi bobot dengan nilai acak dan mereka kemudian dilatih dengan metode yang disebut backpropagation.
  
This is done by using optimization methods (also called optimizer) like the gradient descent in order to reduce the error between the computed and the desired output (also called target output). The error is determined by a loss function whose loss we want to minimize with the optimizer. The whole process is too extensive to cover here, but I’ll refer again to the Grant Sanderson playlist and the Deep Learning book by Ian Goodfellow I mentioned before.
+
Ini dilakukan dengan menggunakan metode optimisasi (juga disebut optimizer) seperti gradient descent untuk mengurangi kesalahan antara output yang dihitung dan yang diinginkan (juga disebut output target). Kesalahan ditentukan oleh fungsi kerugian (loss function) yang kerugiannya (loss-nya) ingin kami perkecil dengan optimizer. Seluruh proses terlalu luas untuk dibahas di sini, tetapi saya akan merujuk lagi ke playlist Grant Sanderson dan buku Deep Learning oleh Ian Goodfellow.
  
What you have to know is that there are various optimization methods that you can use, but the most common optimizer currently used is called Adam which has a good performance in various problems.
+
Yang harus kita ketahui adalah bahwa ada berbagai metode pengoptimalan yang dapat kita gunakan, tetapi pengoptimal yang paling umum saat ini digunakan adalah Adam yang memiliki kinerja yang baik dalam berbagai masalah.
  
You can also use different loss functions, but in this tutorial you will only need the cross entropy loss function or more specifically binary cross entropy which is used for binary classification problems. Be sure to experiment with the various available methods and tools. Some researchers even claim in a recent article that the choice for the best performing methods borders on alchemy. The reason being that many methods are not well explained and consist of a lot of tweaking and testing.
+
Kita juga dapat menggunakan fungsi loss yang berbeda, tetapi dalam tutorial ini kita hanya akan memerlukan cross entropy loss function atau lebih khusus, binary cross entropy yang digunakan untuk masalah klasifikasi biner. Pastikan untuk bereksperimen dengan berbagai metode dan tool yang tersedia. Beberapa peneliti bahkan mengklaim dalam sebuah artikel baru-baru ini bahwa pilihan untuk metode berkinerja terbaik berbatasan dengan alchemy. Alasannya adalah bahwa banyak metode tidak dijelaskan dengan baik dan terdiri dari banyak penyesuaian dan testing.
Introducing Keras
 
  
Keras is a deep learning and neural networks API by François Chollet which is capable of running on top of Tensorflow (Google), Theano or CNTK (Microsoft). To quote the wonderful book by François Chollet, Deep Learning with Python:
+
==Pengenalan Keras==
  
    Keras is a model-level library, providing high-level building blocks for developing deep-learning models. It doesn’t handle low-level operations such as tensor manipulation and differentiation. Instead, it relies on a specialized, well-optimized tensor library to do so, serving as the backend engine of Keras (Source)
+
Keras adalah pembelajaran mendalam dan API neural networks oleh François Chollet yang mampu berjalan di atas Tensorflow (Google), Theano atau CNTK (Microsoft). Mengutip buku bagus dari François Chollet, Deep Learning with Python:
  
It is a great way to start experimenting with neural networks without having to implement every layer and piece on your own. For example Tensorflow is a great machine learning library, but you have to implement a lot of boilerplate code to have a model running.
+
''"Keras is a model-level library, providing high-level building blocks for developing deep-learning models. It doesn’t handle low-level operations such as tensor manipulation and differentiation. Instead, it relies on a specialized, well-optimized tensor library to do so, serving as the backend engine of Keras (Source)"''
Installing Keras
 
  
Before installing Keras, you’ll need either Tensorflow, Theano, or CNTK. In this tutorial we will be using Tensorflow so check out their installation guide here, but feel free to use any of the frameworks that works best for you. Keras can be installed using PyPI with the following command:
+
Ini adalah cara yang bagus untuk mulai bereksperimen dengan neural network tanpa harus menerapkan setiap lapisan oleh kita sendiri. Misalnya Tensorflow adalah library machine learning yang hebat, tetapi kita harus menerapkan banyak kode boilerplate agar model bisa jalan.
  
$ pip install keras
+
==Install Keras==
  
You can choose the backend you want to have by opening the Keras configuration file which you can find here:
+
Sebelum menginstall Keras, kita perlu Tensorflow, Theano, atau CNTK. Dalam tutorial ini kita akan menggunakan Tensorflow jadi lihat panduan instalasi mereka, tetapi jangan ragu untuk menggunakan salah satu framework yang paling cocok untuk anda. Keras dapat diinstal menggunakan PyPI dengan perintah berikut:
  
$HOME/.keras/keras.json
+
$ pip install keras
  
If you are a Windows user, you have to replace $HOME with %USERPROFILE%. The configuration file should look as follows:
+
Kita dapat memilih backend yang ingin kita miliki dengan membuka file konfigurasi Keras yang dapat kita temukan di sini:
  
{
+
$HOME/.keras/keras.json
    "image_data_format": "channels_last",
 
    "epsilon": 1e-07,
 
    "floatx": "float32",
 
    "backend": "tensorflow"
 
}
 
  
You can change the backend field there to "theano", "tensorflow" or "cntk", given that you have installed the backend on your machine. For more details check out the Keras backends documentation.
+
Jika anda adalah pengguna Windows, anda harus mengganti $HOME dengan %USERPROFILE%. File konfigurasi akan terlihat sebagai berikut:
  
You might notice that we use float32 data in the configuration file. The reason for this is that neural networks are frequently used in GPUs, and the computational bottleneck is memory. By using 32 bit, we are able reduce the memory load and we do not lose too much information in the process.
+
{
Your First Keras Model
+
    "image_data_format": "channels_last",
 +
    "epsilon": 1e-07,
 +
    "floatx": "float32",
 +
    "backend": "tensorflow"
 +
}
  
Now you are finally ready to experiment with Keras. Keras supports two main types of models. You have the Sequential model API which you are going to see in use in this tutorial and the functional API which can do everything of the Sequential model but it can be also used for advanced models with complex network architectures.
+
Kita dapat mengubah backend field menjadi "theano", "tensorflow" atau "cntk", mengingat kita telah menginstal backend pada mesin yang kita gunakan. Untuk lebih jelasnya lihat dokumentasi Keras backends.
  
The Sequential model is a linear stack of layers, where you can use the large variety of available layers in Keras. The most common layer is the Dense layer which is your regular densely connected neural network layer with all the weights and biases that you are already familiar with.
+
Anda mungkin memperhatikan bahwa kita menggunakan data float32 dalam file konfigurasi. Alasan untuk ini adalah bahwa neural network sering digunakan dalam GPU, dan hambatan komputasi adalah memori. Dengan menggunakan 32 bit, kita dapat mengurangi beban memori dan kami tidak kehilangan terlalu banyak informasi dalam proses.
  
Let’s see if we can achieve some improvement to our previous logistic regression model. You can use the X_train and X_test arrays that you built in our earlier example.
+
==Model Keras anda yang pertama==
  
Before we build our model, we need to know the input dimension of our feature vectors. This happens only in the first layer since the following layers can do automatic shape inference. In order to build the Sequential model, you can add layers one by one in order as follows:
+
Sekarang kita akhirnya siap untuk bereksperimen dengan Keras. Keras mendukung dua (2) jenis utama model. Kita memiliki API model Sequential yang akan kita lihat digunakan dalam tutorial ini dan API fungsional yang dapat melakukan semua hal dari model Sequential tetapi dapat juga digunakan untuk model lanjutan dengan arsitektur jaringan yang kompleks.
  
>>> from keras.models import Sequential
+
Model Sequential adalah tumpukan linear lapisan, di mana kita dapat menggunakan berbagai macam lapisan yang tersedia di Keras. Lapisan yang paling umum adalah lapisan Dense yang merupakan lapisan neural network biasa yang terhubung dengan semua Weight dan bias yang sudah kita kenal.
>>> from keras import layers
 
  
>>> input_dim = X_train.shape[1]  # Number of features
+
Mari kita lihat apakah kita dapat mencapai beberapa peningkatan pada model regresi logistik kita sebelumnya. Anda dapat menggunakan array X_train dan X_test yang Anda buat dalam contoh kami sebelumnya.
  
>>> model = Sequential()
+
Sebelum kita membangun model kita, kita perlu mengetahui dimensi input vektor fitur kita. Ini hanya terjadi di lapisan pertama karena lapisan berikut dapat melakukan inferensi shape secara otomatis. Untuk membangun model Sequential, kita dapat menambahkan layer satu per satu dengan urutan sebagai berikut:
>>> model.add(layers.Dense(10, input_dim=input_dim, activation='relu'))
 
>>> model.add(layers.Dense(1, activation='sigmoid'))
 
Using TensorFlow backend.
 
  
Before you can start with the training of the model, you need to configure the learning process. This is done with the .compile() method. This method specifies the optimizer and the loss function.
+
from keras.models import Sequential
 +
from keras import layers
 +
 +
input_dim = X_train.shape[1]  # Number of features
 +
 +
model = Sequential()
 +
model.add(layers.Dense(10, input_dim=input_dim, activation='relu'))
 +
model.add(layers.Dense(1, activation='sigmoid'))
  
Additionally, you can add a list of metrics which can be later used for evaluation, but they do not influence the training. In this case, we want to use the binary cross entropy and the Adam optimizer you saw in the primer mentioned before. Keras also includes a handy .summary() function to give an overview of the model and the number of parameters available for training:
+
==Penggunaan backend TensorFlow==
  
>>> model.compile(loss='binary_crossentropy',
+
Sebelum kita dapat mulai dengan training model, kita harus mengonfigurasi proses training. Ini dilakukan dengan metode .compile(). Metode ini menentukan fungsi optimizer dan loss.
...               optimizer='adam',
 
...               metrics=['accuracy'])
 
>>> model.summary()
 
_________________________________________________________________
 
Layer (type)                Output Shape          Param # 
 
=================================================================
 
dense_1 (Dense)              (None, 10)            17150   
 
_________________________________________________________________
 
dense_2 (Dense)              (None, 1)            11       
 
=================================================================
 
Total params: 17,161
 
Trainable params: 17,161
 
Non-trainable params: 0
 
_________________________________________________________________
 
  
You might notice that we have 8575 parameters for the first layer and another 6 in the next one. Where did those come from?
+
Selain itu, kita dapat menambahkan daftar metrik yang nantinya dapat digunakan untuk evaluasi, tetapi mereka tidak memengaruhi training. Dalam hal ini, kita ingin menggunakan  binary cross entropy dan Adam optimizer yang kita lihat dalam bagian sebelumnya. Keras juga mencakup fungsi .summary() yang berguna untuk memberikan gambaran umum tentang model dan jumlah parameter yang tersedia untuk training:
  
See, we have 1714 dimensions for each feature vector, and then we have 5 nodes. We need weights for each feature dimension and each node which accounts for 1714 * 5 = 8570 parameters, and then we have another 5 times an added bias for each node, which gets us the 8575 parameters. In the final node, we have another 5 weights and one bias, which gets us to 6 parameters.
+
model.compile(loss='binary_crossentropy',  
 +
              optimizer='adam',
 +
              metrics=['accuracy'])
 +
model.summary()
 +
 
 +
Hasilnya
 +
_________________________________________________________________
 +
Layer (type)                Output Shape          Param # 
 +
=================================================================
 +
dense_1 (Dense)              (None, 10)            17150   
 +
_________________________________________________________________
 +
dense_2 (Dense)              (None, 1)            11       
 +
=================================================================
 +
Total params: 17,161
 +
Trainable params: 17,161
 +
Non-trainable params: 0
 +
_________________________________________________________________
 +
 
 +
Anda mungkin memperhatikan bahwa kita memiliki 8575 parameter untuk lapisan pertama dan 6 lainnya di lapisan berikutnya. Dari mana datangnya?
 +
 
 +
Lihat, kita memiliki 1714 dimensi untuk setiap feature vector, dan kemudian kita memiliki 5 node. Kita perlu bobot untuk setiap dimensi feature dan setiap node yang menyumbang 1714 * 5 = 8570 parameter, dan kemudian kita memiliki 5 kali bias tambahan untuk setiap node, yang memberi kita 8575 parameter. Pada node terakhir, kita memiliki 5 bobot dan satu bias, yang membawa kita ke 6 parameter.
  
Neat! You are almost there. Now it is time to start your training with the .fit() function.
+
Kita hampir sampai. Sekarang saatnya untuk memulai training dengan fungsi .fit().
  
Since the training in neural networks is an iterative process, the training won’t just stop after it is done. You have to specify the number of iterations you want the model to be training. Those completed iterations are commonly called epochs. We want to run it for 100 epochs to be able to see how the training loss and accuracy are changing after each epoch.
+
Karena training dalam neural network adalah proses berulang, training tidak akan berhenti setelah selesai. Kita harus menentukan jumlah iterasi yang kita inginkan agar model di training. Iterasi yang selesai itu biasa disebut epochs. Kita ingin menjalankannya selama 100 epochs untuk dapat melihat bagaimana training loss dan accuracy berubah setelah setiap epoch.
  
Another parameter you have to your selection is the batch size. The batch size is responsible for how many samples we want to use in one epoch, which means how many samples are used in one forward/backward pass. This increases the speed of the computation as it need fewer epochs to run, but it also needs more memory, and the model may degrade with larger batch sizes. Since we have a small training set, we can leave this to a low batch size:
+
Parameter lain yang kita miliki untuk pilihan adalah ukuran batch (batch size). Ukuran batch bertanggung jawab untuk berapa banyak sampel yang ingin kita gunakan dalam satu epoch, yang berarti berapa banyak sampel yang digunakan dalam satu lintasan maju (forward) / mundur (backward). Ini meningkatkan kecepatan perhitungan karena perlu lebih sedikit epoch untuk run, tetapi juga membutuhkan lebih banyak memori, dan model dapat menurun dengan ukuran batch yang lebih besar. Karena kita memiliki satu set training yang kecil, kita dapat membiarkannya dalam ukuran batch yang rendah:
  
>>> history = model.fit(X_train, y_train,
+
history = model.fit(X_train, y_train,
...                    epochs=100,
+
                    epochs=100,
...                    verbose=False,
+
                    verbose=False,
...                    validation_data=(X_test, y_test)
+
                    validation_data=(X_test, y_test),
...                    batch_size=10)
+
                    batch_size=10)
  
Now you can use the .evaluate() method to measure the accuracy of the model. You can do this both for the training data and testing data. We expect that the training data has a higher accuracy then for the testing data. Tee longer you would train a neural network, the more likely it is that it starts overfitting.
+
Sekarang kita dapat menggunakan metode .evaluate() untuk mengukur akurasi model. Kita dapat melakukan ini baik untuk data training dan data testing. Kami berharap bahwa data training memiliki akurasi yang lebih tinggi daripada data testing. Semakin lama kita melatih neural network, semakin besar kemungkinan overfitting.
  
Note that if you rerun the .fit() method, you’ll start off with the computed weights from the previous training. Make sure to compile the model again before you start training the model again. Now let’s evaluate the accuracy model:
+
Perhatikan bahwa jika kita menjalankan kembali metode .fit(), kita akan mulai dengan bobot yang dihitung dari training sebelumnya. Pastikan untuk mengkompilasi model lagi sebelum kita mulai training model itu lagi. Sekarang mari kita evaluasi akurasi model:
  
>>> loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
+
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
>>> print("Training Accuracy: {:.4f}".format(accuracy))
+
print("Training Accuracy: {:.4f}".format(accuracy))
>>> loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
+
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
>>> print("Testing Accuracy:  {:.4f}".format(accuracy))
+
print("Testing Accuracy:  {:.4f}".format(accuracy))
Training Accuracy: 1.0000
 
Testing Accuracy:  0.7960
 
  
You can already see that the model was overfitting since it reached 100% accuracy for the training set. But this was expected since the number of epochs was fairly large for this model. However, the accuracy of the testing set has already surpassed our previous logistic Regression with BOW model, which is a great step further in terms of our progress.
+
Hasilnya
  
To make your life easier, you can use this little helper function to visualize the loss and accuracy for the training and testing data based on the History callback. This callback, which is automatically applied to each Keras model, records the loss and additional metrics that can be added in the .fit() method. In this case, we are only interested in the accuracy. This helper function employs the matplotlib plotting library:
+
Training Accuracy: 1.0000
 +
Testing Accuracy:  0.7960
  
import matplotlib.pyplot as plt
+
Kita  sudah dapat melihat bahwa model akan overfitting karena mencapai akurasi 100% untuk set pelatihan. Tapi ini diharapkan karena jumlah epochs yang cukup besar untuk model ini. Namun, keakuratan set testing telah melampaui  logistic Regression dengan BOW model, yang merupakan langkah maju yang baik.
plt.style.use('ggplot')
 
  
def plot_history(history):
+
Untuk membuat hidup kita lebih mudah, kita dapat menggunakan fungsi helper untuk memvisualisasikan loss dan accuracy untuk training dan testing data berdasarkan history callback. Callback, yang secara otomatis diterapkan pada setiap model Keras, mencatat loss dan metrik tambahan yang dapat ditambahkan dalam metode .fit(). Dalam hal ini, kami hanya tertarik pada accuracy. Fungsi helper ini menggunakan library matplotlib plotting:
    acc = history.history['acc']
 
    val_acc = history.history['val_acc']
 
    loss = history.history['loss']
 
    val_loss = history.history['val_loss']
 
    x = range(1, len(acc) + 1)
 
  
    plt.figure(figsize=(12, 5))
+
import matplotlib.pyplot as plt
    plt.subplot(1, 2, 1)
+
plt.style.use('ggplot')
    plt.plot(x, acc, 'b', label='Training acc')
+
    plt.plot(x, val_acc, 'r', label='Validation acc')
+
def plot_history(history):
    plt.title('Training and validation accuracy')
+
    acc = history.history['acc']
    plt.legend()
+
    val_acc = history.history['val_acc']
    plt.subplot(1, 2, 2)
+
    loss = history.history['loss']
    plt.plot(x, loss, 'b', label='Training loss')
+
    val_loss = history.history['val_loss']
    plt.plot(x, val_loss, 'r', label='Validation loss')
+
    x = range(1, len(acc) + 1)
    plt.title('Training and validation loss')
+
    plt.legend()
+
    plt.figure(figsize=(12, 5))
 +
    plt.subplot(1, 2, 1)
 +
    plt.plot(x, acc, 'b', label='Training acc')
 +
    plt.plot(x, val_acc, 'r', label='Validation acc')
 +
    plt.title('Training and validation accuracy')
 +
    plt.legend()
 +
    plt.subplot(1, 2, 2)
 +
    plt.plot(x, loss, 'b', label='Training loss')
 +
    plt.plot(x, val_loss, 'r', label='Validation loss')
 +
    plt.title('Training and validation loss')
 +
    plt.legend()
  
To use this function, simply call plot_history() with the collected accuracy and loss inside the history dictionary:
+
Untuk menggunakan fungsi ini, cukup call plot_history() dengan accuracy dan loss yang terkumpul di dalam history dictionary:
  
>>> plot_history(history)
+
plot_history(history)
  
loss accuracy baseline model
 
Accuracy and loss for baseline model
 
  
You can see that we have trained our model for too long since the training set reached 100% accuracy. A good way to see when the model starts overfitting is when the loss of the validation data starts rising again. This tends to be a good point to stop the model. You can see this around 20-40 epochs in this training.
+
[[File:Loss-accuracy-history.png|center|400px|tumb]]
  
Note: When training neural networks, you should use a separate testing and validation set. What you would usually do is take the model with the highest validation accuracy and then test the model with the testing set.
+
Kita dapat melihat bahwa kita telah melatih model terlalu lama sehingga set training mencapai akurasi 100%. Cara yang baik untuk melihat kapan model mulai overfitting adalah ketika loss dari validasi data mulai naik lagi. Ini cenderung menjadi titik yang baik untuk menghentikan model. Anda dapat melihat ini sekitar 20-40 epochs dalam training ini.
  
This makes sure that you don’t overfit the model. Using the validation set to choose the best model is a form of data leakage (or “cheating”) to get to pick the result that produced the best test score out of hundreds of them. Data leakage happens when information outside the training data set is used in the model.
+
Catatan: Saat melatih neural network, kita harus menggunakan set testing dan validasi yang terpisah. Apa yang biasanya kita lakukan adalah mengambil model dengan akurasi validasi tertinggi dan kemudian menguji model dengan set testing.
  
In this case, our testing and validation set are the same, since we have a smaller sample size. As we have covered before, (deep) neural networks perform best when you have a very large number of samples. In the next part, you’ll see a different way to represent words as vectors. This is a very exciting and powerful way to work with words where you’ll see how to represent words as dense vectors.
+
Ini memastikan bahwa kita tidak overfit dari model. Menggunakan set validasi untuk memilih model terbaik adalah bentuk kebocoran data (atau "cheating") untuk memilih hasil yang menghasilkan skor tes terbaik dari ratusan di antaranya. Kebocoran data terjadi ketika informasi di luar set data training digunakan dalam model.
What Is a Word Embedding?
 
  
Text is considered a form of sequence data similar to time series data that you would have in weather data or financial data. In the previous BOW model, you have seen how to represent a whole sequence of words as a single feature vector. Now you will see how to represent each word as vectors. There are various ways to vectorize text, such as:
+
Dalam hal ini, set testing dan validasi kita adalah sama, karena kita memiliki ukuran sampel yang lebih kecil. Seperti yang telah kita bahas sebelumnya, (deep) neural network berkinerja terbaik ketika kita memiliki jumlah sampel yang sangat besar. Di bagian selanjutnya, kita akan melihat cara berbeda untuk mewakili kata sebagai vektor. Ini adalah cara yang sangat menarik dan kuat untuk bekerja dengan kata-kata di mana kita akan melihat bagaimana merepresentasikan kata-kata sebagai dense vector.
  
    Words represented by each word as a vector
+
==Apakah Word Embedding?==
    Characters represented by each character as a vector
 
    N-grams of words/characters represented as a vector (N-grams are overlapping groups of multiple succeeding words/characters in the text)
 
  
In this tutorial, you’ll see how to deal with representing words as vectors which is the common way to use text in neural networks. Two possible ways to represent a word as a vector are one-hot encoding and word embeddings.
+
Teks dianggap sebagai bentuk urutan data yang mirip dengan data time series yang kita miliki dalam data cuaca atau data keuangan. Dalam model BOW sebelumnya, kita telah melihat cara merepresentasikan seluruh rangkaian kata sebagai vektor fitur tunggal. Sekarang kita akan melihat bagaimana merepresentasikan setiap kata sebagai vektor. Ada berbagai cara untuk membuat vektor teks, seperti:
One-Hot Encoding
 
  
The first way to represent a word as a vector is by creating a so-called one-hot encoding, which is simply done by taking a vector of the length of the vocabulary with an entry for each word in the corpus.
+
* Kata-kata diwakili oleh setiap kata sebagai vektor
 +
* Karakter diwakili oleh setiap karakter sebagai vektor
 +
* N-grams dari words/characters diwakili oleh sebuah vector (N-gram adalah kelompok yang saling tumpang tindih dari beberapa kata / karakter berikutnya dalam teks)
  
In this way, you have for each word, given it has a spot in the vocabulary, a vector with zeros everywhere except for the corresponding spot for the word which is set to one. As you might imagine, this can become a fairly large vector for each word and it does not give any additional information like the relationship between words.
+
Dalam tutorial ini, kita akan melihat bagaimana berurusan dengan mewakili kata sebagai vektor yang merupakan cara umum untuk menggunakan teks dalam neural network. Dua cara yang mungkin untuk merepresentasikan sebuah kata sebagai vektor adalah one-hot encoding dan word embedding.
  
Let’s say you have a list of cities as in the following example:
+
==One-Hot Encoding==
  
>>> cities = ['London', 'Berlin', 'Berlin', 'New York', 'London']
+
Cara pertama untuk merepresentasikan sebuah kata sebagai vektor adalah dengan menciptakan apa yang disebut one-hot encoding, yang hanya dilakukan dengan mengambil vektor dari panjang vocabulary dengan entri untuk setiap kata dalam korpus.
>>> cities
 
['London', 'Berlin', 'Berlin', 'New York', 'London']
 
  
You can use scikit-learn and the LabelEncoder to encode the list of cities into categorical integer values like here:
+
Dengan cara ini, untuk setiap kata, kita akan memiliki spot di vocabulary, sebuah vector dengan nilai zero dimana-mana kecuali di spot dari kata tersebut yang di set dengan satu. Seperti yang kita bayangkan, ini bisa menjadi vektor yang cukup besar untuk setiap kata dan tidak memberikan informasi tambahan seperti hubungan antar kata.
  
>>> from sklearn.preprocessing import LabelEncoder
+
Katakanlah kita memiliki daftar kota seperti dalam contoh berikut:
  
>>> encoder = LabelEncoder()
+
cities = ['London', 'Berlin', 'Berlin', 'New York', 'London']
>>> city_labels = encoder.fit_transform(cities)
+
cities
>>> city_labels
 
array([1, 0, 0, 2, 1])
 
  
Using this representation, you can use the OneHotEncoder provided by scikit-learn to encode the categorical values we got before into a one-hot encoded numeric array. OneHotEncoder expects each categorical value to be in a separate row, so you’ll need to reshape the array, then you can apply the encoder:
+
Hasilnya:
  
>>> from sklearn.preprocessing import OneHotEncoder
+
['London', 'Berlin', 'Berlin', 'New York', 'London']
  
>>> encoder = OneHotEncoder(sparse=False)
+
Kita dapat menggunakan scikit-learn dan LabelEncoder untuk meng-encode daftar cities menjadi nilai integer categorical integer sebagai berikut:
>>> city_labels = city_labels.reshape((5, 1))
 
>>> encoder.fit_transform(city_labels)
 
array([[0., 1., 0.],
 
      [1., 0., 0.],
 
      [1., 0., 0.],
 
      [0., 0., 1.],
 
      [0., 1., 0.]])
 
  
You can see that categorical integer value represents the position of the array which is 1 and the rest is 0. This is often used when you have a categorical feature which you cannot represent as a numeric value but you still want to be able to use it in machine learning. One use case for this encoding is of course words in a text but it is most prominently used for categories. Such categories can be for example city, department, or other categories.
+
from sklearn.preprocessing import LabelEncoder
Word Embeddings
+
 +
encoder = LabelEncoder()
 +
city_labels = encoder.fit_transform(cities)
 +
city_labels
  
This method represents words as dense word vectors (also called word embeddings) which are trained unlike the one-hot encoding which are hardcoded. This means that the word embeddings collect more information into fewer dimensions.
+
Hasilnya
  
Note that the word embeddings do not understand the text as a human would, but they rather map the statistical structure of the language used in the corpus. Their aim is to map semantic meaning into a geometric space. This geometric space is then called the embedding space.
+
array([1, 0, 0, 2, 1])
  
This would map semantically similar words close on the embedding space like numbers or colors. If the embedding captures the relationship between words well, things like vector arithmetic should become possible. A famous example in this field of study is the ability to map King - Man + Woman = Queen.
+
Dengan menggunakan representasi ini, kita dapat menggunakan OneHotEncoder yang disediakan oleh scikit-learn untuk mengkodekan nilai categorical yang kita dapatkan sebelumnya ke dalam one-hot encoded numeric array. OneHotEncoder mengharapkan setiap nilai kategorikal berada di baris terpisah, jadi kita harus reshape array, kemudian kita dapat menerapkan encoder:
  
How can you get such a word embedding? You have two options for this. One way is to train your word embeddings during the training of your neural network. The other way is by using pretrained word embeddings which you can directly use in your model. There you have the option to either leave these word embeddings unchanged during training or you train them also.
+
from sklearn.preprocessing import OneHotEncoder
 +
 +
encoder = OneHotEncoder(sparse=False)
 +
city_labels = city_labels.reshape((5, 1))
 +
encoder.fit_transform(city_labels)
  
Now you need to tokenize the data into a format that can be used by the word embeddings. Keras offers a couple of convenience methods for text preprocessing and sequence preprocessing which you can employ to prepare your text.
+
Hasilnya
  
You can start by using the Tokenizer utility class which can vectorize a text corpus into a list of integers. Each integer maps to a value in a dictionary that encodes the entire corpus, with the keys in the dictionary being the vocabulary terms themselves. You can add the parameter num_words, which is responsible for setting the size of the vocabulary. The most common num_words words will be then kept. I have the testing and training data prepared from the previous example:
+
array([[0., 1., 0.],
 +
        [1., 0., 0.],
 +
        [1., 0., 0.],
 +
        [0., 0., 1.],
 +
        [0., 1., 0.]])
  
>>> from keras.preprocessing.text import Tokenizer
+
Kita dapat melihat bahwa categorical integer value mewakili posisi array yaitu 1 dan sisanya 0. Ini sering digunakan ketika kita memiliki categorical feature yang tidak dapat kita wakili sebagai nilai numerik tetapi kita masih ingin dapat menggunakannya dalam machine learning. Satu kasus penggunaan untuk pengkodean ini tentu saja kata-kata dalam teks tetapi paling jelas digunakan untuk kategori. Kategori tersebut dapat berupa kota, departemen, atau kategori lainnya.
  
>>> tokenizer = Tokenizer(num_words=5000)
+
==Word Embeddings==
>>> tokenizer.fit_on_texts(sentences_train)
 
  
>>> X_train = tokenizer.texts_to_sequences(sentences_train)
+
Metode ini mewakili kata-kata sebagai vektor kata yang padat (juga disebut word embeddings) yang di-train tidak seperti one-hot encoding. Ini berarti bahwa word embeddings mengumpulkan lebih banyak informasi ke dimensi yang lebih kecil.
>>> X_test = tokenizer.texts_to_sequences(sentences_test)
 
  
>>> vocab_size = len(tokenizer.word_index) + 1  # Adding 1 because of reserved 0 index
+
Perhatikan bahwa word embeddings tidak memahami teks seperti yang dilakukan manusia, tetapi mereka lebih memetakan struktur statistik dari bahasa yang digunakan dalam corpus. Tujuan mereka adalah memetakan makna semantik ke dalam ruang geometris. Ruang geometris ini kemudian disebut ruang embedding.
  
>>> print(sentences_train[2])
+
Ini akan memetakan kata-kata yang mirip secara semantik yang menutup pada ruang embedding seperti angka atau warna. Jika embedding menangkap hubungan antara kata-kata dengan baik, hal-hal seperti vektor aritmatika harusnya dimungkinkan. Contoh terkenal dalam bidang studi ini adalah kemampuan untuk memetakan King - Man + Woman = Queen.
>>> print(X_train[2])
 
Of all the dishes, the salmon was the best, but all were great.
 
[11, 43, 1, 171, 1, 283, 3, 1, 47, 26, 43, 24, 22]
 
  
The indexing is ordered after the most common words in the text, which you can see by the word the having the index 1. It is important to note that the index 0 is reserved and is not assigned to any word. This zero index is used for padding, which I’ll introduce in a moment.
+
Bagaimana kita bisa mendapatkan word embedding seperti itu? Kita memiliki dua opsi untuk ini. Salah satu caranya adalah melatih word embeddings anda selama men-training neural network anda. Cara lain adalah dengan menggunakan word embeddings pretrained yang dapat anda langsung gunakan dalam model anda. Di sana anda memiliki opsi untuk membiarkan word embedding ini tidak berubah selama pelatihan atau anda melatihnya juga.
  
Unknown words (words that are not in the vocabulary) are denoted in Keras with word_count + 1 since they can also hold some information. You can see the index of each word by taking a look at the word_index dictionary of the Tokenizer object:
+
Sekarang kita perlu melakukan tokenize data menjadi format yang dapat digunakan oleh word embeddings. Keras menawarkan beberapa metode untuk kenyamanan preprocessing teks dan preprocessing urutan yang dapat kita terapkan untuk mempersiapkan teks.
  
>>> for word in ['the', 'all', 'happy', 'sad']:
+
Kita dapat mulai dengan menggunakan class utlity Tokenizer yang dapat membuat vektor dari corpus teks menjadi daftar bilangan integer. Setiap integer memetakan suatu nilai dalam dictionary yang meng-encode seluruh korpus, dengan kunci dalam dictionary menjadi istilah dalam vocabulary itu sendiri. Kita dapat menambahkan parameter num_words, yang bertanggung jawab untuk mengatur ukuran vocabulary. Kata-kata num_words paling umum akan disimpan. Kita telah memiliki data pengujian dan pelatihan yang disiapkan dari contoh sebelumnya:
...    print('{}: {}'.format(word, tokenizer.word_index[word]))
 
the: 1
 
all: 43
 
happy: 320
 
sad: 450
 
  
Note: Pay close attention to the difference between this technique and the X_train that was produced by scikit-learn’s CountVectorizer.
+
from keras.preprocessing.text import Tokenizer
 +
 +
tokenizer = Tokenizer(num_words=5000)
 +
tokenizer.fit_on_texts(sentences_train)
 +
 +
X_train = tokenizer.texts_to_sequences(sentences_train)
 +
X_test = tokenizer.texts_to_sequences(sentences_test)
 +
 +
vocab_size = len(tokenizer.word_index) + 1  # Adding 1 because of reserved 0 index
 +
 +
print(sentences_train[2])
 +
print(X_train[2])
  
With CountVectorizer, we had stacked vectors of word counts, and each vector was the same length (the size of the total corpus vocabulary). With Tokenizer, the resulting vectors equal the length of each text, and the numbers don’t denote counts, but rather correspond to the word values from the dictionary tokenizer.word_index.
+
Hasilnya
  
One problem that we have is that each text sequence has in most cases different length of words. To counter this, you can use pad_sequence() which simply pads the sequence of words with zeros. By default, it prepends zeros but we want to append them. Typically it does not matter whether you prepend or append zeros.
+
Of all the dishes, the salmon was the best, but all were great.
 +
[11, 43, 1, 171, 1, 283, 3, 1, 47, 26, 43, 24, 22]
  
Additionally you would want to add a maxlen parameter to specify how long the sequences should be. This cuts sequences that exceed that number. In the following code, you can see how to pad sequences with Keras:
+
Pengindeksan diurutkan sesuai dengan kata-kata yang paling umum dalam teks, yang dapat kita lihat dengan kata memiliki indeks 1. Penting untuk dicatat bahwa indeks 0 dicadangkan dan tidak diberikan untuk kata apa pun. Indeks nol ini digunakan untuk padding, yang akan  diperkenalkan sebentar lagi.
  
>>> from keras.preprocessing.sequence import pad_sequences
+
Kata-kata yang tidak dikenal (kata-kata yang tidak ada dalam vocabulary) dilambangkan dalam Keras dengan word_count +1 karena mereka juga dapat menyimpan beberapa informasi. Kita dapat melihat indeks setiap kata dengan melihat kamus word_index dari objek Tokenizer:
  
>>> maxlen = 100
+
for word in ['the', 'all', 'happy', 'sad']:
 +
    print('{}: {}'.format(word, tokenizer.word_index[word]))
  
>>> X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
+
Hasilnya
>>> X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)
 
  
>>> print(X_train[0, :])
+
the: 1
[ 1 10  3 282 739  25  8 208  30  64 459 230  13  1 124  5 231  8
+
  all: 43
  58  5 67  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
+
  happy: 320
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
+
  sad: 450
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 
  0  0  0  0  0  0  0  0  0  0]
 
  
The first values represent the index in the vocabulary as you have learned from the previous examples. You can also see that the resulting feature vector contains mostly zeros, since you have a fairly short sentence. In the next part you will see how to work with word embeddings in Keras.
+
Catatan: Perhatikan perbedaan antara teknik ini dan X_train yang diproduksi oleh CountVectorizer scikit-learn.
Keras Embedding Layer
 
  
Notice that, at this point, our data is still hardcoded. We have not told Keras to learn a new embedding space through successive tasks. Now you can use the Embedding Layer of Keras which takes the previously calculated integers and maps them to a dense vector of the embedding. You will need the following parameters:
+
Dengan CountVectorizer, kami telah menumpuk vektor jumlah kata, dan masing-masing vektor memiliki panjang yang sama (ukuran total corpus vocabulary). Dengan Tokenizer, vektor yang dihasilkan sama dengan panjang setiap teks, dan angka tidak menunjukkan jumlah, tetapi lebih sesuai dengan nilai kata dari dictionary tokenizer.word_index.
  
    input_dim: the size of the vocabulary
+
Satu masalah yang kita miliki adalah bahwa setiap urutan teks memiliki panjang kata yang berbeda. Untuk mengatasinya, Anda dapat menggunakan pad_afterence() yang akan mengisi urutan kata dengan nol. Secara default, ini akan prepend nol tetapi kami ingin append nol. Biasanya tidak masalah apakah kita akan me-prepend atau append nol.
    output_dim: the size of the dense vector
 
    input_length: the length of the sequence
 
  
With the Embedding layer we have now a couple of options. One way would be to take the output of the embedding layer and plug it into a Dense layer. In order to do this you have to add a Flatten layer in between that prepares the sequential input for the Dense layer:
+
Selain itu kita ingin menambahkan parameter maxlen untuk menentukan berapa lama urutannya. Ini memotong urutan yang melebihi angka itu. Dalam kode berikut, kita dapat melihat cara menambahkan urutan dengan Keras:
  
from keras.models import Sequential
+
from keras.preprocessing.sequence import pad_sequences
from keras import layers
+
 +
maxlen = 100
 +
 +
X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
 +
X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)
 +
 +
print(X_train[0, :])
  
embedding_dim = 50
+
Hasilnya
  
model = Sequential()
+
[  1  10  3 282 739  25  8 208  30  64 459 230  13  1 124  5 231  8
model.add(layers.Embedding(input_dim=vocab_size,
+
  58  5  67  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
                          output_dim=embedding_dim,
+
    0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
                          input_length=maxlen))
+
    0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
model.add(layers.Flatten())
+
    0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
model.add(layers.Dense(10, activation='relu'))
+
    0  0  0  0  0  0  0  0  0  0]
model.add(layers.Dense(1, activation='sigmoid'))
 
model.compile(optimizer='adam',
 
              loss='binary_crossentropy',
 
              metrics=['accuracy'])
 
model.summary()
 
  
The result will be as follows:
+
Nilai pertama merepresentasikan indeks dalam vocabulary seperti yang telah kita pelajari dari contoh sebelumnya. Kita juga dapat melihat bahwa feature vector yang dihasilkan sebagian besar berisi nol, karena kita memiliki kalimat yang cukup pendek. Di bagian selanjutnya kita akan melihat cara bekerja dengan word embeddings di Keras.
  
_________________________________________________________________
+
==Keras Embedding Layer==
Layer (type)                Output Shape              Param # 
 
=================================================================
 
embedding_8 (Embedding)      (None, 100, 50)          87350   
 
_________________________________________________________________
 
flatten_3 (Flatten)          (None, 5000)              0       
 
_________________________________________________________________
 
dense_13 (Dense)            (None, 10)                50010   
 
_________________________________________________________________
 
dense_14 (Dense)            (None, 1)                11       
 
=================================================================
 
Total params: 137,371
 
Trainable params: 137,371
 
Non-trainable params: 0
 
_________________________________________________________________
 
  
You can now see that we have 87350 new parameters to train. This number comes from vocab_size times the embedding_dim. These weights of the embedding layer are initialized with random weights and are then adjusted through backpropagation during training. This model takes the words as they come in the order of the sentences as input vectors. You can train it with the following:
+
Perhatikan bahwa, pada titik ini, data kita masih di encode secara hardcoded. Kita belum memberi tahu Keras untuk mempelajari ruang embedding baru melalui tugas yang berurutan. Sekarang kita dapat menggunakan Layer Embedding Keras yang mengambil bilangan integer yang dihitung sebelumnya dan memetakannya ke dense vector dari embedding. Kita membutuhkan parameter berikut:
  
history = model.fit(X_train, y_train,
+
input_dim: ukuran vocabulary
                    epochs=20,
+
output_dim: ukuran dense vector
                    verbose=False,
+
  input_length: panjang sequence / urutan
                    validation_data=(X_test, y_test),
 
                    batch_size=10)
 
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 
print("Training Accuracy: {:.4f}".format(accuracy))
 
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 
print("Testing Accuracy: {:.4f}".format(accuracy))
 
plot_history(history)
 
  
The result will be as follows:
+
Dengan layer Embedding sekarang kita memiliki beberapa opsi. Salah satu caranya adalah dengan mengambil output dari lapisan embedding dan memasukannya ke Dense layer. Untuk melakukan ini, kita harus menambahkan Flatten layer di antaranya yang menyiapkan sequential input untuk Dense layer:
  
Training Accuracy: 0.5100
+
from keras.models import Sequential
Testing Accuracy: 0.4600
+
from keras import layers
 +
 +
embedding_dim = 50
 +
 +
model = Sequential()
 +
model.add(layers.Embedding(input_dim=vocab_size,
 +
                            output_dim=embedding_dim,
 +
                            input_length=maxlen))
 +
model.add(layers.Flatten())
 +
model.add(layers.Dense(10, activation='relu'))
 +
model.add(layers.Dense(1, activation='sigmoid'))
 +
model.compile(optimizer='adam',
 +
              loss='binary_crossentropy',
 +
              metrics=['accuracy'])
 +
  model.summary()
  
loss accuracy first model
+
The result will be as follows:
Accuracy and loss for first model
 
  
This is typically a not very reliable way to work with sequential data as you can see in the performance. When working with sequential data you want to focus on methods that look at local and sequential information instead of absolute positional information.
+
_________________________________________________________________
 +
Layer (type)                Output Shape              Param # 
 +
=================================================================
 +
embedding_8 (Embedding)      (None, 100, 50)          87350   
 +
_________________________________________________________________
 +
flatten_3 (Flatten)          (None, 5000)              0       
 +
_________________________________________________________________
 +
dense_13 (Dense)            (None, 10)                50010   
 +
_________________________________________________________________
 +
dense_14 (Dense)            (None, 1)                11       
 +
=================================================================
 +
Total params: 137,371
 +
Trainable params: 137,371
 +
Non-trainable params: 0
 +
_________________________________________________________________
  
Another way to work with embeddings is by using a MaxPooling1D/AveragePooling1D or a GlobalMaxPooling1D/GlobalAveragePooling1D layer after the embedding. You can think of the pooling layers as a way to downsample (a way to reduce the size of) the incoming feature vectors.
+
Kita sekarang dapat melihat bahwa kita memiliki 87350 parameter baru untuk di-training. Angka ini berasal dari vocab_size di kali dengan embedding_dim. Weight di lapisan embedding ini di inisialisasi dengan Weight acak dan kemudian disesuaikan melalui backpropagation selama pelatihan. Model ini mengambil kata-kata ketika datang dalam urutan kalimat sebagai vektor input. Kita dapat melatihnya sebagai berikut:
  
In the case of max pooling you take the maximum value of all features in the pool for each feature dimension. In the case of average pooling you take the average, but max pooling seems to be more commonly used as it highlights large values.
+
history = model.fit(X_train, y_train,
 +
                    epochs=20,
 +
                    verbose=False,
 +
                    validation_data=(X_test, y_test),
 +
                    batch_size=10)
 +
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 +
print("Training Accuracy: {:.4f}".format(accuracy))
 +
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 +
print("Testing Accuracy:  {:.4f}".format(accuracy))
 +
plot_history(history)
  
Global max/average pooling takes the maximum/average of all features whereas in the other case you have to define the pool size. Keras has again its own layer that you can add in the sequential model:
+
Hasilnya
  
from keras.models import Sequential
+
Training Accuracy: 0.5100
from keras import layers
+
Testing Accuracy:  0.4600
  
embedding_dim = 50
 
  
model = Sequential()
+
[[File:Loss-accuracy-first-model.png|center|400px|tumb]]
model.add(layers.Embedding(input_dim=vocab_size,
 
                          output_dim=embedding_dim,
 
                          input_length=maxlen))
 
model.add(layers.GlobalMaxPool1D())
 
model.add(layers.Dense(10, activation='relu'))
 
model.add(layers.Dense(1, activation='sigmoid'))
 
model.compile(optimizer='adam',
 
              loss='binary_crossentropy',
 
              metrics=['accuracy'])
 
model.summary()
 
  
The result will be as follows:
+
Ini biasanya bukan cara yang sangat andal untuk bekerja dengan data berurutan seperti yang kita lihat dalam kinerja. Saat bekerja dengan data sekuensial, kita ingin fokus pada metode yang melihat informasi lokal dan berurutan daripada informasi posisi absolut.
  
_________________________________________________________________
+
Cara lain untuk bekerja dengan embeddings adalah dengan menggunakan lapisan MaxPooling1D/AveragePooling1D atau GlobalMaxPooling1D/GlobalAveragePooling1D setelah embedding. Kita dapat menganggap layer pooling sebagai cara untuk menurunkan sampel (cara untuk mengurangi ukuran) feature vector yang masuk.
Layer (type)                 Output Shape              Param # 
 
=================================================================
 
embedding_9 (Embedding)      (None, 100, 50)          87350   
 
_________________________________________________________________
 
global_max_pooling1d_5 (Glob (None, 50)                0       
 
_________________________________________________________________
 
dense_15 (Dense)            (None, 10)                510     
 
_________________________________________________________________
 
dense_16 (Dense)            (None, 1)                11       
 
=================================================================
 
Total params: 87,871
 
Trainable params: 87,871
 
Non-trainable params: 0
 
_________________________________________________________________
 
  
The procedure for training does not change:
+
Dalam hal pooling max, kita mengambil nilai maksimum semua fitur di pooling untuk setiap dimensi feature. Dalam hal average pooling kita  mengambil rata-rata, tetapi max pooling tampaknya lebih umum digunakan karena menyoroti nilai-nilai besar.
  
history = model.fit(X_train, y_train,
+
Global max/average pooling mengambil maximum/average dari semua feature sementara dalam kasus lainnya kita harus menentukan pool size. Keras sudah memiliki lapisannya sendiri yang dapat kita tambahkan dalam model sekuensial:
                    epochs=50,
 
                    verbose=False,
 
                    validation_data=(X_test, y_test),
 
                    batch_size=10)
 
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 
print("Training Accuracy: {:.4f}".format(accuracy))
 
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 
print("Testing Accuracy:  {:.4f}".format(accuracy))
 
plot_history(history)
 
  
The result will be as follows:
+
from keras.models import Sequential
 +
from keras import layers
 +
 +
embedding_dim = 50
 +
 +
model = Sequential()
 +
model.add(layers.Embedding(input_dim=vocab_size,
 +
                            output_dim=embedding_dim,
 +
                            input_length=maxlen))
 +
model.add(layers.GlobalMaxPool1D())
 +
model.add(layers.Dense(10, activation='relu'))
 +
model.add(layers.Dense(1, activation='sigmoid'))
 +
model.compile(optimizer='adam',
 +
              loss='binary_crossentropy',
 +
              metrics=['accuracy'])
 +
model.summary()
  
Training Accuracy: 1.0000
+
Hasilnya:
Testing Accuracy:  0.8050
 
  
loss accurcay max pooling
+
_________________________________________________________________
Accuracy and loss for max pooling model
+
Layer (type)                Output Shape              Param # 
 +
=================================================================
 +
embedding_9 (Embedding)      (None, 100, 50)          87350   
 +
_________________________________________________________________
 +
global_max_pooling1d_5 (Glob (None, 50)                0       
 +
_________________________________________________________________
 +
dense_15 (Dense)            (None, 10)                510     
 +
_________________________________________________________________
 +
dense_16 (Dense)            (None, 1)                11       
 +
=================================================================
 +
Total params: 87,871
 +
Trainable params: 87,871
 +
Non-trainable params: 0
 +
_________________________________________________________________
  
You can already see some improvements in our models. Next you’ll see how we can employ pretrained word embeddings and if they help us with our model.
+
Prosedur untuk training tidak berubah:
Using Pretrained Word Embeddings
 
  
We just saw an example of jointly learning word embeddings incorporated into the larger model that we want to solve.
+
history = model.fit(X_train, y_train,
 +
                    epochs=50,
 +
                    verbose=False,
 +
                    validation_data=(X_test, y_test),
 +
                    batch_size=10)
 +
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 +
print("Training Accuracy: {:.4f}".format(accuracy))
 +
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 +
print("Testing Accuracy:  {:.4f}".format(accuracy))
 +
plot_history(history) 
 +
 +
Hasil
  
An alternative is to use a precomputed embedding space that utilizes a much larger corpus. It is possible to precompute word embeddings by simply training them on a large corpus of text. Among the most popular methods are Word2Vec developed by Google and GloVe (Global Vectors for Word Representation) developed by the Stanford NLP Group.
+
Training Accuracy: 1.0000
 +
Testing Accuracy:  0.8050
  
Note that those are different approaches with the same goal. Word2Vec achieves this by employing neural networks and GloVe achieves this with a co-occurrence matrix and by using matrix factorization. In both cases you are dealing with dimensionality reduction, but Word2Vec is more accurate and GloVe is faster to compute.
+
[[File:Loss-accurcay-max-pooling2.png|center|400px|thumb]]
  
In this tutorial, you’ll see how to work with the GloVe word embeddings from the Stanford NLP Group as their size is more manageable than the Word2Vec word embeddings provided by Google. Go ahead and download the 6B (trained on 6 billion words) word embeddings from here (822 MB).
+
Kita sudah dapat melihat beberapa peningkatan dalam model  kita. Selanjutnya kita akan melihat bagaimana kita dapat menggunakan pretrained word embeddings dan jika hal tersebut bisa membantu kita dengan model yang kita gunakan.
  
You can find other word embeddings also on the main GloVe page. You can find the pretrained Word2Vec embeddings by Google here. If you want to train your own word embeddings, you can do so efficiently with the gensim Python package which uses Word2Vec for calculation. More details on how to do this here.
+
==Penggunaan Pretrained Word Embeddings==
  
Now that we got you covered, you can start using the word embeddings in your models. You can see in the next example how you can load the embedding matrix. Each line in the file starts with the word and is followed by the embedding vector for the particular word.
+
Kita baru saja melihat contoh belajar word embeddings yang dimasukkan ke dalam model yang lebih besar yang ingin kita pecahkan.
  
This is a large file with 400000 lines, with each line representing a word followed by its vector as a stream of floats. For example, here are the first 50 characters of the first line:
+
Alternatif lain adalah dengan menggunakan ruang embedding yang dikomputasi yang menggunakan corpus yang jauh lebih besar. Dimungkinkan untuk memulai word embedding dengan hanya melatihnya pada kumpulan teks yang besar. Di antara metode yang paling populer adalah Word2Vec yang dikembangkan oleh Google dan GloVe (Global Vectors for Word Representation) yang dikembangkan oleh Stanford NLP Group.
  
$ head -n 1 data/glove_word_embeddings/glove.6B.50d.txt | cut -c-50
+
Perhatikan bahwa itu adalah pendekatan yang berbeda dengan tujuan yang sama. Word2Vec mencapai ini dengan menggunakan neural networks dan GloVe mencapainya dengan  co-occurrence matrix bersama dan dengan menggunakan faktorisasi matriks. Dalam kedua kasus kita akan berurusan dengan pengurangan dimensionalitas, tetapi Word2Vec lebih akurat dan GloVe lebih cepat untuk dihitung.
    the 0.418 0.24968 -0.41242 0.1217 0.34527 -0.04445
 
  
Since you don’t need all words, you can focus on only the words that we have in our vocabulary. Since we have only a limited number of words in our vocabulary, we can skip most of the 40000 words in the pretrained word embeddings:
+
Dalam tutorial ini, kita akan melihat cara bekerja dengan word embeddings GloVe dan bukan Stanford NLP Group karena ukurannya lebih mudah dikelola daripada embeddings Word2Vec yang disediakan oleh Google. Silakan dan unduh word embeddings 6B (terlatih 6 miliar kata) dari http://nlp.stanford.edu/data/glove.6B.zip (822 MB).
  
import numpy as np
+
Kita dapat menemukan word embeddings lainnya juga di halaman utama GloVe https://nlp.stanford.edu/projects/glove/. Kita dapat menemukan pretrained Word2Vec embeddings oleh Google di https://code.google.com/archive/p/word2vec/ . Jika anda ingin melatih word embeddings anda sendiri, anda dapat melakukannya secara efisien dengan paket gensim Python https://radimrehurek.com/gensim/index.html yang menggunakan Word2Vec untuk perhitungan. Rincian lebih lanjut tentang cara melakukan ini di https://radimrehurek.com/gensim/models/word2vec.html .
  
def create_embedding_matrix(filepath, word_index, embedding_dim):
+
Kita dapat mulai menggunakan word embeddings dalam model kita. Kita dapat melihat pada contoh berikut bagaimana kita dapat memuat embedding matrix. Setiap baris dalam file dimulai dengan kata dan diikuti oleh embedding vector untuk kata tertentu.
    vocab_size = len(word_index) + 1  # Adding again 1 because of reserved 0 index
 
    embedding_matrix = np.zeros((vocab_size, embedding_dim))
 
  
    with open(filepath) as f:
+
Ini adalah file besar dengan 400.000 baris, dengan setiap baris mewakili kata yang diikuti oleh vektornya sebagai aliran floating point. Misalnya, berikut adalah 50 karakter pertama dari baris pertama:
        for line in f:
 
            word, *vector = line.split()
 
            if word in word_index:
 
                idx = word_index[word]
 
                embedding_matrix[idx] = np.array(
 
                    vector, dtype=np.float32)[:embedding_dim]
 
  
    return embedding_matrix
+
$ head -n 1 glove.6B/glove.6B.50d.txt | cut -c-50
 +
    the 0.418 0.24968 -0.41242 0.1217 0.34527 -0.04445
  
You can use this function now to retrieve the embedding matrix:
+
Karena kita tidak membutuhkan semua kata, kita hanya dapat fokus pada kata-kata yang kita miliki dalam vocabulary kita. Karena kita hanya memiliki jumlah kata yang terbatas dalam vocabulary kita, kita dapat melewatkan sebagian besar dari 40000 kata dalam  pretrained word embeddings:
  
>>> embedding_dim = 50
+
import numpy as np
>>> embedding_matrix = create_embedding_matrix(
+
...    'data/glove_word_embeddings/glove.6B.50d.txt',
+
def create_embedding_matrix(filepath, word_index, embedding_dim):
...    tokenizer.word_index, embedding_dim)
+
    vocab_size = len(word_index) + 1  # Adding again 1 because of reserved 0 index
 +
    embedding_matrix = np.zeros((vocab_size, embedding_dim))
 +
 +
    with open(filepath) as f:
 +
        for line in f:
 +
            word, *vector = line.split()
 +
            if word in word_index:
 +
                idx = word_index[word]
 +
                embedding_matrix[idx] = np.array(
 +
                        vector, dtype=np.float32)[:embedding_dim]
 +
    return embedding_matrix
  
Wonderful! Now you are ready to use the embedding matrix in training. Let’s go ahead and use the previous network with global max pooling and see if we can improve this model. When you use pretrained word embeddings you have the choice to either allow the embedding to be updated during training or only use the resulting embedding vectors as they are.
+
Kita dapat menggunakan fungsi ini sekarang untuk mengambil embedding matrix:
  
First, let’s have a quick look how many of the embedding vectors are nonzero:
+
embedding_dim = 50
 +
embedding_matrix = create_embedding_matrix(
 +
        '/home/onno/TensorFlow/glove.6B/glove.6B.50d.txt',
 +
        tokenizer.word_index, embedding_dim)
  
>>> nonzero_elements = np.count_nonzero(np.count_nonzero(embedding_matrix, axis=1))
+
Sekarang kita siap menggunakan embedding matrix dalam training. Mari gunakan network sebelumnya dengan global max pooling dan lihat apakah kita bisa meningkatkan model ini. Saat kita menggunakan pretrained word embeddings  kita memiliki pilihan untuk memperbolehkan embedding diperbarui selama training atau hanya menggunakan embedding vectors yang dihasilkan apa adanya.
>>> nonzero_elements / vocab_size
 
0.9507727532913566
 
  
This means 95.1% of the vocabulary is covered by the pretrained model, which is a good coverage of our vocabulary. Let’s have a look at the performance when using the GlobalMaxPool1D layer:
+
Pertama, mari kita lihat sekilas berapa banyak embedding vectors yang bukan nol:
  
model = Sequential()
+
nonzero_elements = np.count_nonzero(np.count_nonzero(embedding_matrix, axis=1))
model.add(layers.Embedding(vocab_size, embedding_dim,
+
print(nonzero_elements / vocab_size)
                          weights=[embedding_matrix],
 
                          input_length=maxlen,
 
                          trainable=False))
 
model.add(layers.GlobalMaxPool1D())
 
model.add(layers.Dense(10, activation='relu'))
 
model.add(layers.Dense(1, activation='sigmoid'))
 
model.compile(optimizer='adam',
 
              loss='binary_crossentropy',
 
              metrics=['accuracy'])
 
model.summary()
 
  
The result will be as follows:
+
Hasilnya:
  
_________________________________________________________________
+
0.9522330097087378
Layer (type)                Output Shape              Param # 
 
=================================================================
 
embedding_10 (Embedding)    (None, 100, 50)          87350   
 
_________________________________________________________________
 
global_max_pooling1d_6 (Glob (None, 50)                0        
 
_________________________________________________________________
 
dense_17 (Dense)            (None, 10)                510     
 
_________________________________________________________________
 
dense_18 (Dense)            (None, 1)                11       
 
=================================================================
 
Total params: 87,871
 
Trainable params: 521
 
Non-trainable params: 87,350
 
_________________________________________________________________
 
  
history = model.fit(X_train, y_train,
+
Ini berarti 95.1% dari vocabulary tercakup oleh pretrained model, yang merupakan cakupan yang baik dari vocabulary kita. Mari kita lihat kinerja ketika menggunakan lapisan GlobalMaxPool1D:
                    epochs=50,
 
                    verbose=False,
 
                    validation_data=(X_test, y_test),
 
                    batch_size=10)
 
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 
print("Training Accuracy: {:.4f}".format(accuracy))
 
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 
print("Testing Accuracy: {:.4f}".format(accuracy))
 
plot_history(history)
 
  
The result will be as follows:
+
model = Sequential()
 +
model.add(layers.Embedding(vocab_size, embedding_dim,
 +
                            weights=[embedding_matrix],
 +
                            input_length=maxlen,
 +
                            trainable=False))
 +
model.add(layers.GlobalMaxPool1D())
 +
model.add(layers.Dense(10, activation='relu'))
 +
model.add(layers.Dense(1, activation='sigmoid'))
 +
model.compile(optimizer='adam',
 +
              loss='binary_crossentropy',
 +
              metrics=['accuracy'])
 +
model.summary()
  
Training Accuracy: 0.7500
+
Hasilnya:
Testing Accuracy:  0.6950
 
  
loss accuracy embedding untrained
+
_________________________________________________________________
Accuracy and loss for untrained word embeddings
+
Layer (type)                Output Shape              Param # 
 +
=================================================================
 +
embedding_10 (Embedding)    (None, 100, 50)          87350   
 +
_________________________________________________________________
 +
global_max_pooling1d_6 (Glob (None, 50)                0       
 +
_________________________________________________________________
 +
dense_17 (Dense)            (None, 10)                510     
 +
_________________________________________________________________
 +
dense_18 (Dense)            (None, 1)                11       
 +
=================================================================
 +
Total params: 87,871
 +
Trainable params: 521
 +
Non-trainable params: 87,350
 +
_________________________________________________________________
  
Since the word embeddings are not additionally trained, it is expected to be lower. But let’s now see how this performs if we allow the embedding to be trained by using trainable=True:
+
history = model.fit(X_train, y_train,
 +
                    epochs=50,
 +
                    verbose=False,
 +
                    validation_data=(X_test, y_test),
 +
                    batch_size=10)
 +
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 +
print("Training Accuracy: {:.4f}".format(accuracy))
 +
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 +
print("Testing Accuracy: {:.4f}".format(accuracy))
 +
plot_history(history)
  
model = Sequential()
+
Hasilnya:
model.add(layers.Embedding(vocab_size, embedding_dim,
 
                          weights=[embedding_matrix],
 
                          input_length=maxlen,
 
                          trainable=True))
 
model.add(layers.GlobalMaxPool1D())
 
model.add(layers.Dense(10, activation='relu'))
 
model.add(layers.Dense(1, activation='sigmoid'))
 
model.compile(optimizer='adam',
 
              loss='binary_crossentropy',
 
              metrics=['accuracy'])
 
model.summary()
 
  
The result will be as follows:
+
Training Accuracy: 0.7500
 +
Testing Accuracy:  0.6950
  
_________________________________________________________________
 
Layer (type)                Output Shape              Param # 
 
=================================================================
 
embedding_11 (Embedding)    (None, 100, 50)          87350   
 
_________________________________________________________________
 
global_max_pooling1d_7 (Glob (None, 50)                0       
 
_________________________________________________________________
 
dense_19 (Dense)            (None, 10)                510     
 
_________________________________________________________________
 
dense_20 (Dense)            (None, 1)                11       
 
=================================================================
 
Total params: 87,871
 
Trainable params: 87,871
 
Non-trainable params: 0
 
_________________________________________________________________
 
  
history = model.fit(X_train, y_train,
+
[[File:Loss-accuracy-embedding-untrained.png|center|400px|thumb]]
                    epochs=50,
 
                    verbose=False,
 
                    validation_data=(X_test, y_test),
 
                    batch_size=10)
 
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 
print("Training Accuracy: {:.4f}".format(accuracy))
 
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 
print("Testing Accuracy:  {:.4f}".format(accuracy))
 
plot_history(history)
 
  
The result will be as follows:
+
Karena word embeddings tidak memperoleh training tambahan, maka hasilnya akan lebih rendah. Tetapi sekarang mari kita lihat bagaimana kinerjanya jika kita mengizinkan embedding untuk di training dengan menggunakan trainable=True:
  
Training Accuracy: 1.0000
+
model = Sequential()
Testing Accuracy: 0.8250
+
model.add(layers.Embedding(vocab_size, embedding_dim,
 +
                            weights=[embedding_matrix],
 +
                            input_length=maxlen,
 +
                            trainable=True))
 +
model.add(layers.GlobalMaxPool1D())
 +
model.add(layers.Dense(10, activation='relu'))
 +
model.add(layers.Dense(1, activation='sigmoid'))
 +
model.compile(optimizer='adam',
 +
              loss='binary_crossentropy',
 +
              metrics=['accuracy'])
 +
  model.summary()
  
loss accuracy embedding trained
+
Hasilnya:
Accuracy and Loss for pretrained word embeddings
 
  
You can see that it is most effective to allow the embeddings to be trained. When dealing with large training sets it can boost the training process to be much faster than without. In our case it seemed to help but not by much. This does not have to be because of pretrained word embeddings.
+
_________________________________________________________________
 +
Layer (type)                Output Shape              Param # 
 +
=================================================================
 +
embedding_11 (Embedding)    (None, 100, 50)          87350   
 +
_________________________________________________________________
 +
global_max_pooling1d_7 (Glob (None, 50)                0       
 +
_________________________________________________________________
 +
dense_19 (Dense)            (None, 10)                510     
 +
_________________________________________________________________
 +
dense_20 (Dense)            (None, 1)                11       
 +
=================================================================
 +
Total params: 87,871
 +
Trainable params: 87,871
 +
Non-trainable params: 0
 +
_________________________________________________________________
  
Now it is time to focus on a more advanced neural network model to see if it is possible to boost the model and give it the leading edge over the previous models.
+
history = model.fit(X_train, y_train,
Convolutional Neural Networks (CNN)
+
                    epochs=50,
 +
                    verbose=False,
 +
                    validation_data=(X_test, y_test),
 +
                    batch_size=10)
 +
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 +
print("Training Accuracy: {:.4f}".format(accuracy))
 +
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 +
print("Testing Accuracy:  {:.4f}".format(accuracy))
 +
plot_history(history)
  
Convolutional neural networks or also called convnets are one of the most exciting developments in machine learning in recent years.
+
Hasilnya:
  
They have revolutionized image classification and computer vision by being able to extract features from images and using them in neural networks. The properties that made them useful in image processing makes them also handy for sequence processing. You can imagine a CNN as a specialized neural network that is able to detect specific patterns.
+
Training Accuracy: 1.0000
 +
Testing Accuracy:  0.8250
  
If it is just another neural network, what differentiates it from what you have previously learned?
+
[[File:Loss-accuracy-embedding-trained.png|center|400px|thub]]
  
A CNN has hidden layers which are called convolutional layers. When you think of images, a computer has to deal with a two dimensional matrix of numbers and therefore you need some way to detect features in this matrix. These convolutional layers are able to detect edges, corners and other kinds of textures which makes them such a special tool. The convolutional layer consists of multiple filters which are slid across the image and are able to detect specific features.
+
Kita dapat lihat bahwa paling efektif jika mengijinkan embeddings di train. Ketika berhadapan dengan set training yang besar, itu dapat meningkatkan proses training menjadi lebih cepat daripada tanpa. Dalam kasus kita, itu tampaknya membantu tetapi tidak banyak. Ini tidak harus karena pretrained word embeddings.
  
This is the very core of the technique, the mathematical process of convolution. With each convolutional layer the network is able to detect more complex patterns. In the Feature Visualization by Chris Olah you can get a good intuition what these features can look like.
+
Sekarang saatnya untuk fokus pada model neural network yang lebih maju untuk melihat apakah mungkin untuk meningkatkan model dan memberikan keunggulan pada model-model sebelumnya.
  
When you are working with sequential data, like text, you work with one dimensional convolutions, but the idea and the application stays the same. You still want to pick up on patterns in the sequence which become more complex with each added convolutional layer.
+
==Convolutional Neural Networks (CNN)==
  
In the next figure you can see how such a convolution works. It starts by taking a patch of input features with the size of the filter kernel. With this patch you take the dot product of the multiplied weights of the filter. The one dimensional convnet is invariant to translations, which means that certain sequences can be recognized at a different position. This can be helpful for certain patterns in the text:
+
Convolutional neural networks atau disebut juga convnets adalah salah satu perkembangan paling menarik dalam machine learning dalam beberapa tahun terakhir.
one dimensional convolution
 
1D Convolution (Image source)
 
  
Now let’s have a look how you can use this network in Keras. Keras offers again various Convolutional layers which you can use for this task. The layer you’ll need is the Conv1D layer. This layer has again various parameters to choose from. The ones you are interested in for now are the number of filters, the kernel size, and the activation function. You can add this layer in between the Embedding layer and the GlobalMaxPool1D layer:
+
Mereka telah merevolusi klasifikasi gambar dan computer vision dengan mampu mengekstraksi fitur dari gambar dan menggunakannya dalam neural networks. Properti yang membuatnya berguna dalam pemrosesan gambar membuat mereka juga berguna untuk pemrosesan urutan. Anda dapat membayangkan CNN sebagai specialized neural network yang mampu mendeteksi pola tertentu.
  
embedding_dim = 100
+
Jika itu hanya neural network lain, apa yang membedakannya dari apa yang telah kita pelajari sebelumnya?
  
model = Sequential()
+
CNN memiliki lapisan tersembunyi yang disebut lapisan konvolusional. Ketika kita membayangkan sebuah gambar, komputer harus berurusan dengan matrix dua dimensi angka dan oleh karena itu kita perlu beberapa cara untuk mendeteksi fitur dalam matrix ini. Lapisan konvolusional ini mampu mendeteksi tepi, sudut dan jenis tekstur lainnya yang menjadikannya tool yang istimewa. Lapisan convolutional terdiri dari beberapa filter yang digeser melintasi gambar dan dapat mendeteksi fitur-fitur tertentu.
model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))
 
model.add(layers.Conv1D(128, 5, activation='relu'))
 
model.add(layers.GlobalMaxPooling1D())
 
model.add(layers.Dense(10, activation='relu'))
 
model.add(layers.Dense(1, activation='sigmoid'))
 
model.compile(optimizer='adam',
 
              loss='binary_crossentropy',
 
              metrics=['accuracy'])
 
model.summary()
 
  
The result will be as follows:
+
Ini adalah inti dari tekniknya, proses konvolusi matematika. Dengan setiap lapisan konvolusional, network dapat mendeteksi pola yang lebih kompleks. Dalam Feature Visualization https://distill.pub/2017/feature-visualization/ oleh Chris Olah kita bisa mendapatkan intuisi yang baik seperti apa fitur-fitur ini.
  
_________________________________________________________________
+
Saat kita bekerja dengan data sekuensial, seperti teks, kita bekerja dengan konvolusi satu dimensi, tetapi gagasan dan aplikasinya tetap sama. Kita masih ingin menangkap pola dalam urutan yang menjadi lebih kompleks dengan setiap lapisan konvolusional yang ditambahkan.
Layer (type)                Output Shape              Param # 
 
=================================================================
 
embedding_13 (Embedding)    (None, 100, 100)          174700   
 
_________________________________________________________________
 
conv1d_2 (Conv1D)            (None, 96, 128)          64128   
 
_________________________________________________________________
 
global_max_pooling1d_9 (Glob (None, 128)              0       
 
_________________________________________________________________
 
dense_23 (Dense)            (None, 10)                1290     
 
_________________________________________________________________
 
dense_24 (Dense)            (None, 1)                11       
 
=================================================================
 
Total params: 240,129
 
Trainable params: 240,129
 
Non-trainable params: 0
 
_________________________________________________________________
 
  
history = model.fit(X_train, y_train,
+
Pada gambar berikut, kita dapat melihat bagaimana konvolusi bekerja. Dimulai dengan menambahkan patch fitur input dengan ukuran kernel filter. Dengan patch ini, kita mengambil produk dot dari Weight filter yang dikalikan. Convnet satu dimensi tidak sama dengan terjemahan, yang berarti bahwa urutan tertentu dapat dikenali pada posisi yang berbeda. Ini dapat membantu untuk pola-pola tertentu dalam teks:
                    epochs=10,
 
                    verbose=False,
 
                    validation_data=(X_test, y_test),
 
                    batch_size=10)
 
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 
print("Training Accuracy: {:.4f}".format(accuracy))
 
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 
print("Testing Accuracy:  {:.4f}".format(accuracy))
 
plot_history(history)
 
  
The result will be as follows:
+
[[File:1d-convolution.png|center|400px|thumb]]
  
Training Accuracy: 1.0000
+
==1D Convolution (Image source)==
Testing Accuracy:  0.7700
 
  
loss accuracy convolution model
+
Sekarang mari kita lihat bagaimana kita dapat menggunakan network ini di Keras. Keras menawarkan lagi berbagai lapisan konvolusional yang dapat kita gunakan untuk tugas ini. Lapisan yang kita butuhkan adalah lapisan Conv1D. Lapisan ini memiliki lagi berbagai parameter untuk dipilih. Yang kita minati saat ini adalah jumlah filter, ukuran kernel, dan fungsi aktivasi. Kita bisa menambahkan lapisan ini di antara lapisan Embedding dan lapisan GlobalMaxPool1D:
Accuracy and loss for convolutional neural network
 
  
You can see that 80% accuracy seems to be tough hurdle to overcome with this data set and a CNN might not be well equipped. The reason for such a plateau might be that:
+
embedding_dim = 100
 +
 +
model = Sequential()
 +
model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))
 +
model.add(layers.Conv1D(128, 5, activation='relu'))
 +
model.add(layers.GlobalMaxPooling1D())
 +
model.add(layers.Dense(10, activation='relu'))
 +
model.add(layers.Dense(1, activation='sigmoid'))
 +
model.compile(optimizer='adam',
 +
              loss='binary_crossentropy',
 +
              metrics=['accuracy'])
 +
model.summary()
  
    There are not enough training samples
+
Hasilnya:
    The data you have does not generalize well
 
    Missing focus on tweaking the hyperparameters
 
  
CNNs work best with large training sets where they are able to find generalizations where a simple model like logistic regression won’t be able.
+
_________________________________________________________________
Hyperparameters Optimization
+
Layer (type)                Output Shape              Param # 
 +
=================================================================
 +
embedding_13 (Embedding)    (None, 100, 100)          174700   
 +
_________________________________________________________________
 +
conv1d_2 (Conv1D)            (None, 96, 128)          64128   
 +
_________________________________________________________________
 +
global_max_pooling1d_9 (Glob (None, 128)              0       
 +
_________________________________________________________________
 +
dense_23 (Dense)            (None, 10)                1290     
 +
_________________________________________________________________
 +
dense_24 (Dense)            (None, 1)                11       
 +
=================================================================
 +
Total params: 240,129
 +
Trainable params: 240,129
 +
Non-trainable params: 0
 +
_________________________________________________________________
  
One crucial steps of deep learning and working with neural networks is hyperparameter optimization.
+
history = model.fit(X_train, y_train,
 +
                    epochs=10,
 +
                    verbose=False,
 +
                    validation_data=(X_test, y_test),
 +
                    batch_size=10)
 +
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
 +
print("Training Accuracy: {:.4f}".format(accuracy))
 +
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
 +
print("Testing Accuracy:  {:.4f}".format(accuracy))
 +
plot_history(history)
  
As you saw in the models that we have used so far, even with simpler ones, you had a large number of parameters to tweak and choose from. Those parameters are called hyperparameters. This is the most time consuming part of machine learning and sadly there are no one-fits-all solutions ready.
+
Hasilnya:
  
When you have a look at the competitions on Kaggle, one of the largest places to compete against other fellow data scientists, you can see that many of the winning teams and models have gone through a lot of tweaking and experimenting until they reached their prime. So don’t get discouraged when it gets tough and you reach a plateau, but rather think about the ways you could optimize the model or the data.
+
Training Accuracy: 1.0000
 +
Testing Accuracy:  0.7700
  
One popular method for hyperparameter optimization is grid search. What this method does is it takes lists of parameters and it runs the model with each parameter combination that it can find. It is the most thorough way but also the most computationally heavy way to do this. Another common way, random search, which you’ll see in action here, simply takes random combinations of parameters.
+
[[File:Loss-accuracy-convolution-model4.png|center|400px|thumb]]
  
In order to apply random search with Keras, you will need to use the KerasClassifier which serves as a wrapper for the scikit-learn API. With this wrapper you are able to use the various tools available with scikit-learn like cross-validation. The class that you need is RandomizedSearchCV which implements random search with cross-validation. Cross-validation is a way to validate the model and take the whole data set and separate it into multiple testing and training data sets.
+
Anda dapat melihat bahwa accuracy 80% tampaknya merupakan rintangan yang sulit untuk diatasi dengan kumpulan data ini dan CNN mungkin tidak dilengkapi dengan baik. Alasan untuk dataran tinggi accuracy seperti itu adalah:
  
There are various types of cross-validation. One type is the k-fold cross-validation which you’ll see in this example. In this type the data set is partitioned into k equal sized sets where one set is used for testing and the rest of the partitions are used for training. This enables you to run k different runs, where each partition is once used as a testing set. So, the higher k is the more accurate the model evaluation is, but the smaller each testing set is.
+
* Tidak cukup banyak sample training
 +
* Data yang kita miliki kurang generalize
 +
* Gagal fokus saat mengatur hyperparameters
  
First step for KerasClassifier is to have a function that creates a Keras model. We will use the previous model, but we will allow various parameters to be set for the hyperparameter optimization:
+
CNN bekerja paling baik dengan training set yang besar di mana mereka dapat menemukan generalisasi di mana model sederhana seperti regresi logistik tidak akan mampu.
  
def create_model(num_filters, kernel_size, vocab_size, embedding_dim, maxlen):
+
==Optimasi Hyperparameters==
    model = Sequential()
 
    model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))
 
    model.add(layers.Conv1D(num_filters, kernel_size, activation='relu'))
 
    model.add(layers.GlobalMaxPooling1D())
 
    model.add(layers.Dense(10, activation='relu'))
 
    model.add(layers.Dense(1, activation='sigmoid'))
 
    model.compile(optimizer='adam',
 
                  loss='binary_crossentropy',
 
                  metrics=['accuracy'])
 
    return model
 
  
Next, you want to define the parameter grid that you want to use in training. This consists of a dictionary with each parameters named as in the previous function. The number of spaces on the grid is 3 * 3 * 1 * 1 * 1, where each of those numbers is the number of different choices for a given parameter.
+
Salah satu langkah penting dalam deep learnig dan bekerja dengan neural network adalah optimasi hyperparameter.
  
You can see how this could get computationally expensive very quickly, but luckily both grid search and random search are embarrassingly parallel, and the classes come with an n_jobs parameter that lets you test grid spaces in parallel. The parameter grid is initialized with the following dictionary:
+
Seperti yang kita lihat dalam model yang telah kita gunakan sejauh ini, bahkan dengan model yang lebih sederhana, kita memiliki sejumlah besar parameter untuk di-tweak dan dipilih. Parameter tersebut disebut hyperparameters. Ini adalah bagian yang paling memakan waktu dari machine learning dan sayangnya tidak ada solusi yang cocok untuk semua.
  
param_grid = dict(num_filters=[32, 64, 128],
+
Ketika anda melihat kompetisi di Kaggle, salah satu tempat terbesar untuk bersaing dengan sesama ilmuwan data lainnya, anda dapat melihat bahwa banyak tim dan model pemenang telah melalui banyak penyesuaian dan percobaan hingga mencapai puncaknya. Jadi jangan berkecil hati ketika menjadi sulit dan anda mencapai dataran tinggi, tetapi pikirkan cara anda dapat mengoptimalkan model atau data.
                  kernel_size=[3, 5, 7],
 
                  vocab_size=[5000],
 
                  embedding_dim=[50],
 
                  maxlen=[100])
 
  
Now you are already ready to start running the random search. In this example we iterate over each data set and then you want to preprocess the data in the same way as previously. Afterwards you take the previous function and add it to the KerasClassifier wrapper class including the number of epochs.
+
Salah satu metode populer untuk optimasi hyperparameter adalah grid search. Apa yang dilakukan metode ini adalah mengambil daftar parameter dan menjalankan model dengan setiap kombinasi parameter yang dapat ditemukannya. Ini adalah cara yang paling menyeluruh tetapi juga cara yang paling berat secara komputasi untuk melakukan ini. Cara umum lain, pencarian acak, yang akan kita lihat dalam tindakan di sini, cukup mengambil kombinasi parameter secara acak.
  
The resulting instance and the parameter grid are then used as the estimator in the RandomSearchCV class. Additionally, you can choose the number of folds in the k-folds cross-validation, which is in this case 4. You have seen most of the code in this snippet before in our previous examples. Besides the RandomSearchCV and KerasClassifier, I have added a little block of code handling the evaluation:
+
Untuk menerapkan random search dengan Keras, kita harus menggunakan KerasClassifier yang berfungsi sebagai pembungkus untuk scikit-learn API. Dengan pembungkus ini kita dapat menggunakan berbagai tool yang tersedia dengan scikit-learn seperti cross-validation. Class yang kita butuhkan adalah RandomizedSearchCV yang mengimplementasikan random search dengan cross-validation. Cross-validation adalah cara untuk memvalidasi model dan mengambil seluruh rangkaian data dan memisahkannya menjadi beberapa data set testing dan training.
  
from keras.wrappers.scikit_learn import KerasClassifier
+
Ada berbagai jenis cross-validation. Salah satu jenis adalah cross-validation k-fold yang akan kita lihat dalam contoh ini. Dalam tipe ini set data dipartisi ke dalam k set ukuran yang sama di mana satu set digunakan untuk testing dan sisanya dari partisi digunakan untuk training. Ini memungkinkan kita untuk menjalankan k dalam berbagai proses yang berbeda, di mana setiap partisi pernah digunakan sebagai set testing. Jadi, semakin tinggi k adalah semakin akurat model evaluasi, tetapi semakin kecil setiap set testing-nya.
from sklearn.model_selection import RandomizedSearchCV
 
  
# Main settings
+
Langkah pertama untuk KerasClassifier adalah memiliki fungsi yang menciptakan model Keras. Kita akan menggunakan model sebelumnya, tetapi kita akan mengizinkan berbagai parameter ditetapkan untuk optimasi hyperparameter:
epochs = 20
 
embedding_dim = 50
 
maxlen = 100
 
output_file = 'data/output.txt'
 
  
# Run grid search for each source (yelp, amazon, imdb)
+
def create_model(num_filters, kernel_size, vocab_size, embedding_dim, maxlen):
for source, frame in df.groupby('source'):
+
    model = Sequential()
    print('Running grid search for data set :', source)
+
    model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))
    sentences = df['sentence'].values
+
    model.add(layers.Conv1D(num_filters, kernel_size, activation='relu'))
    y = df['label'].values
+
    model.add(layers.GlobalMaxPooling1D())
 +
    model.add(layers.Dense(10, activation='relu'))
 +
    model.add(layers.Dense(1, activation='sigmoid'))
 +
    model.compile(optimizer='adam',
 +
                  loss='binary_crossentropy',
 +
                  metrics=['accuracy'])
 +
    return model
  
    # Train-test split
+
Selanjutnya, kita ingin menentukan parameter grid yang ingin kita gunakan dalam training. Ini terdiri dari dictionary dengan masing-masing parameter dalam fungsi sebelumnya. Jumlah spasi di grid adalah 3 * 3 * 1 * 1 * 1, di mana masing-masing angka tersebut adalah jumlah pilihan yang berbeda untuk parameter yang diberikan.
    sentences_train, sentences_test, y_train, y_test = train_test_split(
 
        sentences, y, test_size=0.25, random_state=1000)
 
  
    # Tokenize words
+
Kita dapat melihat bagaimana ini bisa menjadi komputasi yang mahal dengan sangat cepat, tetapi untungnya grid search dan random search sebetulnya paralel, dan class muncul dengan parameter n_jobs yang memungkinkan kita menguji ruang grid secara paralel. Kotak parameter diinisialisasi dengan dictionary berikut:
    tokenizer = Tokenizer(num_words=5000)
 
    tokenizer.fit_on_texts(sentences_train)
 
    X_train = tokenizer.texts_to_sequences(sentences_train)
 
    X_test = tokenizer.texts_to_sequences(sentences_test)
 
  
    # Adding 1 because of reserved 0 index
+
param_grid = dict(num_filters=[32, 64, 128],
    vocab_size = len(tokenizer.word_index) + 1
+
                  kernel_size=[3, 5, 7],
 +
                  vocab_size=[5000],
 +
                  embedding_dim=[50],
 +
                  maxlen=[100])
  
    # Pad sequences with zeros
+
Sekarang kita sudah siap untuk mulai menjalankan random search. Dalam contoh ini kita mengulang setiap set data dan kemudian kita ingin memproses ulang data dengan cara yang sama seperti sebelumnya. Setelah itu kita mengambil fungsi sebelumnya dan menambahkannya ke KerasClassifier wrapper class termasuk jumlah epoch.
    X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
+
Instance yang dihasilkan dan parameter grid kemudian digunakan sebagai estimator di RandomSearchCV class.
    X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)
 
  
    # Parameter grid for grid search
+
Selain itu, kita dapat memilih jumlah fold dalam k-folds cross-validation, yang dalam kasus ini 4. Kita telah melihat sebagian besar kode dalam cuplikan ini sebelumnya dalam contoh sebelumnya. Selain RandomSearchCV dan KerasClassifier, telah menambahkan sedikit kode untuk penanganan evaluasi:
    param_grid = dict(num_filters=[32, 64, 128],
 
                      kernel_size=[3, 5, 7],
 
                      vocab_size=[vocab_size],
 
                      embedding_dim=[embedding_dim],
 
                      maxlen=[maxlen])
 
    model = KerasClassifier(build_fn=create_model,
 
                            epochs=epochs, batch_size=10,
 
                            verbose=False)
 
    grid = RandomizedSearchCV(estimator=model, param_distributions=param_grid,
 
                              cv=4, verbose=1, n_iter=5)
 
    grid_result = grid.fit(X_train, y_train)
 
  
    # Evaluate testing set
+
from keras.wrappers.scikit_learn import KerasClassifier
    test_accuracy = grid.score(X_test, y_test)
+
from sklearn.model_selection import RandomizedSearchCV
 +
 +
# Main settings
 +
epochs = 20
 +
embedding_dim = 50
 +
maxlen = 100
 +
output_file = 'data/output.txt'
 +
 +
# Run grid search for each source (yelp, amazon, imdb)
 +
for source, frame in df.groupby('source'):
 +
    print('Running grid search for data set :', source)
 +
    sentences = df['sentence'].values
 +
    y = df['label'].values
 +
 +
    # Train-test split
 +
    sentences_train, sentences_test, y_train, y_test = train_test_split(
 +
        sentences, y, test_size=0.25, random_state=1000)
 +
 +
    # Tokenize words
 +
    tokenizer = Tokenizer(num_words=5000)
 +
    tokenizer.fit_on_texts(sentences_train)
 +
    X_train = tokenizer.texts_to_sequences(sentences_train)
 +
    X_test = tokenizer.texts_to_sequences(sentences_test)
 +
 +
    # Adding 1 because of reserved 0 index
 +
    vocab_size = len(tokenizer.word_index) + 1
 +
 +
    # Pad sequences with zeros
 +
    X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
 +
    X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)
 +
 +
    # Parameter grid for grid search
 +
    param_grid = dict(num_filters=[32, 64, 128],
 +
                      kernel_size=[3, 5, 7],
 +
                      vocab_size=[vocab_size],
 +
                      embedding_dim=[embedding_dim],
 +
                      maxlen=[maxlen])
 +
    model = KerasClassifier(build_fn=create_model,
 +
                            epochs=epochs, batch_size=10,
 +
                            verbose=False)
 +
    grid = RandomizedSearchCV(estimator=model, param_distributions=param_grid,
 +
                              cv=4, verbose=1, n_iter=5)
 +
    grid_result = grid.fit(X_train, y_train)
 +
 +
    # Evaluate testing set
 +
    test_accuracy = grid.score(X_test, y_test)
 +
 +
    # Save and evaluate results
 +
    prompt = input(f'finished {source}; write to file and proceed? [y/n]')
 +
    if prompt.lower() not in {'y', 'true', 'yes'}:
 +
        break
 +
    with open(output_file, 'a') as f:
 +
        s = ('Running {} data set\nBest Accuracy : '
 +
              '{:.4f}\n{}\nTest Accuracy : {:.4f}\n\n')
 +
        output_string = s.format(
 +
            source,
 +
            grid_result.best_score_,
 +
            grid_result.best_params_,
 +
            test_accuracy)
 +
        print(output_string)
 +
        f.write(output_string)
  
    # Save and evaluate results
+
Ini membutuhkan waktu yang merupakan kesempatan sempurna untuk pergi keluar untuk mendapatkan udara segar atau bahkan mendaki gunung, tergantung pada berapa banyak model yang ingin kita jalankan. Mari kita lihat apa yang kita punya:
    prompt = input(f'finished {source}; write to file and proceed? [y/n]')
 
    if prompt.lower() not in {'y', 'true', 'yes'}:
 
        break
 
    with open(output_file, 'a') as f:
 
        s = ('Running {} data set\nBest Accuracy : '
 
            '{:.4f}\n{}\nTest Accuracy : {:.4f}\n\n')
 
        output_string = s.format(
 
            source,
 
            grid_result.best_score_,
 
            grid_result.best_params_,
 
            test_accuracy)
 
        print(output_string)
 
        f.write(output_string)
 
  
This takes a while which is a perfect chance to go outside to get some fresh air or even go on a hike, depending on how many models you want to run. Let’s take a look what we have got:
+
Running amazon data set
 +
Best Accuracy : 0.8122
 +
{'vocab_size': 4603, 'num_filters': 64, 'maxlen': 100, 'kernel_size': 5, 'embedding_dim': 50}
 +
Test Accuracy : 0.8457
  
Running amazon data set
+
Running imdb data set
Best Accuracy : 0.8122
+
Best Accuracy : 0.8161
{'vocab_size': 4603, 'num_filters': 64, 'maxlen': 100, 'kernel_size': 5, 'embedding_dim': 50}
+
{'vocab_size': 4603, 'num_filters': 128, 'maxlen': 100, 'kernel_size': 5, 'embedding_dim': 50}
Test Accuracy : 0.8457
+
Test Accuracy : 0.8210
  
Running imdb data set
+
Running yelp data set
Best Accuracy : 0.8161
+
Best Accuracy : 0.8127
{'vocab_size': 4603, 'num_filters': 128, 'maxlen': 100, 'kernel_size': 5, 'embedding_dim': 50}
+
{'vocab_size': 4603, 'num_filters': 64, 'maxlen': 100, 'kernel_size': 7, 'embedding_dim': 50}
Test Accuracy : 0.8210
+
Test Accuracy : 0.8384
  
Running yelp data set
+
Menarik! Untuk beberapa hal maka akurasi testing lebih tinggi daripada akurasi training yang mungkin karena ada perbedaan besar dalam skor selama cross-validation. Kita dapat melihat bahwa kita masih tidak dapat menembus banyak melalui 80% yang ditakuti, yang tampaknya menjadi batas alami untuk data ini dengan ukuran yang diberikan. Ingat bahwa kita memiliki satu set data kecil dan convolutional neural networks cenderung melakukan yang terbaik dengan set data besar.
Best Accuracy : 0.8127
 
{'vocab_size': 4603, 'num_filters': 64, 'maxlen': 100, 'kernel_size': 7, 'embedding_dim': 50}
 
Test Accuracy : 0.8384
 
  
Interesting! For some reason the testing accuracy is higher than the training accuracy which might be because there is a large variance in the scores during cross-validation. We can see that we were still not able to break much through the dreaded 80%, which seems to be a natural limit for this data with its given size. Remember that we have a small data set and convolutional neural networks tend to perform the best with large data sets.
+
Metode lain untuk CV adalah nested cross-validation (ditampilkan di sini) yang digunakan ketika hyperparameters juga perlu dioptimalkan. Ini digunakan karena model non-nested CV yang dihasilkan memiliki bias terhadap kumpulan data yang dapat menyebabkan skor terlalu optimis. Kita tahu, ketika melakukan optimasi hiperparameter seperti yang kita lakukan dalam contoh sebelumnya, kita memilih hyperparameter terbaik untuk set training tertentu tetapi ini tidak berarti bahwa hyperparameter ini menggeneralisasi yang terbaik.
  
Another method for CV is the nested cross-validation (shown here) which is used when the hyperparameters also need to be optimized. This is used because the resulting non-nested CV model has a bias toward the data set which can lead to an overly optimistic score. You see, when doing hyperparameter optimization as we did in the previous example, we are picking the best hyperparameters for that specific training set but this does not mean that these hyperparameters generalize the best.
+
==Conclusion==
Conclusion
 
  
There you have it: you have learned how to work with text classification with Keras, and we have gone from a bag-of-words model with logistic regression to increasingly more advanced methods leading to convolutional neural networks.
+
Kita telah belajar cara bekerja dengan klasifikasi teks dengan Keras, dan kita telah beralih dari model bag-of-words dengan regresi logistik menjadi metode yang semakin maju yang mengarah ke convolutional neural networks.
  
You should be now familiar with word embeddings, why they are useful, and also how to use pretrained word embeddings for your training. You have also learned how to work with neural networks and how to use hyperparameter optimization to squeeze more performance out of your model.
+
Kita sekarang harus terbiasa dengan word embeddings, mengapa mereka berguna, dan juga bagaimana menggunakan pretrained word embeddings untuk training kita. Kita juga telah belajar cara bekerja dengan neural network dan cara menggunakan optimasi hyperparameter untuk memeras lebih banyak kinerja dari model kita.
  
One big topic which we have not covered here left for another time was recurrent neural networks, more specifically LSTM and GRU. Those are other powerful and popular tools to work with sequential data like text or time series. Other interesting developments are currently in neural networks that employ attention which are under active research and seem to be a promising next step since LSTM tend to be heavy on the computation.
+
Satu topik besar yang belum kita bahas di sini dibiarkan lain waktu adalah recurrent neural networks, lebih khusus LSTM dan GRU. Itu adalah tool powerfull dan populer lainnya untuk bekerja dengan data sequential seperti teks atau time series. Perkembangan menarik lainnya saat ini dalam neural network yang menggunakan perhatian yang sedang dalam penelitian aktif dan tampaknya menjadi langkah berikutnya yang menjanjikan karena LSTM cenderung berat pada perhitungan.
  
You have now an understanding of a crucial cornerstone in natural language processing which you can use for text classification of all sorts. Sentiment analysis is the most prominent example for this, but this includes many other applications such as:
+
Kita sekarang memiliki pemahaman tentang landasan penting dalam natural language processing yang dapat kita gunakan untuk semua jenis text classification. Analisis sentimen adalah contoh yang paling menonjol untuk ini, tetapi ini mencakup banyak aplikasi lain seperti:
  
    Spam detection in emails
+
* Deteksi Spam di email
    Automatic tagging of texts
+
* Automatic tagging pada text
    Categorization of news articles with predefined topics
+
* Kategorisasi artikel berita untuk topik yang sudah di definisikan.
  
You can use this knowledge and the models that you have trained on an advanced project as in this tutorial to employ sentiment analysis on a continuous stream of twitter data with Kibana and Elasticsearch. You could also combine sentiment analysis or text classification with speech recognition like in this handy tutorial using the SpeechRecognition library in Python.
+
Kita dapat menggunakan pengetahuan ini dan model-model yang telah kita latih pada proyek lanjutan seperti dalam tutorial ini untuk menggunakan analisis sentimen pada  continuous stream data twitter dengan Kibana dan Elasticsearch. Kita juga bisa menggabungkan analisis sentimen atau  text classification dengan speech recognition seperti dalam tutorial praktis ini menggunakan library SpeechRecognition di Python.
  
 
==Referensi==
 
==Referensi==
Line 959: Line 993:
  
 
==Pranala Menarik==
 
==Pranala Menarik==
 +
 +
* [[Keras]]

Latest revision as of 08:30, 14 August 2019

Sumber: https://realpython.com/python-keras-text-classification/

Bayangkan kita bisa mengetahui mood orang-orang di Internet. Mungkin kita tidak tertarik secara keseluruhan, tetapi cukup happy melihat orang bahagia di platform media sosial favorit kita. Setelah tutorial ini, kita akan diperlengkapi untuk melakukan ini. Saat melakukan ini, kita akan memahami kemajuan di (deep) neural network saat ini dan bagaimana penerapannya pada teks.

Membaca mood dari teks dengan machine learning dikenal dengan analisis sentimen, dan itu adalah salah satu kasus penggunaan yang menonjol dalam klasifikasi teks. Ini masuk ke bidang penelitian yang sangat aktif dari natural language processing (NLP). Kasus penggunaan umum lainnya dari klasifikasi teks termasuk deteksi spam, penandaan otomatis atas permintaan pelanggan, dan kategorisasi teks ke dalam topik yang ditentukan. Jadi, bagaimana kita bisa melakukan ini?

Memilih Dataset

Sebelum kita mulai, mari kita lihat data apa yang kita miliki. Pergi dan unduh kumpulan data dari Sentiment Labelled Sentences Data Set dari UCI Machine Learning Repository https://archive.ics.uci.edu/ml/datasets/Sentiment+Labelled+Sentences

Repositori ini adalah sumber yang bagus untuk data set machine learning jika kita ingin mencoba beberapa algoritma. Kumpulan data ini mencakup review berlabel dari IMDb, Amazon, dan Yelp. Setiap ulasan ditandai dengan skor 0 untuk sentimen negatif atau 1 untuk sentimen positif.

Ekstrak folder ke folder data, lanjut dengan load data dengan Pandas:

import pandas as pd

filepath_dict = {'yelp':   '/home/onno/TensorFlow/data/sentiment_analysis/yelp_labelled.txt',
                 'amazon': '/home/onno/TensorFlow/data/sentiment_analysis/amazon_cells_labelled.txt',
                 'imdb':   '/home/onno/TensorFlow/data/sentiment_analysis/imdb_labelled.txt'}

df_list = []
for source, filepath in filepath_dict.items():
    df = pd.read_csv(filepath, names=['sentence', 'label'], sep='\t')
    df['source'] = source  # Add another column filled with the source name
    df_list.append(df)

df = pd.concat(df_list)
print(df.iloc[0])

Hasilnya kira-kira sebagai berikut,

sentence    Wow... Loved this place.
label                              1
source                          yelp
Name: 0, dtype: object

Ini terlihat benar. Dengan kumpulan data ini, kita dapat melatih model untuk memprediksi sentimen dari sebuah kalimat. Luangkan waktu sejenak untuk memikirkan bagaimana kita akan memprediksi data.

Salah satu cara kita dapat melakukan ini adalah dengan menghitung frekuensi setiap kata dalam setiap kalimat dan menghubungkan penghitungan ini kembali ke seluruh rangkaian kata dalam dataset. Kita akan mulai dengan mengambil data dan membuat kosa kata dari semua kata dalam semua kalimat. Kumpulan teks juga disebut corpus di NLP.

Vocabulary dalam hal ini adalah daftar kata-kata yang ada dalam teks di mana setiap kata memiliki indeks sendiri. Ini memungkinkan kita membuat vektor untuk sebuah kalimat. Kita kemudian akan mengambil kalimat yang ingin kita vektorisasi, dan kita menghitung setiap kemunculannya dalam kosa kata. Vektor yang dihasilkan akan dengan panjang kosakata dan jumlah untuk setiap kata dalam vocabulary.

Vektor yang dihasilkan biasa disebut feature vector. Dalam feature vector, setiap dimensi dapat berupa fitur numerik atau kategorikal, seperti misalnya tinggi bangunan, harga saham, atau, dalam kasus ini, hitungan kata dalam vocabulary. Feature Vector ini adalah bagian penting dalam data science dan machine learning, karena model yang ingin kita latih tergantung pada mereka.

Mari kita ilustrasikan ini dengan cepat. Bayangkan kita memiliki dua kalimat berikut:

sentences = ['John likes ice cream', 'John hates chocolate.']

Selanjutnya, kita dapat menggunakan CountVectorizer yang disediakan oleh scikit-learn library untuk membuat vektor kalimat. Library ini akan mengambil kata-kata dari setiap kalimat dan menciptakan vocabulary dari semua kata unik dalam kalimat. Vocabulary ini kemudian dapat digunakan untuk membuat feature vector dari jumlah kata:

from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(min_df=0, lowercase=False)
vectorizer.fit(sentences)
vectorizer.vocabulary_

Hasilnya:

{'John': 0, 'chocolate': 1, 'cream': 2, 'hates': 3, 'ice': 4, 'likes': 5}

Vocabulary ini juga berfungsi sebagai indeks setiap kata. Sekarang, kita dapat mengambil setiap kalimat dan mendapatkan kemunculan kata berdasarkan vocabulary sebelumnya. Vocabulary terdiri dari semua lima kata dalam kalimat ini, masing-masing mewakili satu kata dalam Vocabulary. Ketika kita mengambil dua kalimat sebelumnya dan mengubahnya dengan CountVectorizer maka kita akan mendapatkan vektor yang mewakili jumlah setiap kata dari kalimat:

vectorizer.transform(sentences).toarray()

Hasilnya:

array([[1, 0, 1, 0, 1, 1],
    [1, 1, 0, 1, 0, 0]])

Sekarang, kita dapat melihat vektor fitur yang dihasilkan untuk setiap kalimat berdasarkan vocabulary sebelumnya. Misalnya, jika kita melihat item pertama, kita dapat melihat bahwa kedua vektor memiliki 1 di sana. Ini berarti bahwa kedua kalimat memiliki satu kemunculan John, yang berada pada tempat pertama dalam Vocabulary.

Ini dianggap model Bag-of-words (BOW), yang merupakan cara umum dalam NLP untuk membuat vektor dari teks. Setiap dokumen direpresentasikan sebagai vektor. Kita dapat menggunakan vektor ini sekarang sebagai feature vector untuk model machine learning. Ini membawa kita ke bagian selanjutnya, mendefinisikan model dasar.

Mendefinisikan Model Baseline

Saat kita bekerja dengan machine learning, satu langkah penting adalah menentukan model dasar. Ini biasanya melibatkan model sederhana, yang kemudian digunakan sebagai perbandingan dengan model yang lebih maju yang ingin kita uji. Dalam hal ini, kita akan menggunakan model dasar untuk membandingkannya dengan metode yang lebih maju yang melibatkan (deep) neural network.

Pertama, kita akan membagi data menjadi set training dan testing yang akan memungkinkan kita untuk mengevaluasi akurasi dan melihat apakah model kita dapat digeneralisasikan dengan baik. Ini berarti apakah model tersebut mampu berkinerja baik pada data yang belum pernah dilihat sebelumnya. Ini adalah cara untuk melihat apakah modelnya overfitting (cocok).

Overfitting adalah ketika model dilatih terlalu baik pada data training. Kita ingin menghindari overfitting, karena ini berarti model sebagian besar hanya menghafal data pelatihan. Ini akan menjelaskan akurasi yang besar dengan data training tetapi akurasi yang rendah dalam data testing.

Kita mulai dengan mengambil data set Yelp yang kita ekstrak dari kumpulan data gabungan. Dari sana, kita mengambil kalimat dan label. Nilai .values mengembalikan array NumPy daripada objek series Pandas yang dalam konteks ini akan lebih mudah digunakan:

from sklearn.model_selection import train_test_split

df_yelp = df[df['source'] == 'yelp']

sentences = df_yelp['sentence'].values
y = df_yelp['label'].values

sentences_train, sentences_test, y_train, y_test = train_test_split(
    sentences, y, test_size=0.25, random_state=1000)

Di sini kita akan menggunakan lagi model BOW sebelumnya untuk membuat vektor kalimat. Kita dapat menggunakan lagi CountVectorizer untuk tugas ini. Karena kita mungkin tidak memiliki data pengujian yang tersedia selama testing, kikta dapat membuat Vocabulary hanya menggunakan data training. Dengan menggunakan Vocabulary ini, kita dapat membuat feature vector untuk setiap kalimat dari rangkaian training dan testing:

from sklearn.feature_extraction.text import CountVectorizer

vectorizer = CountVectorizer()
vectorizer.fit(sentences_train)

X_train = vectorizer.transform(sentences_train)
X_test  = vectorizer.transform(sentences_test)
X_train

Hasilnya:

<750x1714 sparse matrix of type '<class 'numpy.int64'>'
    with 7368 stored elements in Compressed Sparse Row format>

Kita dapat melihat bahwa feature vector yang dihasilkan memiliki 750 sampel yang merupakan jumlah sampel training yang kita miliki setelah split train-test. Setiap sampel memiliki 1714 dimensi yang merupakan ukuran Vocabulary. Kita juga dapat melihat bahwa kita mendapatkan matriks sparce (yang banyak nol-nya). Ini adalah tipe data yang dioptimalkan untuk matriks dengan hanya beberapa elemen non-zero (tidak nol). Untuk menghemat memory, kita hanya akan memperhatikan elemen yang non-zero saja.

CountVectorizer melakukan tokenization yang memisahkan kalimat menjadi satu set token seperti yang kita lihat sebelumnya dalam Vocabulary. Ini juga menghilangkan tanda baca dan karakter khusus dan dapat menerapkan preprocessing lainnya untuk setiap kata. Jika mau, kita dapat menggunakan tokenizer khusus dari perpustakaan NLTK dengan CountVectorizer atau menggunakan sejumlah penyesuaian yang dapat kita eksplorasi untuk meningkatkan kinerja model kita.

Catatan: Ada banyak parameter tambahan untuk CountVectorizer() yang kita lupakan untuk digunakan di sini, seperti menambahkan ngram, karena tujuan awalnya adalah untuk membangun model baseline sederhana. Tokeb pattern itu sendiri default ke token_pattern = ’(?U)\b \w\w+\b’, yang merupakan pola regex yang mengatakan, "sebuah kata adalah 2 atau lebih karakter kata Unicode yang dikelilingi oleh batas kata.".

Model klasifikasi yang akan kita gunakan adalah regresi logistik yang merupakan model linier sederhana namun kuat yang secara matematis merupakan bentuk regresi antara 0 dan 1 berdasarkan feature vector input. Dengan menentukan nilai cutoff (secara default 0,5), model regresi digunakan untuk klasifikasi. Anda dapat menggunakan library scikit-learn yang menyediakan classifier LogisticRegression:

Model klasifikasi yang akan kita gunakan adalah regresi logistik yang merupakan model linier sederhana namun kuat yang secara matematis merupakan bentuk regresi antara 0 dan 1 berdasarkan feature vector input. Dengan menentukan nilai cutoff (secara default 0,5), model regresi digunakan untuk klasifikasi. Anda dapat menggunakan library scikit-learn yang menyediakan classifier LogisticRegression:

from sklearn.linear_model import LogisticRegression

classifier = LogisticRegression()
classifier.fit(X_train, y_train)
score = classifier.score(X_test, y_test)

print("Accuracy:", score)

Hasilnya:

Accuracy: 0.796

Kita dapat melihat bahwa logistic regression mencapai 79,6% yang mengesankan, tetapi mari kita lihat bagaimana kinerja model ini pada set data lain yang kita miliki. Dalam skrip ini, kita melakukan dan mengevaluasi seluruh proses untuk setiap set data yang kita miliki:

for source in df['source'].unique():
    df_source = df[df['source'] == source]
    sentences = df_source['sentence'].values
    y = df_source['label'].values

    sentences_train, sentences_test, y_train, y_test = train_test_split(
        sentences, y, test_size=0.25, random_state=1000)

    vectorizer = CountVectorizer()
    vectorizer.fit(sentences_train)
    X_train = vectorizer.transform(sentences_train)
    X_test  = vectorizer.transform(sentences_test)

    classifier = LogisticRegression()
    classifier.fit(X_train, y_train)
    score = classifier.score(X_test, y_test)
    print('Accuracy for {} data: {:.4f}'.format(source, score))

Here’s the result:

Accuracy for yelp data: 0.7960
Accuracy for amazon data: 0.7960
Accuracy for imdb data: 0.7487

Bagus! Kita dapat melihat bahwa model yang cukup sederhana ini menghasilkan akurasi yang cukup baik. Akan menarik untuk melihat apakah kita dapat memperbaiki model ini. Pada bagian selanjutnya, kita akan mengenal (Deep) Neural Network dan bagaimana menerapkannya pada klasifikasi teks.

(Deep) Neural Networks

Kita mungkin telah mengalami beberapa kekaguman dan ketakutan terkait dengan kecerdasan buatan dan deep learning. Kita mungkin telah menemukan beberapa artikel yang membingungkan atau TED talk yang khawatir membicarakan pendekatan singularitas atau mungkin kita melihat robot backflipping dan kita bertanya-tanya apakah kehidupan di belantara sebetulnya demikian menarik.

Pada catatan yang lebih ringan, semua peneliti AI sepakat bahwa mereka tidak setuju satu sama lain ketika AI akan melebihi kinerja tingkat Manusia. Dalam tulisan ini kita masih punya waktu.

Jadi kita mungkin penasaran bagaimana neural network bekerja. Jika kita sudah terbiasa dengan neural network, jangan ragu untuk beralih ke bagian yang melibatkan Keras. Juga, ada buku Deep Learning yang bagus dari Ian Goodfellow jika kita ingin menggali lebih dalam tentang matematika. Kita dapat membaca seluruh buku online secara gratis. Pada bagian ini kita akan mendapatkan gambaran tentang neural network dan cara kerja dalamnya, dan nanti kita akan melihat cara menggunakan neural network dengan library Keras yang luar biasa.

Dalam artikel ini, kita tidak perlu khawatir tentang singularitas, tetapi (deep) neural networks memainkan peran penting dalam perkembangan terbaru dalam AI. Semuanya dimulai dengan makalah terkenal pada 2012 oleh Geoffrey Hinton dan timnya, yang mengungguli semua model sebelumnya dalam Tantangan ImageNet yang terkenal.

Tantangannya bisa dianggap sebagai Piala Dunia dalam computer vision yang melibatkan pengklasifikasian satu set besar gambar berdasarkan label yang diberikan. Geoffrey Hinton dan timnya berhasil mengalahkan model-model sebelumnya dengan menggunakan convolution neural network (CNN), yang akan kita bahas dalam tutorial ini juga.

Sejak itu, neural network telah bergerak ke beberapa bidang yang melibatkan klasifikasi, regresi dan bahkan model generatif. Bidang yang paling umum termasuk penglihatan komputer, pengenalan suara dan natural language processing (NLP).

Neural Networks, atau kadang-kadang disebut Artificial Neural Network (ANN) / Jaringan Saraf Tiruan (JST) atau feedforward neural network, adalah jaringan komputasi yang secara samar-samar terinspirasi oleh jaringan saraf di otak manusia. Mereka terdiri dari neuron (juga disebut node) yang terhubung seperti pada grafik di bawah ini.

Ann.png

Kita mulai dengan memiliki lapisan neuron input tempat kita memberi masukan di feature vector kita dan nilai tersebut kemudian diumpankan (feed forward) ke lapisan tersembunyi. Pada setiap koneksi, kita memasukan nilai untuk dimajukan, kemudian nilai dikalikan dengan bobot dan ditambahkan bias. Ini terjadi pada setiap koneksi dan pada akhirnya kita mencapai lapisan output dengan satu atau lebih node output.

Jika kita ingin memiliki klasifikasi biner, kita dapat menggunakan satu simpul, tetapi jika kita memiliki beberapa kategori, kita harus menggunakan banyak simpul untuk setiap kategori.

Kita dapat memiliki lapisan tersembunyi sebanyak yang kita inginkan. Sebetulnya, neural networks dengan lebih dari satu lapisan tersembunyi dianggap sebagai deep neural networks. Jangan khawatir: kita tidak akan sampai di sini ke kedalaman matematika tentang neural network. Tetapi jika kita ingin mendapatkan pemahaman visual intuitif tentang matematika yang terlibat, anda dapat melihat Playlist YouTube https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi oleh Grant Sanderson. Rumus dari satu layer ke yang berikutnya adalah persamaan pendek ini:

Rumus-neural-network.png

Mari kita perlahan membongkar apa yang terjadi di sini. Kita lihat, kita berurusan di sini hanya dengan dua lapisan. Layer dengan node a berfungsi sebagai input untuk layer dengan node o. Untuk menghitung nilai untuk setiap simpul keluaran, kita harus mengalikan setiap simpul masukan dengan bobot w dan menambahkan bias b.

Semua itu harus dijumlahkan dan diteruskan ke fungsi f. Fungsi ini dianggap sebagai fungsi aktivasi dan ada berbagai fungsi berbeda yang dapat digunakan tergantung pada lapisan atau masalahnya. Umumnya umum untuk menggunakan rectified linear unit (ReLU) untuk lapisan hidden, fungsi sigmoid untuk lapisan output dalam masalah klasifikasi biner, atau fungsi softmax untuk lapisan output dari masalah klasifikasi multi-kelas.

Kita mungkin sudah bertanya-tanya bagaimana bobot dihitung, dan ini jelas merupakan bagian terpenting dari neural networks, tetapi juga bagian yang paling sulit. Algoritma dimulai dengan menginisialisasi bobot dengan nilai acak dan mereka kemudian dilatih dengan metode yang disebut backpropagation.

Ini dilakukan dengan menggunakan metode optimisasi (juga disebut optimizer) seperti gradient descent untuk mengurangi kesalahan antara output yang dihitung dan yang diinginkan (juga disebut output target). Kesalahan ditentukan oleh fungsi kerugian (loss function) yang kerugiannya (loss-nya) ingin kami perkecil dengan optimizer. Seluruh proses terlalu luas untuk dibahas di sini, tetapi saya akan merujuk lagi ke playlist Grant Sanderson dan buku Deep Learning oleh Ian Goodfellow.

Yang harus kita ketahui adalah bahwa ada berbagai metode pengoptimalan yang dapat kita gunakan, tetapi pengoptimal yang paling umum saat ini digunakan adalah Adam yang memiliki kinerja yang baik dalam berbagai masalah.

Kita juga dapat menggunakan fungsi loss yang berbeda, tetapi dalam tutorial ini kita hanya akan memerlukan cross entropy loss function atau lebih khusus, binary cross entropy yang digunakan untuk masalah klasifikasi biner. Pastikan untuk bereksperimen dengan berbagai metode dan tool yang tersedia. Beberapa peneliti bahkan mengklaim dalam sebuah artikel baru-baru ini bahwa pilihan untuk metode berkinerja terbaik berbatasan dengan alchemy. Alasannya adalah bahwa banyak metode tidak dijelaskan dengan baik dan terdiri dari banyak penyesuaian dan testing.

Pengenalan Keras

Keras adalah pembelajaran mendalam dan API neural networks oleh François Chollet yang mampu berjalan di atas Tensorflow (Google), Theano atau CNTK (Microsoft). Mengutip buku bagus dari François Chollet, Deep Learning with Python:

"Keras is a model-level library, providing high-level building blocks for developing deep-learning models. It doesn’t handle low-level operations such as tensor manipulation and differentiation. Instead, it relies on a specialized, well-optimized tensor library to do so, serving as the backend engine of Keras (Source)"

Ini adalah cara yang bagus untuk mulai bereksperimen dengan neural network tanpa harus menerapkan setiap lapisan oleh kita sendiri. Misalnya Tensorflow adalah library machine learning yang hebat, tetapi kita harus menerapkan banyak kode boilerplate agar model bisa jalan.

Install Keras

Sebelum menginstall Keras, kita perlu Tensorflow, Theano, atau CNTK. Dalam tutorial ini kita akan menggunakan Tensorflow jadi lihat panduan instalasi mereka, tetapi jangan ragu untuk menggunakan salah satu framework yang paling cocok untuk anda. Keras dapat diinstal menggunakan PyPI dengan perintah berikut:

$ pip install keras

Kita dapat memilih backend yang ingin kita miliki dengan membuka file konfigurasi Keras yang dapat kita temukan di sini:

$HOME/.keras/keras.json

Jika anda adalah pengguna Windows, anda harus mengganti $HOME dengan %USERPROFILE%. File konfigurasi akan terlihat sebagai berikut:

{
    "image_data_format": "channels_last",
    "epsilon": 1e-07,
    "floatx": "float32",
    "backend": "tensorflow"
}

Kita dapat mengubah backend field menjadi "theano", "tensorflow" atau "cntk", mengingat kita telah menginstal backend pada mesin yang kita gunakan. Untuk lebih jelasnya lihat dokumentasi Keras backends.

Anda mungkin memperhatikan bahwa kita menggunakan data float32 dalam file konfigurasi. Alasan untuk ini adalah bahwa neural network sering digunakan dalam GPU, dan hambatan komputasi adalah memori. Dengan menggunakan 32 bit, kita dapat mengurangi beban memori dan kami tidak kehilangan terlalu banyak informasi dalam proses.

Model Keras anda yang pertama

Sekarang kita akhirnya siap untuk bereksperimen dengan Keras. Keras mendukung dua (2) jenis utama model. Kita memiliki API model Sequential yang akan kita lihat digunakan dalam tutorial ini dan API fungsional yang dapat melakukan semua hal dari model Sequential tetapi dapat juga digunakan untuk model lanjutan dengan arsitektur jaringan yang kompleks.

Model Sequential adalah tumpukan linear lapisan, di mana kita dapat menggunakan berbagai macam lapisan yang tersedia di Keras. Lapisan yang paling umum adalah lapisan Dense yang merupakan lapisan neural network biasa yang terhubung dengan semua Weight dan bias yang sudah kita kenal.

Mari kita lihat apakah kita dapat mencapai beberapa peningkatan pada model regresi logistik kita sebelumnya. Anda dapat menggunakan array X_train dan X_test yang Anda buat dalam contoh kami sebelumnya.

Sebelum kita membangun model kita, kita perlu mengetahui dimensi input vektor fitur kita. Ini hanya terjadi di lapisan pertama karena lapisan berikut dapat melakukan inferensi shape secara otomatis. Untuk membangun model Sequential, kita dapat menambahkan layer satu per satu dengan urutan sebagai berikut:

from keras.models import Sequential
from keras import layers

input_dim = X_train.shape[1]  # Number of features

model = Sequential()
model.add(layers.Dense(10, input_dim=input_dim, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

Penggunaan backend TensorFlow

Sebelum kita dapat mulai dengan training model, kita harus mengonfigurasi proses training. Ini dilakukan dengan metode .compile(). Metode ini menentukan fungsi optimizer dan loss.

Selain itu, kita dapat menambahkan daftar metrik yang nantinya dapat digunakan untuk evaluasi, tetapi mereka tidak memengaruhi training. Dalam hal ini, kita ingin menggunakan binary cross entropy dan Adam optimizer yang kita lihat dalam bagian sebelumnya. Keras juga mencakup fungsi .summary() yang berguna untuk memberikan gambaran umum tentang model dan jumlah parameter yang tersedia untuk training:

model.compile(loss='binary_crossentropy', 
             optimizer='adam', 
             metrics=['accuracy'])
model.summary()

Hasilnya

_________________________________________________________________
Layer (type)                 Output Shape          Param #   
=================================================================
dense_1 (Dense)              (None, 10)            17150     
_________________________________________________________________
dense_2 (Dense)              (None, 1)             11        
=================================================================
Total params: 17,161
Trainable params: 17,161
Non-trainable params: 0
_________________________________________________________________

Anda mungkin memperhatikan bahwa kita memiliki 8575 parameter untuk lapisan pertama dan 6 lainnya di lapisan berikutnya. Dari mana datangnya?

Lihat, kita memiliki 1714 dimensi untuk setiap feature vector, dan kemudian kita memiliki 5 node. Kita perlu bobot untuk setiap dimensi feature dan setiap node yang menyumbang 1714 * 5 = 8570 parameter, dan kemudian kita memiliki 5 kali bias tambahan untuk setiap node, yang memberi kita 8575 parameter. Pada node terakhir, kita memiliki 5 bobot dan satu bias, yang membawa kita ke 6 parameter.

Kita hampir sampai. Sekarang saatnya untuk memulai training dengan fungsi .fit().

Karena training dalam neural network adalah proses berulang, training tidak akan berhenti setelah selesai. Kita harus menentukan jumlah iterasi yang kita inginkan agar model di training. Iterasi yang selesai itu biasa disebut epochs. Kita ingin menjalankannya selama 100 epochs untuk dapat melihat bagaimana training loss dan accuracy berubah setelah setiap epoch.

Parameter lain yang kita miliki untuk pilihan adalah ukuran batch (batch size). Ukuran batch bertanggung jawab untuk berapa banyak sampel yang ingin kita gunakan dalam satu epoch, yang berarti berapa banyak sampel yang digunakan dalam satu lintasan maju (forward) / mundur (backward). Ini meningkatkan kecepatan perhitungan karena perlu lebih sedikit epoch untuk run, tetapi juga membutuhkan lebih banyak memori, dan model dapat menurun dengan ukuran batch yang lebih besar. Karena kita memiliki satu set training yang kecil, kita dapat membiarkannya dalam ukuran batch yang rendah:

history = model.fit(X_train, y_train,
                    epochs=100,
                    verbose=False,
                    validation_data=(X_test, y_test),
                    batch_size=10)

Sekarang kita dapat menggunakan metode .evaluate() untuk mengukur akurasi model. Kita dapat melakukan ini baik untuk data training dan data testing. Kami berharap bahwa data training memiliki akurasi yang lebih tinggi daripada data testing. Semakin lama kita melatih neural network, semakin besar kemungkinan overfitting.

Perhatikan bahwa jika kita menjalankan kembali metode .fit(), kita akan mulai dengan bobot yang dihitung dari training sebelumnya. Pastikan untuk mengkompilasi model lagi sebelum kita mulai training model itu lagi. Sekarang mari kita evaluasi akurasi model:

loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))

Hasilnya

Training Accuracy: 1.0000
Testing Accuracy:  0.7960

Kita sudah dapat melihat bahwa model akan overfitting karena mencapai akurasi 100% untuk set pelatihan. Tapi ini diharapkan karena jumlah epochs yang cukup besar untuk model ini. Namun, keakuratan set testing telah melampaui logistic Regression dengan BOW model, yang merupakan langkah maju yang baik.

Untuk membuat hidup kita lebih mudah, kita dapat menggunakan fungsi helper untuk memvisualisasikan loss dan accuracy untuk training dan testing data berdasarkan history callback. Callback, yang secara otomatis diterapkan pada setiap model Keras, mencatat loss dan metrik tambahan yang dapat ditambahkan dalam metode .fit(). Dalam hal ini, kami hanya tertarik pada accuracy. Fungsi helper ini menggunakan library matplotlib plotting:

import matplotlib.pyplot as plt
plt.style.use('ggplot')

def plot_history(history):
    acc = history.history['acc']
    val_acc = history.history['val_acc']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    x = range(1, len(acc) + 1) 

    plt.figure(figsize=(12, 5))
    plt.subplot(1, 2, 1)
    plt.plot(x, acc, 'b', label='Training acc')
    plt.plot(x, val_acc, 'r', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend()
    plt.subplot(1, 2, 2)
    plt.plot(x, loss, 'b', label='Training loss')
    plt.plot(x, val_loss, 'r', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend()

Untuk menggunakan fungsi ini, cukup call plot_history() dengan accuracy dan loss yang terkumpul di dalam history dictionary:

plot_history(history)


tumb

Kita dapat melihat bahwa kita telah melatih model terlalu lama sehingga set training mencapai akurasi 100%. Cara yang baik untuk melihat kapan model mulai overfitting adalah ketika loss dari validasi data mulai naik lagi. Ini cenderung menjadi titik yang baik untuk menghentikan model. Anda dapat melihat ini sekitar 20-40 epochs dalam training ini.

Catatan: Saat melatih neural network, kita harus menggunakan set testing dan validasi yang terpisah. Apa yang biasanya kita lakukan adalah mengambil model dengan akurasi validasi tertinggi dan kemudian menguji model dengan set testing.

Ini memastikan bahwa kita tidak overfit dari model. Menggunakan set validasi untuk memilih model terbaik adalah bentuk kebocoran data (atau "cheating") untuk memilih hasil yang menghasilkan skor tes terbaik dari ratusan di antaranya. Kebocoran data terjadi ketika informasi di luar set data training digunakan dalam model.

Dalam hal ini, set testing dan validasi kita adalah sama, karena kita memiliki ukuran sampel yang lebih kecil. Seperti yang telah kita bahas sebelumnya, (deep) neural network berkinerja terbaik ketika kita memiliki jumlah sampel yang sangat besar. Di bagian selanjutnya, kita akan melihat cara berbeda untuk mewakili kata sebagai vektor. Ini adalah cara yang sangat menarik dan kuat untuk bekerja dengan kata-kata di mana kita akan melihat bagaimana merepresentasikan kata-kata sebagai dense vector.

Apakah Word Embedding?

Teks dianggap sebagai bentuk urutan data yang mirip dengan data time series yang kita miliki dalam data cuaca atau data keuangan. Dalam model BOW sebelumnya, kita telah melihat cara merepresentasikan seluruh rangkaian kata sebagai vektor fitur tunggal. Sekarang kita akan melihat bagaimana merepresentasikan setiap kata sebagai vektor. Ada berbagai cara untuk membuat vektor teks, seperti:

  • Kata-kata diwakili oleh setiap kata sebagai vektor
  • Karakter diwakili oleh setiap karakter sebagai vektor
  • N-grams dari words/characters diwakili oleh sebuah vector (N-gram adalah kelompok yang saling tumpang tindih dari beberapa kata / karakter berikutnya dalam teks)

Dalam tutorial ini, kita akan melihat bagaimana berurusan dengan mewakili kata sebagai vektor yang merupakan cara umum untuk menggunakan teks dalam neural network. Dua cara yang mungkin untuk merepresentasikan sebuah kata sebagai vektor adalah one-hot encoding dan word embedding.

One-Hot Encoding

Cara pertama untuk merepresentasikan sebuah kata sebagai vektor adalah dengan menciptakan apa yang disebut one-hot encoding, yang hanya dilakukan dengan mengambil vektor dari panjang vocabulary dengan entri untuk setiap kata dalam korpus.

Dengan cara ini, untuk setiap kata, kita akan memiliki spot di vocabulary, sebuah vector dengan nilai zero dimana-mana kecuali di spot dari kata tersebut yang di set dengan satu. Seperti yang kita bayangkan, ini bisa menjadi vektor yang cukup besar untuk setiap kata dan tidak memberikan informasi tambahan seperti hubungan antar kata.

Katakanlah kita memiliki daftar kota seperti dalam contoh berikut:

cities = ['London', 'Berlin', 'Berlin', 'New York', 'London']
cities

Hasilnya:

['London', 'Berlin', 'Berlin', 'New York', 'London']

Kita dapat menggunakan scikit-learn dan LabelEncoder untuk meng-encode daftar cities menjadi nilai integer categorical integer sebagai berikut:

from sklearn.preprocessing import LabelEncoder

encoder = LabelEncoder()
city_labels = encoder.fit_transform(cities)
city_labels

Hasilnya

array([1, 0, 0, 2, 1])

Dengan menggunakan representasi ini, kita dapat menggunakan OneHotEncoder yang disediakan oleh scikit-learn untuk mengkodekan nilai categorical yang kita dapatkan sebelumnya ke dalam one-hot encoded numeric array. OneHotEncoder mengharapkan setiap nilai kategorikal berada di baris terpisah, jadi kita harus reshape array, kemudian kita dapat menerapkan encoder:

from sklearn.preprocessing import OneHotEncoder

encoder = OneHotEncoder(sparse=False)
city_labels = city_labels.reshape((5, 1))
encoder.fit_transform(city_labels)

Hasilnya

array([[0., 1., 0.],
       [1., 0., 0.],
       [1., 0., 0.],
       [0., 0., 1.],
       [0., 1., 0.]])

Kita dapat melihat bahwa categorical integer value mewakili posisi array yaitu 1 dan sisanya 0. Ini sering digunakan ketika kita memiliki categorical feature yang tidak dapat kita wakili sebagai nilai numerik tetapi kita masih ingin dapat menggunakannya dalam machine learning. Satu kasus penggunaan untuk pengkodean ini tentu saja kata-kata dalam teks tetapi paling jelas digunakan untuk kategori. Kategori tersebut dapat berupa kota, departemen, atau kategori lainnya.

Word Embeddings

Metode ini mewakili kata-kata sebagai vektor kata yang padat (juga disebut word embeddings) yang di-train tidak seperti one-hot encoding. Ini berarti bahwa word embeddings mengumpulkan lebih banyak informasi ke dimensi yang lebih kecil.

Perhatikan bahwa word embeddings tidak memahami teks seperti yang dilakukan manusia, tetapi mereka lebih memetakan struktur statistik dari bahasa yang digunakan dalam corpus. Tujuan mereka adalah memetakan makna semantik ke dalam ruang geometris. Ruang geometris ini kemudian disebut ruang embedding.

Ini akan memetakan kata-kata yang mirip secara semantik yang menutup pada ruang embedding seperti angka atau warna. Jika embedding menangkap hubungan antara kata-kata dengan baik, hal-hal seperti vektor aritmatika harusnya dimungkinkan. Contoh terkenal dalam bidang studi ini adalah kemampuan untuk memetakan King - Man + Woman = Queen.

Bagaimana kita bisa mendapatkan word embedding seperti itu? Kita memiliki dua opsi untuk ini. Salah satu caranya adalah melatih word embeddings anda selama men-training neural network anda. Cara lain adalah dengan menggunakan word embeddings pretrained yang dapat anda langsung gunakan dalam model anda. Di sana anda memiliki opsi untuk membiarkan word embedding ini tidak berubah selama pelatihan atau anda melatihnya juga.

Sekarang kita perlu melakukan tokenize data menjadi format yang dapat digunakan oleh word embeddings. Keras menawarkan beberapa metode untuk kenyamanan preprocessing teks dan preprocessing urutan yang dapat kita terapkan untuk mempersiapkan teks.

Kita dapat mulai dengan menggunakan class utlity Tokenizer yang dapat membuat vektor dari corpus teks menjadi daftar bilangan integer. Setiap integer memetakan suatu nilai dalam dictionary yang meng-encode seluruh korpus, dengan kunci dalam dictionary menjadi istilah dalam vocabulary itu sendiri. Kita dapat menambahkan parameter num_words, yang bertanggung jawab untuk mengatur ukuran vocabulary. Kata-kata num_words paling umum akan disimpan. Kita telah memiliki data pengujian dan pelatihan yang disiapkan dari contoh sebelumnya:

from keras.preprocessing.text import Tokenizer

tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(sentences_train)

X_train = tokenizer.texts_to_sequences(sentences_train)
X_test = tokenizer.texts_to_sequences(sentences_test)

vocab_size = len(tokenizer.word_index) + 1  # Adding 1 because of reserved 0 index

print(sentences_train[2])
print(X_train[2])

Hasilnya

Of all the dishes, the salmon was the best, but all were great.
[11, 43, 1, 171, 1, 283, 3, 1, 47, 26, 43, 24, 22]

Pengindeksan diurutkan sesuai dengan kata-kata yang paling umum dalam teks, yang dapat kita lihat dengan kata memiliki indeks 1. Penting untuk dicatat bahwa indeks 0 dicadangkan dan tidak diberikan untuk kata apa pun. Indeks nol ini digunakan untuk padding, yang akan diperkenalkan sebentar lagi.

Kata-kata yang tidak dikenal (kata-kata yang tidak ada dalam vocabulary) dilambangkan dalam Keras dengan word_count +1 karena mereka juga dapat menyimpan beberapa informasi. Kita dapat melihat indeks setiap kata dengan melihat kamus word_index dari objek Tokenizer:

for word in ['the', 'all', 'happy', 'sad']:
    print('{}: {}'.format(word, tokenizer.word_index[word]))

Hasilnya

the: 1
all: 43
happy: 320
sad: 450

Catatan: Perhatikan perbedaan antara teknik ini dan X_train yang diproduksi oleh CountVectorizer scikit-learn.

Dengan CountVectorizer, kami telah menumpuk vektor jumlah kata, dan masing-masing vektor memiliki panjang yang sama (ukuran total corpus vocabulary). Dengan Tokenizer, vektor yang dihasilkan sama dengan panjang setiap teks, dan angka tidak menunjukkan jumlah, tetapi lebih sesuai dengan nilai kata dari dictionary tokenizer.word_index.

Satu masalah yang kita miliki adalah bahwa setiap urutan teks memiliki panjang kata yang berbeda. Untuk mengatasinya, Anda dapat menggunakan pad_afterence() yang akan mengisi urutan kata dengan nol. Secara default, ini akan prepend nol tetapi kami ingin append nol. Biasanya tidak masalah apakah kita akan me-prepend atau append nol.

Selain itu kita ingin menambahkan parameter maxlen untuk menentukan berapa lama urutannya. Ini memotong urutan yang melebihi angka itu. Dalam kode berikut, kita dapat melihat cara menambahkan urutan dengan Keras:

from keras.preprocessing.sequence import pad_sequences

maxlen = 100

X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)

print(X_train[0, :])

Hasilnya

[  1  10   3 282 739  25   8 208  30  64 459 230  13   1 124   5 231   8
  58   5  67   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0]

Nilai pertama merepresentasikan indeks dalam vocabulary seperti yang telah kita pelajari dari contoh sebelumnya. Kita juga dapat melihat bahwa feature vector yang dihasilkan sebagian besar berisi nol, karena kita memiliki kalimat yang cukup pendek. Di bagian selanjutnya kita akan melihat cara bekerja dengan word embeddings di Keras.

Keras Embedding Layer

Perhatikan bahwa, pada titik ini, data kita masih di encode secara hardcoded. Kita belum memberi tahu Keras untuk mempelajari ruang embedding baru melalui tugas yang berurutan. Sekarang kita dapat menggunakan Layer Embedding Keras yang mengambil bilangan integer yang dihitung sebelumnya dan memetakannya ke dense vector dari embedding. Kita membutuhkan parameter berikut:

input_dim: ukuran vocabulary
output_dim: ukuran dense vector
input_length: panjang sequence / urutan

Dengan layer Embedding sekarang kita memiliki beberapa opsi. Salah satu caranya adalah dengan mengambil output dari lapisan embedding dan memasukannya ke Dense layer. Untuk melakukan ini, kita harus menambahkan Flatten layer di antaranya yang menyiapkan sequential input untuk Dense layer:

from keras.models import Sequential
from keras import layers

embedding_dim = 50

model = Sequential()
model.add(layers.Embedding(input_dim=vocab_size, 
                           output_dim=embedding_dim, 
                           input_length=maxlen))
model.add(layers.Flatten())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])
model.summary()

The result will be as follows:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_8 (Embedding)      (None, 100, 50)           87350     
_________________________________________________________________
flatten_3 (Flatten)          (None, 5000)              0         
_________________________________________________________________
dense_13 (Dense)             (None, 10)                50010     
_________________________________________________________________
dense_14 (Dense)             (None, 1)                 11        
=================================================================
Total params: 137,371
Trainable params: 137,371
Non-trainable params: 0
_________________________________________________________________

Kita sekarang dapat melihat bahwa kita memiliki 87350 parameter baru untuk di-training. Angka ini berasal dari vocab_size di kali dengan embedding_dim. Weight di lapisan embedding ini di inisialisasi dengan Weight acak dan kemudian disesuaikan melalui backpropagation selama pelatihan. Model ini mengambil kata-kata ketika datang dalam urutan kalimat sebagai vektor input. Kita dapat melatihnya sebagai berikut:

history = model.fit(X_train, y_train,
                    epochs=20,
                    verbose=False,
                    validation_data=(X_test, y_test),
                    batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history)

Hasilnya

Training Accuracy: 0.5100
Testing Accuracy:  0.4600


tumb

Ini biasanya bukan cara yang sangat andal untuk bekerja dengan data berurutan seperti yang kita lihat dalam kinerja. Saat bekerja dengan data sekuensial, kita ingin fokus pada metode yang melihat informasi lokal dan berurutan daripada informasi posisi absolut.

Cara lain untuk bekerja dengan embeddings adalah dengan menggunakan lapisan MaxPooling1D/AveragePooling1D atau GlobalMaxPooling1D/GlobalAveragePooling1D setelah embedding. Kita dapat menganggap layer pooling sebagai cara untuk menurunkan sampel (cara untuk mengurangi ukuran) feature vector yang masuk.

Dalam hal pooling max, kita mengambil nilai maksimum semua fitur di pooling untuk setiap dimensi feature. Dalam hal average pooling kita mengambil rata-rata, tetapi max pooling tampaknya lebih umum digunakan karena menyoroti nilai-nilai besar.

Global max/average pooling mengambil maximum/average dari semua feature sementara dalam kasus lainnya kita harus menentukan pool size. Keras sudah memiliki lapisannya sendiri yang dapat kita tambahkan dalam model sekuensial:

from keras.models import Sequential
from keras import layers

embedding_dim = 50 

model = Sequential()
model.add(layers.Embedding(input_dim=vocab_size, 
                           output_dim=embedding_dim, 
                           input_length=maxlen))
model.add(layers.GlobalMaxPool1D())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])
model.summary()

Hasilnya:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_9 (Embedding)      (None, 100, 50)           87350     
_________________________________________________________________
global_max_pooling1d_5 (Glob (None, 50)                0         
_________________________________________________________________
dense_15 (Dense)             (None, 10)                510       
_________________________________________________________________
dense_16 (Dense)             (None, 1)                 11        
=================================================================
Total params: 87,871
Trainable params: 87,871
Non-trainable params: 0
_________________________________________________________________

Prosedur untuk training tidak berubah:

history = model.fit(X_train, y_train,
                    epochs=50,
                    verbose=False,
                    validation_data=(X_test, y_test),
                    batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history)  

Hasil

Training Accuracy: 1.0000
Testing Accuracy:  0.8050
Loss-accurcay-max-pooling2.png

Kita sudah dapat melihat beberapa peningkatan dalam model kita. Selanjutnya kita akan melihat bagaimana kita dapat menggunakan pretrained word embeddings dan jika hal tersebut bisa membantu kita dengan model yang kita gunakan.

Penggunaan Pretrained Word Embeddings

Kita baru saja melihat contoh belajar word embeddings yang dimasukkan ke dalam model yang lebih besar yang ingin kita pecahkan.

Alternatif lain adalah dengan menggunakan ruang embedding yang dikomputasi yang menggunakan corpus yang jauh lebih besar. Dimungkinkan untuk memulai word embedding dengan hanya melatihnya pada kumpulan teks yang besar. Di antara metode yang paling populer adalah Word2Vec yang dikembangkan oleh Google dan GloVe (Global Vectors for Word Representation) yang dikembangkan oleh Stanford NLP Group.

Perhatikan bahwa itu adalah pendekatan yang berbeda dengan tujuan yang sama. Word2Vec mencapai ini dengan menggunakan neural networks dan GloVe mencapainya dengan co-occurrence matrix bersama dan dengan menggunakan faktorisasi matriks. Dalam kedua kasus kita akan berurusan dengan pengurangan dimensionalitas, tetapi Word2Vec lebih akurat dan GloVe lebih cepat untuk dihitung.

Dalam tutorial ini, kita akan melihat cara bekerja dengan word embeddings GloVe dan bukan Stanford NLP Group karena ukurannya lebih mudah dikelola daripada embeddings Word2Vec yang disediakan oleh Google. Silakan dan unduh word embeddings 6B (terlatih 6 miliar kata) dari http://nlp.stanford.edu/data/glove.6B.zip (822 MB).

Kita dapat menemukan word embeddings lainnya juga di halaman utama GloVe https://nlp.stanford.edu/projects/glove/. Kita dapat menemukan pretrained Word2Vec embeddings oleh Google di https://code.google.com/archive/p/word2vec/ . Jika anda ingin melatih word embeddings anda sendiri, anda dapat melakukannya secara efisien dengan paket gensim Python https://radimrehurek.com/gensim/index.html yang menggunakan Word2Vec untuk perhitungan. Rincian lebih lanjut tentang cara melakukan ini di https://radimrehurek.com/gensim/models/word2vec.html .

Kita dapat mulai menggunakan word embeddings dalam model kita. Kita dapat melihat pada contoh berikut bagaimana kita dapat memuat embedding matrix. Setiap baris dalam file dimulai dengan kata dan diikuti oleh embedding vector untuk kata tertentu.

Ini adalah file besar dengan 400.000 baris, dengan setiap baris mewakili kata yang diikuti oleh vektornya sebagai aliran floating point. Misalnya, berikut adalah 50 karakter pertama dari baris pertama:

$ head -n 1 glove.6B/glove.6B.50d.txt | cut -c-50
    the 0.418 0.24968 -0.41242 0.1217 0.34527 -0.04445

Karena kita tidak membutuhkan semua kata, kita hanya dapat fokus pada kata-kata yang kita miliki dalam vocabulary kita. Karena kita hanya memiliki jumlah kata yang terbatas dalam vocabulary kita, kita dapat melewatkan sebagian besar dari 40000 kata dalam pretrained word embeddings:

import numpy as np

def create_embedding_matrix(filepath, word_index, embedding_dim):
    vocab_size = len(word_index) + 1  # Adding again 1 because of reserved 0 index
    embedding_matrix = np.zeros((vocab_size, embedding_dim))

    with open(filepath) as f:
        for line in f:
            word, *vector = line.split()
            if word in word_index:
                idx = word_index[word] 
                embedding_matrix[idx] = np.array(
                        vector, dtype=np.float32)[:embedding_dim]
    return embedding_matrix

Kita dapat menggunakan fungsi ini sekarang untuk mengambil embedding matrix:

embedding_dim = 50
embedding_matrix = create_embedding_matrix(
        '/home/onno/TensorFlow/glove.6B/glove.6B.50d.txt',
        tokenizer.word_index, embedding_dim)

Sekarang kita siap menggunakan embedding matrix dalam training. Mari gunakan network sebelumnya dengan global max pooling dan lihat apakah kita bisa meningkatkan model ini. Saat kita menggunakan pretrained word embeddings kita memiliki pilihan untuk memperbolehkan embedding diperbarui selama training atau hanya menggunakan embedding vectors yang dihasilkan apa adanya.

Pertama, mari kita lihat sekilas berapa banyak embedding vectors yang bukan nol:

nonzero_elements = np.count_nonzero(np.count_nonzero(embedding_matrix, axis=1))
print(nonzero_elements / vocab_size)

Hasilnya:

0.9522330097087378

Ini berarti 95.1% dari vocabulary tercakup oleh pretrained model, yang merupakan cakupan yang baik dari vocabulary kita. Mari kita lihat kinerja ketika menggunakan lapisan GlobalMaxPool1D:

model = Sequential()
model.add(layers.Embedding(vocab_size, embedding_dim, 
                           weights=[embedding_matrix], 
                           input_length=maxlen, 
                           trainable=False))
model.add(layers.GlobalMaxPool1D())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])
model.summary()

Hasilnya:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_10 (Embedding)     (None, 100, 50)           87350     
_________________________________________________________________
global_max_pooling1d_6 (Glob (None, 50)                0         
_________________________________________________________________
dense_17 (Dense)             (None, 10)                510       
_________________________________________________________________
dense_18 (Dense)             (None, 1)                 11        
=================================================================
Total params: 87,871
Trainable params: 521
Non-trainable params: 87,350
_________________________________________________________________
history = model.fit(X_train, y_train,
                    epochs=50,
                    verbose=False,
                    validation_data=(X_test, y_test),
                    batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history)

Hasilnya:

Training Accuracy: 0.7500
Testing Accuracy:  0.6950


Loss-accuracy-embedding-untrained.png

Karena word embeddings tidak memperoleh training tambahan, maka hasilnya akan lebih rendah. Tetapi sekarang mari kita lihat bagaimana kinerjanya jika kita mengizinkan embedding untuk di training dengan menggunakan trainable=True:

model = Sequential()
model.add(layers.Embedding(vocab_size, embedding_dim, 
                           weights=[embedding_matrix], 
                           input_length=maxlen, 
                           trainable=True))
model.add(layers.GlobalMaxPool1D())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])
model.summary()

Hasilnya:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_11 (Embedding)     (None, 100, 50)           87350     
_________________________________________________________________
global_max_pooling1d_7 (Glob (None, 50)                0         
_________________________________________________________________
dense_19 (Dense)             (None, 10)                510       
_________________________________________________________________
dense_20 (Dense)             (None, 1)                 11        
=================================================================
Total params: 87,871
Trainable params: 87,871
Non-trainable params: 0
_________________________________________________________________
history = model.fit(X_train, y_train,
                    epochs=50,
                    verbose=False,
                    validation_data=(X_test, y_test),
                    batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history)

Hasilnya:

Training Accuracy: 1.0000
Testing Accuracy:  0.8250
thub

Kita dapat lihat bahwa paling efektif jika mengijinkan embeddings di train. Ketika berhadapan dengan set training yang besar, itu dapat meningkatkan proses training menjadi lebih cepat daripada tanpa. Dalam kasus kita, itu tampaknya membantu tetapi tidak banyak. Ini tidak harus karena pretrained word embeddings.

Sekarang saatnya untuk fokus pada model neural network yang lebih maju untuk melihat apakah mungkin untuk meningkatkan model dan memberikan keunggulan pada model-model sebelumnya.

Convolutional Neural Networks (CNN)

Convolutional neural networks atau disebut juga convnets adalah salah satu perkembangan paling menarik dalam machine learning dalam beberapa tahun terakhir.

Mereka telah merevolusi klasifikasi gambar dan computer vision dengan mampu mengekstraksi fitur dari gambar dan menggunakannya dalam neural networks. Properti yang membuatnya berguna dalam pemrosesan gambar membuat mereka juga berguna untuk pemrosesan urutan. Anda dapat membayangkan CNN sebagai specialized neural network yang mampu mendeteksi pola tertentu.

Jika itu hanya neural network lain, apa yang membedakannya dari apa yang telah kita pelajari sebelumnya?

CNN memiliki lapisan tersembunyi yang disebut lapisan konvolusional. Ketika kita membayangkan sebuah gambar, komputer harus berurusan dengan matrix dua dimensi angka dan oleh karena itu kita perlu beberapa cara untuk mendeteksi fitur dalam matrix ini. Lapisan konvolusional ini mampu mendeteksi tepi, sudut dan jenis tekstur lainnya yang menjadikannya tool yang istimewa. Lapisan convolutional terdiri dari beberapa filter yang digeser melintasi gambar dan dapat mendeteksi fitur-fitur tertentu.

Ini adalah inti dari tekniknya, proses konvolusi matematika. Dengan setiap lapisan konvolusional, network dapat mendeteksi pola yang lebih kompleks. Dalam Feature Visualization https://distill.pub/2017/feature-visualization/ oleh Chris Olah kita bisa mendapatkan intuisi yang baik seperti apa fitur-fitur ini.

Saat kita bekerja dengan data sekuensial, seperti teks, kita bekerja dengan konvolusi satu dimensi, tetapi gagasan dan aplikasinya tetap sama. Kita masih ingin menangkap pola dalam urutan yang menjadi lebih kompleks dengan setiap lapisan konvolusional yang ditambahkan.

Pada gambar berikut, kita dapat melihat bagaimana konvolusi bekerja. Dimulai dengan menambahkan patch fitur input dengan ukuran kernel filter. Dengan patch ini, kita mengambil produk dot dari Weight filter yang dikalikan. Convnet satu dimensi tidak sama dengan terjemahan, yang berarti bahwa urutan tertentu dapat dikenali pada posisi yang berbeda. Ini dapat membantu untuk pola-pola tertentu dalam teks:

1d-convolution.png

1D Convolution (Image source)

Sekarang mari kita lihat bagaimana kita dapat menggunakan network ini di Keras. Keras menawarkan lagi berbagai lapisan konvolusional yang dapat kita gunakan untuk tugas ini. Lapisan yang kita butuhkan adalah lapisan Conv1D. Lapisan ini memiliki lagi berbagai parameter untuk dipilih. Yang kita minati saat ini adalah jumlah filter, ukuran kernel, dan fungsi aktivasi. Kita bisa menambahkan lapisan ini di antara lapisan Embedding dan lapisan GlobalMaxPool1D:

embedding_dim = 100

model = Sequential()
model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))
model.add(layers.Conv1D(128, 5, activation='relu'))
model.add(layers.GlobalMaxPooling1D())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])
model.summary()

Hasilnya:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_13 (Embedding)     (None, 100, 100)          174700    
_________________________________________________________________
conv1d_2 (Conv1D)            (None, 96, 128)           64128     
_________________________________________________________________
global_max_pooling1d_9 (Glob (None, 128)               0         
_________________________________________________________________
dense_23 (Dense)             (None, 10)                1290      
_________________________________________________________________
dense_24 (Dense)             (None, 1)                 11        
=================================================================
Total params: 240,129
Trainable params: 240,129
Non-trainable params: 0
_________________________________________________________________
history = model.fit(X_train, y_train,
                    epochs=10,
                    verbose=False,
                    validation_data=(X_test, y_test),
                    batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history)

Hasilnya:

Training Accuracy: 1.0000
Testing Accuracy:  0.7700
Loss-accuracy-convolution-model4.png

Anda dapat melihat bahwa accuracy 80% tampaknya merupakan rintangan yang sulit untuk diatasi dengan kumpulan data ini dan CNN mungkin tidak dilengkapi dengan baik. Alasan untuk dataran tinggi accuracy seperti itu adalah:

  • Tidak cukup banyak sample training
  • Data yang kita miliki kurang generalize
  • Gagal fokus saat mengatur hyperparameters

CNN bekerja paling baik dengan training set yang besar di mana mereka dapat menemukan generalisasi di mana model sederhana seperti regresi logistik tidak akan mampu.

Optimasi Hyperparameters

Salah satu langkah penting dalam deep learnig dan bekerja dengan neural network adalah optimasi hyperparameter.

Seperti yang kita lihat dalam model yang telah kita gunakan sejauh ini, bahkan dengan model yang lebih sederhana, kita memiliki sejumlah besar parameter untuk di-tweak dan dipilih. Parameter tersebut disebut hyperparameters. Ini adalah bagian yang paling memakan waktu dari machine learning dan sayangnya tidak ada solusi yang cocok untuk semua.

Ketika anda melihat kompetisi di Kaggle, salah satu tempat terbesar untuk bersaing dengan sesama ilmuwan data lainnya, anda dapat melihat bahwa banyak tim dan model pemenang telah melalui banyak penyesuaian dan percobaan hingga mencapai puncaknya. Jadi jangan berkecil hati ketika menjadi sulit dan anda mencapai dataran tinggi, tetapi pikirkan cara anda dapat mengoptimalkan model atau data.

Salah satu metode populer untuk optimasi hyperparameter adalah grid search. Apa yang dilakukan metode ini adalah mengambil daftar parameter dan menjalankan model dengan setiap kombinasi parameter yang dapat ditemukannya. Ini adalah cara yang paling menyeluruh tetapi juga cara yang paling berat secara komputasi untuk melakukan ini. Cara umum lain, pencarian acak, yang akan kita lihat dalam tindakan di sini, cukup mengambil kombinasi parameter secara acak.

Untuk menerapkan random search dengan Keras, kita harus menggunakan KerasClassifier yang berfungsi sebagai pembungkus untuk scikit-learn API. Dengan pembungkus ini kita dapat menggunakan berbagai tool yang tersedia dengan scikit-learn seperti cross-validation. Class yang kita butuhkan adalah RandomizedSearchCV yang mengimplementasikan random search dengan cross-validation. Cross-validation adalah cara untuk memvalidasi model dan mengambil seluruh rangkaian data dan memisahkannya menjadi beberapa data set testing dan training.

Ada berbagai jenis cross-validation. Salah satu jenis adalah cross-validation k-fold yang akan kita lihat dalam contoh ini. Dalam tipe ini set data dipartisi ke dalam k set ukuran yang sama di mana satu set digunakan untuk testing dan sisanya dari partisi digunakan untuk training. Ini memungkinkan kita untuk menjalankan k dalam berbagai proses yang berbeda, di mana setiap partisi pernah digunakan sebagai set testing. Jadi, semakin tinggi k adalah semakin akurat model evaluasi, tetapi semakin kecil setiap set testing-nya.

Langkah pertama untuk KerasClassifier adalah memiliki fungsi yang menciptakan model Keras. Kita akan menggunakan model sebelumnya, tetapi kita akan mengizinkan berbagai parameter ditetapkan untuk optimasi hyperparameter:

def create_model(num_filters, kernel_size, vocab_size, embedding_dim, maxlen):
    model = Sequential()
    model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))
    model.add(layers.Conv1D(num_filters, kernel_size, activation='relu'))
    model.add(layers.GlobalMaxPooling1D())
    model.add(layers.Dense(10, activation='relu'))
    model.add(layers.Dense(1, activation='sigmoid'))
    model.compile(optimizer='adam',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    return model

Selanjutnya, kita ingin menentukan parameter grid yang ingin kita gunakan dalam training. Ini terdiri dari dictionary dengan masing-masing parameter dalam fungsi sebelumnya. Jumlah spasi di grid adalah 3 * 3 * 1 * 1 * 1, di mana masing-masing angka tersebut adalah jumlah pilihan yang berbeda untuk parameter yang diberikan.

Kita dapat melihat bagaimana ini bisa menjadi komputasi yang mahal dengan sangat cepat, tetapi untungnya grid search dan random search sebetulnya paralel, dan class muncul dengan parameter n_jobs yang memungkinkan kita menguji ruang grid secara paralel. Kotak parameter diinisialisasi dengan dictionary berikut:

param_grid = dict(num_filters=[32, 64, 128],
                  kernel_size=[3, 5, 7],
                  vocab_size=[5000], 
                  embedding_dim=[50],
                  maxlen=[100])

Sekarang kita sudah siap untuk mulai menjalankan random search. Dalam contoh ini kita mengulang setiap set data dan kemudian kita ingin memproses ulang data dengan cara yang sama seperti sebelumnya. Setelah itu kita mengambil fungsi sebelumnya dan menambahkannya ke KerasClassifier wrapper class termasuk jumlah epoch. Instance yang dihasilkan dan parameter grid kemudian digunakan sebagai estimator di RandomSearchCV class.

Selain itu, kita dapat memilih jumlah fold dalam k-folds cross-validation, yang dalam kasus ini 4. Kita telah melihat sebagian besar kode dalam cuplikan ini sebelumnya dalam contoh sebelumnya. Selain RandomSearchCV dan KerasClassifier, telah menambahkan sedikit kode untuk penanganan evaluasi:

from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import RandomizedSearchCV

# Main settings
epochs = 20
embedding_dim = 50
maxlen = 100
output_file = 'data/output.txt'

# Run grid search for each source (yelp, amazon, imdb)
for source, frame in df.groupby('source'): 
    print('Running grid search for data set :', source)
    sentences = df['sentence'].values
    y = df['label'].values

    # Train-test split
    sentences_train, sentences_test, y_train, y_test = train_test_split(
        sentences, y, test_size=0.25, random_state=1000)

    # Tokenize words
    tokenizer = Tokenizer(num_words=5000)
    tokenizer.fit_on_texts(sentences_train)
    X_train = tokenizer.texts_to_sequences(sentences_train)
    X_test = tokenizer.texts_to_sequences(sentences_test)

    # Adding 1 because of reserved 0 index
    vocab_size = len(tokenizer.word_index) + 1

    # Pad sequences with zeros
    X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
    X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)

    # Parameter grid for grid search
    param_grid = dict(num_filters=[32, 64, 128],
                      kernel_size=[3, 5, 7],
                      vocab_size=[vocab_size],
                      embedding_dim=[embedding_dim],
                      maxlen=[maxlen])
    model = KerasClassifier(build_fn=create_model,
                            epochs=epochs, batch_size=10,
                            verbose=False)
    grid = RandomizedSearchCV(estimator=model, param_distributions=param_grid,
                              cv=4, verbose=1, n_iter=5)
    grid_result = grid.fit(X_train, y_train)

    # Evaluate testing set
    test_accuracy = grid.score(X_test, y_test)

    # Save and evaluate results
    prompt = input(f'finished {source}; write to file and proceed? [y/n]')
    if prompt.lower() not in {'y', 'true', 'yes'}:
        break
    with open(output_file, 'a') as f:
        s = ('Running {} data set\nBest Accuracy : '
             '{:.4f}\n{}\nTest Accuracy : {:.4f}\n\n')
        output_string = s.format(
            source,
            grid_result.best_score_,
            grid_result.best_params_,
            test_accuracy)
        print(output_string)
        f.write(output_string)

Ini membutuhkan waktu yang merupakan kesempatan sempurna untuk pergi keluar untuk mendapatkan udara segar atau bahkan mendaki gunung, tergantung pada berapa banyak model yang ingin kita jalankan. Mari kita lihat apa yang kita punya:

Running amazon data set
Best Accuracy : 0.8122
{'vocab_size': 4603, 'num_filters': 64, 'maxlen': 100, 'kernel_size': 5, 'embedding_dim': 50}
Test Accuracy : 0.8457
Running imdb data set
Best Accuracy : 0.8161
{'vocab_size': 4603, 'num_filters': 128, 'maxlen': 100, 'kernel_size': 5, 'embedding_dim': 50}
Test Accuracy : 0.8210
Running yelp data set
Best Accuracy : 0.8127
{'vocab_size': 4603, 'num_filters': 64, 'maxlen': 100, 'kernel_size': 7, 'embedding_dim': 50}
Test Accuracy : 0.8384

Menarik! Untuk beberapa hal maka akurasi testing lebih tinggi daripada akurasi training yang mungkin karena ada perbedaan besar dalam skor selama cross-validation. Kita dapat melihat bahwa kita masih tidak dapat menembus banyak melalui 80% yang ditakuti, yang tampaknya menjadi batas alami untuk data ini dengan ukuran yang diberikan. Ingat bahwa kita memiliki satu set data kecil dan convolutional neural networks cenderung melakukan yang terbaik dengan set data besar.

Metode lain untuk CV adalah nested cross-validation (ditampilkan di sini) yang digunakan ketika hyperparameters juga perlu dioptimalkan. Ini digunakan karena model non-nested CV yang dihasilkan memiliki bias terhadap kumpulan data yang dapat menyebabkan skor terlalu optimis. Kita tahu, ketika melakukan optimasi hiperparameter seperti yang kita lakukan dalam contoh sebelumnya, kita memilih hyperparameter terbaik untuk set training tertentu tetapi ini tidak berarti bahwa hyperparameter ini menggeneralisasi yang terbaik.

Conclusion

Kita telah belajar cara bekerja dengan klasifikasi teks dengan Keras, dan kita telah beralih dari model bag-of-words dengan regresi logistik menjadi metode yang semakin maju yang mengarah ke convolutional neural networks.

Kita sekarang harus terbiasa dengan word embeddings, mengapa mereka berguna, dan juga bagaimana menggunakan pretrained word embeddings untuk training kita. Kita juga telah belajar cara bekerja dengan neural network dan cara menggunakan optimasi hyperparameter untuk memeras lebih banyak kinerja dari model kita.

Satu topik besar yang belum kita bahas di sini dibiarkan lain waktu adalah recurrent neural networks, lebih khusus LSTM dan GRU. Itu adalah tool powerfull dan populer lainnya untuk bekerja dengan data sequential seperti teks atau time series. Perkembangan menarik lainnya saat ini dalam neural network yang menggunakan perhatian yang sedang dalam penelitian aktif dan tampaknya menjadi langkah berikutnya yang menjanjikan karena LSTM cenderung berat pada perhitungan.

Kita sekarang memiliki pemahaman tentang landasan penting dalam natural language processing yang dapat kita gunakan untuk semua jenis text classification. Analisis sentimen adalah contoh yang paling menonjol untuk ini, tetapi ini mencakup banyak aplikasi lain seperti:

  • Deteksi Spam di email
  • Automatic tagging pada text
  • Kategorisasi artikel berita untuk topik yang sudah di definisikan.

Kita dapat menggunakan pengetahuan ini dan model-model yang telah kita latih pada proyek lanjutan seperti dalam tutorial ini untuk menggunakan analisis sentimen pada continuous stream data twitter dengan Kibana dan Elasticsearch. Kita juga bisa menggabungkan analisis sentimen atau text classification dengan speech recognition seperti dalam tutorial praktis ini menggunakan library SpeechRecognition di Python.

Referensi


Pranala Menarik