Bu bölümde modelimizi oluşturmak, eğitmek ve değerlendirmek için çalışacağız. 3. adımda S/W
oranımızı kullanarak bir n-gram modeli veya dizi modeli kullanmayı seçtik.
Şimdi, sınıflandırma algoritmamızı yazıp eğitme zamanı. Bunun için TensorFlow'u tf.keras API'siyle kullanırız.
Keras ile makine öğrenimi modelleri oluşturmak için katmanları bir araya getirmek, veri işleme yapı taşlarını bir araya getirmek gerekir. Tıpkı Lego tuğlalarını monte etmek gibi. Bu katmanlar, girişlerimizde gerçekleştirmek istediğimiz bir dönüşüm dizisi belirtebilmemizi sağlar. Öğrenim algoritmamız tek bir metin girişini alıp tek bir sınıflandırmayı gösterirken Sıralı model API'sini kullanarak doğrusal bir katman yığını oluşturabiliriz.
Şekil 9: Doğrusal katman yığını
Giriş katmanı ve ara katmanlar, n-gram veya dizi modeli oluşturmamıza bağlı olarak farklı şekilde yapılandırılır. Ancak model türünden bağımsız olarak, son katman belirli bir sorun için aynı olacaktır.
Son Katmanı Oluşturma
Yalnızca 2 sınıfımız (ikili sınıflandırma) olduğunda modelimiz tek bir olasılık puanı vermelidir. Örneğin, belirli bir giriş örneği için 0.2
çıkışının "Bu örneğin birinci sınıftaki (1. sınıf) %20 güveni, 0. sınıftaki% 80'i" anlamına geldiğini unutmayın. Böyle bir olasılık sonucunu elde etmek için son katmanın etkinleştirme işlevinin sigmoid işlevi olması ve kayıp işlevinin
1. sırada olması gerekir{1=1{11{11{1'ü{10 girilmelidir{11{1){1
2'den fazla sınıf (çok sınıflı sınıflandırma) varsa modelimiz sınıf başına bir olasılık puanı oluşturmalıdır. Bu puanların toplamı
1 olmalıdır. Örneğin, {0: 0.2, 1: 0.7, 2: 0.1}
çıkışı "Bu örneğin sınıf 0, sınıf %10 ve sınıf 2'de %10 olduğu" anlamına gelir. Bu sonuçları elde etmek için son katmanın etkinleştirme işlevi softmax, modeli eğitmek için kullanılan kayıp işlevi ise kategorik çapraz entropi şeklinde olmalıdır. (Sağdaki Şekil 10'a bakın).
Şekil 10: Son katman
Aşağıdaki kod, sınıf sayısını giriş olarak alan ve uygun sayıda katman birimi (ikili sınıflandırma için 1 birim, her sınıf için 1 birim) ve uygun etkinleştirme işlevi üreten bir işlevi tanımlar:
def _get_last_layer_units_and_activation(num_classes):
"""Gets the # units and activation function for the last network layer.
# Arguments
num_classes: int, number of classes.
# Returns
units, activation values.
"""
if num_classes == 2:
activation = 'sigmoid'
units = 1
else:
activation = 'softmax'
units = num_classes
return units, activation
Aşağıdaki iki bölümde n-gram modelleri ve dizi modelleri için kalan model katmanlarının oluşturulmasına ilişkin adım adım açıklamalı kılavuz bulunmaktadır.
S/W
oranı küçük olduğunda n-gram modellerinin dizi modellerinden daha iyi performans gösterdiğini tespit ettik. Dizi modelleri, çok sayıda küçük ve yoğun vektör olduğunda daha iyi sonuç verir. Bunun nedeni, yerleşik ilişkilerin yoğun bir alanda öğrenilmesidir. Bunun en iyi sonucu, birçok örnekte görülür.
N-gram modeli oluşturma [Seçenek A]
Jetonları, n-gram modelleri olarak bağımsız olarak (kelime sırasını dikkate almadan) işleyen modellerden bahsediyoruz. Basit çok katmanlı algılar (lojistik regresyon dahil), gradyan güçlendirme makineleri ve vektör makinelerini destekleyen modellerin tümü bu kategoriye girer. Metin sıralama hakkında herhangi bir bilgiden yararlanamazlar.
Yukarıda belirtilen n-gram modellerinin bazılarının performansını karşılaştırdık ve çok katmanlı algıların (MLP'ler) genellikle diğer seçeneklerden daha iyi performans gösterdiğini gözlemledik. MLP'ler kolayca tanımlanıp anlaşılabilir, doğru doğruluk sağlar ve nispeten az hesaplama gerektirir.
Aşağıdaki kod, tf.keras'da iki katmanlı bir makine öğrenimi modeli tanımlar. Bu örnekte, Normalleştirme için çıkış katmanları eklenir (eğitim örneklerine aşırı sığdırma işlemi önlemek için).
from tensorflow.python.keras import models
from tensorflow.python.keras.layers import Dense
from tensorflow.python.keras.layers import Dropout
def mlp_model(layers, units, dropout_rate, input_shape, num_classes):
"""Creates an instance of a multi-layer perceptron model.
# Arguments
layers: int, number of `Dense` layers in the model.
units: int, output dimension of the layers.
dropout_rate: float, percentage of input to drop at Dropout layers.
input_shape: tuple, shape of input to the model.
num_classes: int, number of output classes.
# Returns
An MLP model instance.
"""
op_units, op_activation = _get_last_layer_units_and_activation(num_classes)
model = models.Sequential()
model.add(Dropout(rate=dropout_rate, input_shape=input_shape))
for _ in range(layers-1):
model.add(Dense(units=units, activation='relu'))
model.add(Dropout(rate=dropout_rate))
model.add(Dense(units=op_units, activation=op_activation))
return model
Dizi modeli oluşturma [Option B]
Jetonların bitişiğinden öğrenilebilen dizi modelleri, dizi modelleri olarak adlandırılır. Buna, modellerin CNN ve RNN sınıfları da dahildir. Veriler, bu modeller için dizi vektörleri olarak önceden işlenir.
Dizi modelleri hakkında genellikle öğrenilecek parametre sayısı daha fazladır. Bu modellerin ilk katmanı, yoğun bir vektör alanındaki kelimeler arasındaki ilişkiyi öğrenen bir yerleştirme katmanıdır. Kelime ilişkilerini öğrenmek çok sayıda örnek üzerinde en iyi sonucu verir.
Belirli bir veri kümesindeki kelimeler, büyük olasılıkla söz konusu veri kümesine özgü değildir. Böylece, diğer veri kümelerini kullanarak veri kümemizdeki kelimeler arasındaki ilişkiyi öğrenebiliriz. Bunun için, başka bir veri kümesinden öğrenilen yerleştirmeyi yerleştirme katmanımıza aktarabiliriz. Bu yerleştirmeler, önceden eğitilmiş yerleştirmeler olarak adlandırılır. Önceden eğitilmiş bir yerleştirmenin kullanılması, modele öğrenme sürecinde bir başlangıç sağlar.
GloVe gibi büyük arşivler kullanılarak eğitilmiş, önceden eğitilmiş yerleştirmeler vardır. GloVe, birçok şirkette (esas olarak Wikipedia) eğitildi. Dizi modellerimizi eğitirken GloVe yerleştirmelerinin bir sürümünü kullandık ve önceden eğitilmiş yerleştirmelerin ağırlıklarını dondurup ağın geri kalanını eğittikse modellerin iyi performans göstermediğini gözlemledik. Bunun nedeni, yerleştirme katmanının eğitildiği bağlamın, içeriği kullandığımız bağlamdan farklı olması olabilir.
Wikipedia verileri üzerinde eğitilmiş GloVe yerleştirmeleri, IMDb veri kümesimizdeki dil kalıplarıyla uyumlu olmayabilir. Tahmin edilen ilişkilerde güncelleme yapılması gerekebilir. Diğer bir deyişle, yerleştirme ağırlıkları içeriğe dayalı ayar yapılması gerekebilir. Bunu iki aşamada yapıyoruz:
İlk çalıştırmada, yerleştirme katmanı ağırlıkları dondurulduğunda ağın geri kalanının öğrenmesine izin verilir. Bu çalıştırmanın sonunda model ağırlıkları, başlatılmamış değerlerinden çok daha iyi bir duruma ulaşır. İkinci çalıştırma için yerleştirme katmanının da öğrenmesine izin vererek ağdaki tüm ağırlıklarda küçük ayarlamalar yapıyoruz. Bu işleme, hassas yerleştirme yerleştirmesi diyoruz.
Hassas ayarlı yerleştirmeler daha iyi sonuç verir. Ancak bu durum, ağı eğitmek için gerekli olan işlem gücünün artmasını sağlar. Yeterli sayıda örnek aldığımızda, bir yerleştirmeyi sıfırdan öğrenebiliriz.
S/W > 15K
için sıfırdan başlayarak hassas ayarlı yerleştirme ile aynı doğruluk düzeyinin geçerli olduğunu gördük.
CNN, sepCNN, RNN (LSTM &GRU), CNN-RNN ve yığınlı RNN gibi farklı dizi modellerini karşılaştırdık ve farklı mimari modeller uyguladık. Genellikle veri açısından verimli ve bilgi işlem açısından verimli bir evrimsel ağ varyantı olan sepCNN'lerin diğer modellerden daha iyi performans gösterdiğini tespit ettik.
Aşağıdaki kod, dört katmanlı bir sepCNN modeli oluşturur:
from tensorflow.python.keras import models from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers from tensorflow.python.keras.layers import Dense from tensorflow.python.keras.layers import Dropout from tensorflow.python.keras.layers import Embedding from tensorflow.python.keras.layers import SeparableConv1D from tensorflow.python.keras.layers import MaxPooling1D from tensorflow.python.keras.layers import GlobalAveragePooling1D def sepcnn_model(blocks, filters, kernel_size, embedding_dim, dropout_rate, pool_size, input_shape, num_classes, num_features, use_pretrained_embedding=False, is_embedding_trainable=False, embedding_matrix=None): """Creates an instance of a separable CNN model. # Arguments blocks: int, number of pairs of sepCNN and pooling blocks in the model. filters: int, output dimension of the layers. kernel_size: int, length of the convolution window. embedding_dim: int, dimension of the embedding vectors. dropout_rate: float, percentage of input to drop at Dropout layers. pool_size: int, factor by which to downscale input at MaxPooling layer. input_shape: tuple, shape of input to the model. num_classes: int, number of output classes. num_features: int, number of words (embedding input dimension). use_pretrained_embedding: bool, true if pre-trained embedding is on. is_embedding_trainable: bool, true if embedding layer is trainable. embedding_matrix: dict, dictionary with embedding coefficients. # Returns A sepCNN model instance. """ op_units, op_activation = _get_last_layer_units_and_activation(num_classes) model = models.Sequential() # Add embedding layer. If pre-trained embedding is used add weights to the # embeddings layer and set trainable to input is_embedding_trainable flag. if use_pretrained_embedding: model.add(Embedding(input_dim=num_features, output_dim=embedding_dim, input_length=input_shape[0], weights=[embedding_matrix], trainable=is_embedding_trainable)) else: model.add(Embedding(input_dim=num_features, output_dim=embedding_dim, input_length=input_shape[0])) for _ in range(blocks-1): model.add(Dropout(rate=dropout_rate)) model.add(SeparableConv1D(filters=filters, kernel_size=kernel_size, activation='relu', bias_initializer='random_uniform', depthwise_initializer='random_uniform', padding='same')) model.add(SeparableConv1D(filters=filters, kernel_size=kernel_size, activation='relu', bias_initializer='random_uniform', depthwise_initializer='random_uniform', padding='same')) model.add(MaxPooling1D(pool_size=pool_size)) model.add(SeparableConv1D(filters=filters * 2, kernel_size=kernel_size, activation='relu', bias_initializer='random_uniform', depthwise_initializer='random_uniform', padding='same')) model.add(SeparableConv1D(filters=filters * 2, kernel_size=kernel_size, activation='relu', bias_initializer='random_uniform', depthwise_initializer='random_uniform', padding='same')) model.add(GlobalAveragePooling1D()) model.add(Dropout(rate=dropout_rate)) model.add(Dense(op_units, activation=op_activation)) return model
Modelinizi Eğitin
Model mimarisini inşa ettiğimize göre, modeli eğitmemiz gerekiyor. Eğitim, modelin mevcut durumunu temel alan bir tahminde bulunmayı, tahminin ne kadar yanlış olduğunu hesaplamayı ve ağın ağırlıklarını ya da parametrelerini güncellemeyi bu hatayı azaltıp modeli daha iyi hale getirmeyi içerir. Bu işlem, modelimiz birleşene ve artık öğrenene kadar tekrarlanır. Bu işlem için seçilecek üç temel parametre vardır (bkz. Tablo 2).
- Metrik: Modelimizin performansını ölçmek için metrik kullanma. Denemelerimizde metrik olarak doğruluğu kullandık.
- Kayıp işlevi: Eğitim işleminin, ağ ağırlıklarını ayarlayarak en aza indirmeye çalıştığı bir kayıp değerini hesaplamak için kullanılan bir işlev. Sınıflandırma sorunları için entropi kaybı iyi sonuç verir.
- Optimize Edici: Ağ ağırlıklarının, kayıp işlevinin sonucuna göre nasıl güncelleneceğine karar veren bir işlevdir. Denemelerimizde popüler Adam optimize ediciyi kullandık.
Keras'ta bu öğrenme parametrelerini derleme yöntemini kullanarak bir modele iletebiliriz.
Öğrenme parametresi | Değer |
---|---|
Metrik | doğruluk |
Kayıp işlevi - ikili sınıflandırma | ikili_terentropi |
Kayıp işlevi - çok sınıflı sınıflandırma | seyrek_kategorik_tüm_kros |
Optimize Edici | Adam |
2. Tablo: Öğrenme parametreleri
Asıl eğitim fit yöntemi kullanılarak gerçekleştirilir.
Veri kümenizin boyutuna bağlı olarak bu, çoğu işlem döngüsünün harcanacağı yöntemdir. Her eğitim yinelemesinde, kayıpı hesaplamak için eğitim verilerinizden batch_size
örnek kullanılır ve ağırlıklar bu değere göre bir kez güncellenir.
Model, eğitim veri kümesinin tamamını gördükten sonra eğitim süreci bir epoch
işlemini tamamlar. Her dönemin sonunda, modelin ne kadar iyi öğrendiğini değerlendirmek için doğrulama veri kümesini kullanırız. Veri kümesini kullanarak önceden belirlenmiş sayıda dönem için eğitimi tekrarlarız. Bunu, optimizasyon doğruluğu art arda kullanılan dönemler arasında dengeli hale geldiğinde erken durarak optimize edebilir ve böylece modelin artık eğitilmediğini görebilirsiniz.
Eğitim hiper parametresi | Değer |
---|---|
Öğrenme oranı | 1e-3 |
Dönemler | 1.000 |
Grup boyutu | 512 |
Erken durdurma | parametre: val_loss, sabır: 1 |
3. Tablo: Hiperparametreleri eğitme
Aşağıdaki Keras kodu, yukarıdaki 2. Tablo ve 3'te seçilen parametreleri kullanarak eğitim sürecini uygular:
def train_ngram_model(data, learning_rate=1e-3, epochs=1000, batch_size=128, layers=2, units=64, dropout_rate=0.2): """Trains n-gram model on the given dataset. # Arguments data: tuples of training and test texts and labels. learning_rate: float, learning rate for training model. epochs: int, number of epochs. batch_size: int, number of samples per batch. layers: int, number of `Dense` layers in the model. units: int, output dimension of Dense layers in the model. dropout_rate: float: percentage of input to drop at Dropout layers. # Raises ValueError: If validation data has label values which were not seen in the training data. """ # Get the data. (train_texts, train_labels), (val_texts, val_labels) = data # Verify that validation labels are in the same range as training labels. num_classes = explore_data.get_num_classes(train_labels) unexpected_labels = [v for v in val_labels if v not in range(num_classes)] if len(unexpected_labels): raise ValueError('Unexpected label values found in the validation set:' ' {unexpected_labels}. Please make sure that the ' 'labels in the validation set are in the same range ' 'as training labels.'.format( unexpected_labels=unexpected_labels)) # Vectorize texts. x_train, x_val = vectorize_data.ngram_vectorize( train_texts, train_labels, val_texts) # Create model instance. model = build_model.mlp_model(layers=layers, units=units, dropout_rate=dropout_rate, input_shape=x_train.shape[1:], num_classes=num_classes) # Compile model with learning parameters. if num_classes == 2: loss = 'binary_crossentropy' else: loss = 'sparse_categorical_crossentropy' optimizer = tf.keras.optimizers.Adam(lr=learning_rate) model.compile(optimizer=optimizer, loss=loss, metrics=['acc']) # Create callback for early stopping on validation loss. If the loss does # not decrease in two consecutive tries, stop training. callbacks = [tf.keras.callbacks.EarlyStopping( monitor='val_loss', patience=2)] # Train and validate model. history = model.fit( x_train, train_labels, epochs=epochs, callbacks=callbacks, validation_data=(x_val, val_labels), verbose=2, # Logs once per epoch. batch_size=batch_size) # Print results. history = history.history print('Validation accuracy: {acc}, loss: {loss}'.format( acc=history['val_acc'][-1], loss=history['val_loss'][-1])) # Save model. model.save('IMDb_mlp_model.h5') return history['val_acc'][-1], history['val_loss'][-1]
Dizi modelini eğitmek için gerekli kod örneklerini burada bulabilirsiniz.