Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Temel metin sınıflandırması

TensorFlow.org üzerinde görüntüle Google Colab'da yayınla Kaynağı GitHub'da görüntüle Not defterini indir

Bu eğitimde, diskte depolanan düz metin dosyalarından başlayarak metin sınıflandırması gösterilmektedir. Bir IMDB veri kümesinde duyarlılık analizi gerçekleştirmek için ikili bir sınıflandırıcıyı eğiteceksiniz. Dizüstü bilgisayarın sonunda, Yığın Taşması ile ilgili bir programlama sorusunun etiketini tahmin etmek için çok sınıflı bir sınıflandırıcıyı eğiteceğiniz bir deneme var.

 import matplotlib.pyplot as plt
import os
import re
import shutil
import string
import tensorflow as tf

from tensorflow.keras import layers
from tensorflow.keras import losses
from tensorflow.keras import preprocessing
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
 
 print(tf.__version__)
 
2.3.0

Duygu analizi

Bu dizüstü bilgisayar, film incelemelerini, incelemenin metnine göre olumlu veya olumsuz olarak sınıflandırmak için bir duygu analizi modeli eğitiyor. Bu, önemli ve yaygın olarak uygulanabilir bir makine öğrenimi problemi olan ikili -veya iki-sınıflı sınıflandırma örneğidir.

İnternet Film Veritabanı'ndan 50.000 film incelemesi metnini içeren Büyük Film İnceleme Veri Kümesi'ni kullanacaksınız. Bunlar eğitim için 25.000 incelemeye ve test için 25.000 incelemeye ayrılmıştır. Eğitim ve test setleri dengelidir , yani eşit sayıda olumlu ve olumsuz yorum içerirler.

IMDB veri kümesini indirin ve keşfedin

Veri kümesini indirip çıkaralım, ardından dizin yapısını inceleyelim.

 url = "https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz"

dataset = tf.keras.utils.get_file("aclImdb_v1.tar.gz", url,
                                    untar=True, cache_dir='.',
                                    cache_subdir='')

dataset_dir = os.path.join(os.path.dirname(dataset), 'aclImdb')
 
Downloading data from https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
84131840/84125825 [==============================] - 7s 0us/step

 os.listdir(dataset_dir)
 
['imdb.vocab', 'train', 'test', 'README', 'imdbEr.txt']
 train_dir = os.path.join(dataset_dir, 'train')
os.listdir(train_dir)
 
['urls_pos.txt',
 'neg',
 'labeledBow.feat',
 'pos',
 'urls_neg.txt',
 'unsup',
 'unsupBow.feat',
 'urls_unsup.txt']

aclImdb/train/pos ve aclImdb/train/neg dizinleri, her biri tek bir film incelemesi olan birçok metin dosyası içerir. Bir tanesine bakalım.

 sample_file = os.path.join(train_dir, 'pos/1181_9.txt')
with open(sample_file) as f:
  print(f.read())
 
Rachel Griffiths writes and directs this award winning short film. A heartwarming story about coping with grief and cherishing the memory of those we've loved and lost. Although, only 15 minutes long, Griffiths manages to capture so much emotion and truth onto film in the short space of time. Bud Tingwell gives a touching performance as Will, a widower struggling to cope with his wife's death. Will is confronted by the harsh reality of loneliness and helplessness as he proceeds to take care of Ruth's pet cow, Tulip. The film displays the grief and responsibility one feels for those they have loved and lost. Good cinematography, great direction, and superbly acted. It will bring tears to all those who have lost a loved one, and survived.

Veri kümesini yükleyin

Daha sonra, verileri diskten yükler ve eğitim için uygun bir formata hazırlarsınız. Bunu yapmak için, aşağıdaki gibi bir dizin yapısı bekleyen yararlı text_dataset_from_directory yardımcı programını kullanacaksınız.

 main_directory/
...class_a/
......a_text_1.txt
......a_text_2.txt
...class_b/
......b_text_1.txt
......b_text_2.txt
 

İkili sınıflandırma için bir veri kümesi hazırlamak için diskte class_a ve class_b karşılık gelen iki klasöre ihtiyacınız olacaktır. Bunlar aclImdb/train/pos ve aclImdb/train/neg bulunabilecek olumlu ve olumsuz film incelemeleri olacaktır. IMDB veri kümesi ek klasörler içerdiğinden, bu yardımcı programı kullanmadan önce bunları kaldırabilirsiniz.

 remove_dir = os.path.join(train_dir, 'unsup')
shutil.rmtree(remove_dir)
 

Ardından, etiketli bir tf.data.Dataset oluşturmak için text_dataset_from_directory yardımcı programını tf.data.Dataset . tf.data , verilerle çalışmak için güçlü bir araç koleksiyonudur.

Bir makine öğrenimi deneyi yürütürken, veri kümenizi üç bölüme ayırmak en iyi uygulamadır: tren , doğrulama ve test .

IMDB veri kümesi zaten tren ve teste ayrılmıştır, ancak bir doğrulama setinden yoksundur. Aşağıdaki validation_split argümanını kullanarak eğitim verilerinin 80:20'lik bir bölümünü kullanarak bir doğrulama kümesi oluşturalım.

 batch_size = 32
seed = 42

raw_train_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='training', 
    seed=seed)
 
Found 25000 files belonging to 2 classes.
Using 20000 files for training.

Yukarıda görebileceğiniz gibi, eğitim klasöründe eğitim için% 80 (veya 20.000) kullanacağınız 25.000 örnek var. Bir anda göreceğiniz gibi, bir veri kümesini doğrudan modele geçirerek bir model model.fit . tf.data konusunda tf.data , veri kümesini yineleyebilir ve aşağıdaki gibi birkaç örnek yazdırabilirsiniz.

 for text_batch, label_batch in raw_train_ds.take(1):
  for i in range(3):
    print("Review", text_batch.numpy()[i])
    print("Label", label_batch.numpy()[i])
 
Review b'"Pandemonium" is a horror movie spoof that comes off more stupid than funny. Believe me when I tell you, I love comedies. Especially comedy spoofs. "Airplane", "The Naked Gun" trilogy, "Blazing Saddles", "High Anxiety", and "Spaceballs" are some of my favorite comedies that spoof a particular genre. "Pandemonium" is not up there with those films. Most of the scenes in this movie had me sitting there in stunned silence because the movie wasn\'t all that funny. There are a few laughs in the film, but when you watch a comedy, you expect to laugh a lot more than a few times and that\'s all this film has going for it. Geez, "Scream" had more laughs than this film and that was more of a horror film. How bizarre is that?<br /><br />*1/2 (out of four)'
Label 0
Review b"David Mamet is a very interesting and a very un-equal director. His first movie 'House of Games' was the one I liked best, and it set a series of films with characters whose perspective of life changes as they get into complicated situations, and so does the perspective of the viewer.<br /><br />So is 'Homicide' which from the title tries to set the mind of the viewer to the usual crime drama. The principal characters are two cops, one Jewish and one Irish who deal with a racially charged area. The murder of an old Jewish shop owner who proves to be an ancient veteran of the Israeli Independence war triggers the Jewish identity in the mind and heart of the Jewish detective.<br /><br />This is were the flaws of the film are the more obvious. The process of awakening is theatrical and hard to believe, the group of Jewish militants is operatic, and the way the detective eventually walks to the final violent confrontation is pathetic. The end of the film itself is Mamet-like smart, but disappoints from a human emotional perspective.<br /><br />Joe Mantegna and William Macy give strong performances, but the flaws of the story are too evident to be easily compensated."
Label 0
Review b'Great documentary about the lives of NY firefighters during the worst terrorist attack of all time.. That reason alone is why this should be a must see collectors item.. What shocked me was not only the attacks, but the"High Fat Diet" and physical appearance of some of these firefighters. I think a lot of Doctors would agree with me that,in the physical shape they were in, some of these firefighters would NOT of made it to the 79th floor carrying over 60 lbs of gear. Having said that i now have a greater respect for firefighters and i realize becoming a firefighter is a life altering job. The French have a history of making great documentary\'s and that is what this is, a Great Documentary.....'
Label 1

İncelemelerin ham metin içerdiğine dikkat edin (noktalama işaretleriyle ve ara sıra HTML etiketleriyle <br/> ). Aşağıdaki bölümde bunların nasıl ele alınacağını göstereceksiniz.

Etiketler 0 veya 1'dir. Bunlardan hangisinin pozitif ve negatif film incelemelerine karşılık geldiğini görmek için veri kümesindeki class_names özelliğini kontrol edebilirsiniz.

 print("Label 0 corresponds to", raw_train_ds.class_names[0])
print("Label 1 corresponds to", raw_train_ds.class_names[1])
 
Label 0 corresponds to neg
Label 1 corresponds to pos

Ardından, bir doğrulama ve test veri kümesi oluşturacaksınız. Doğrulama için eğitim setinden kalan 5.000 incelemeyi kullanacaksınız.

 raw_val_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='validation', 
    seed=seed)
 
Found 25000 files belonging to 2 classes.
Using 5000 files for validation.

 raw_test_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/test', 
    batch_size=batch_size)
 
Found 25000 files belonging to 2 classes.

Veri kümesini eğitim için hazırlama

Ardından, yardımcı preprocessing.TextVectorization kullanarak verileri standartlaştıracak, tokenleştirecek ve vektörelleştireceksiniz.

Standartlaştırma, tipik olarak veri kümesini basitleştirmek için noktalama işaretlerini veya HTML öğelerini kaldırmak için metnin önişlemini ifade eder. Tokenization, dizeleri belirteçlere bölmeyi ifade eder (örneğin, bir cümleyi boşluklara bölerek tek tek kelimelere bölme). Vektörizasyon, simgeleri nöral bir ağa beslenebilmeleri için sayılara dönüştürmeyi ifade eder. Tüm bu görevler bu katmanla gerçekleştirilebilir.

Yukarıda gördüğünüz gibi, incelemeler <br /> gibi çeşitli HTML etiketleri içeriyor. Bu etiketler, TextVectorization katmanındaki varsayılan standartlaştırıcı tarafından kaldırılmaz (metni düşük çekirdeğe dönüştürür ve varsayılan olarak noktalama işaretlerini kaldırır, ancak HTML'yi şeritlemez). HTML'yi kaldırmak için özel bir standartlaştırma işlevi yazacaksınız.

 def custom_standardization(input_data):
  lowercase = tf.strings.lower(input_data)
  stripped_html = tf.strings.regex_replace(lowercase, '<br />', ' ')
  return tf.strings.regex_replace(stripped_html,
                                  '[%s]' % re.escape(string.punctuation),
                                  '')
 

Ardından, bir TextVectorization katmanı oluşturacaksınız. verilerimizi standartlaştırmak, tokenleştirmek ve vektörleştirmek için bu katmanı kullanacaksınız. Her belirteç için benzersiz tamsayı dizinleri oluşturmak üzere output_mode int olarak ayarlarsınız.

Varsayılan bölme işlevini ve yukarıda tanımladığınız özel standartlaştırma işlevini kullandığınızı unutmayın. Ayrıca açık bir maksimum gibi model için bazı sabitleri tanımlayacağız sequence_length tam için ped veya trankulatı dizileri için katmanı neden olur, sequence_length değerler.

 max_features = 10000
sequence_length = 250

vectorize_layer = TextVectorization(
    standardize=custom_standardization,
    max_tokens=max_features,
    output_mode='int',
    output_sequence_length=sequence_length)
 

Ardından, çağrısı yapacağı adapt veri kümesine önişleme tabakasının durumunu sığdırmak için. Bu, modelin tamsayılara bir dizeler dizini oluşturmasına neden olur.

 # Make a text-only dataset (without labels), then call adapt
train_text = raw_train_ds.map(lambda x, y: x)
vectorize_layer.adapt(train_text)
 

Bazı verileri önceden işlemek için bu katmanı kullanmanın sonucunu görmek için bir işlev oluşturalım.

 def vectorize_text(text, label):
  text = tf.expand_dims(text, -1)
  return vectorize_layer(text), label
 
 # retrieve a batch (of 32 reviews and labels) from the dataset
text_batch, label_batch = next(iter(raw_train_ds))
first_review, first_label = text_batch[0], label_batch[0]
print("Review", first_review)
print("Label", raw_train_ds.class_names[first_label])
print("Vectorized review", vectorize_text(first_review, first_label))
 
Review tf.Tensor(b'Silent Night, Deadly Night 5 is the very last of the series, and like part 4, it\'s unrelated to the first three except by title and the fact that it\'s a Christmas-themed horror flick.<br /><br />Except to the oblivious, there\'s some obvious things going on here...Mickey Rooney plays a toymaker named Joe Petto and his creepy son\'s name is Pino. Ring a bell, anyone? Now, a little boy named Derek heard a knock at the door one evening, and opened it to find a present on the doorstep for him. Even though it said "don\'t open till Christmas", he begins to open it anyway but is stopped by his dad, who scolds him and sends him to bed, and opens the gift himself. Inside is a little red ball that sprouts Santa arms and a head, and proceeds to kill dad. Oops, maybe he should have left well-enough alone. Of course Derek is then traumatized by the incident since he watched it from the stairs, but he doesn\'t grow up to be some killer Santa, he just stops talking.<br /><br />There\'s a mysterious stranger lurking around, who seems very interested in the toys that Joe Petto makes. We even see him buying a bunch when Derek\'s mom takes him to the store to find a gift for him to bring him out of his trauma. And what exactly is this guy doing? Well, we\'re not sure but he does seem to be taking these toys apart to see what makes them tick. He does keep his landlord from evicting him by promising him to pay him in cash the next day and presents him with a "Larry the Larvae" toy for his kid, but of course "Larry" is not a good toy and gets out of the box in the car and of course, well, things aren\'t pretty.<br /><br />Anyway, eventually what\'s going on with Joe Petto and Pino is of course revealed, and as with the old story, Pino is not a "real boy". Pino is probably even more agitated and naughty because he suffers from "Kenitalia" (a smooth plastic crotch) so that could account for his evil ways. And the identity of the lurking stranger is revealed too, and there\'s even kind of a happy ending of sorts. Whee.<br /><br />A step up from part 4, but not much of one. Again, Brian Yuzna is involved, and Screaming Mad George, so some decent special effects, but not enough to make this great. A few leftovers from part 4 are hanging around too, like Clint Howard and Neith Hunter, but that doesn\'t really make any difference. Anyway, I now have seeing the whole series out of my system. Now if I could get some of it out of my brain. 4 out of 5.', shape=(), dtype=string)
Label neg
Vectorized review (<tf.Tensor: shape=(1, 250), dtype=int64, numpy=
array([[1287,  313, 2380,  313,  661,    7,    2,   52,  229,    5,    2,
         200,    3,   38,  170,  669,   29, 5492,    6,    2,   83,  297,
         549,   32,  410,    3,    2,  186,   12,   29,    4,    1,  191,
         510,  549,    6,    2, 8229,  212,   46,  576,  175,  168,   20,
           1, 5361,  290,    4,    1,  761,  969,    1,    3,   24,  935,
        2271,  393,    7,    1, 1675,    4, 3747,  250,  148,    4,  112,
         436,  761, 3529,  548,    4, 3633,   31,    2, 1331,   28, 2096,
           3, 2912,    9,    6,  163,    4, 1006,   20,    2,    1,   15,
          85,   53,  147,    9,  292,   89,  959, 2314,  984,   27,  762,
           6,  959,    9,  564,   18,    7, 2140,   32,   24, 1254,   36,
           1,   85,    3, 3298,   85,    6, 1410,    3, 1936,    2, 3408,
         301,  965,    7,    4,  112,  740, 1977,   12,    1, 2014, 2772,
           3,    4,  428,    3, 5177,    6,  512, 1254,    1,  278,   27,
         139,   25,  308,    1,  579,    5,  259, 3529,    7,   92, 8981,
          32,    2, 3842,  230,   27,  289,    9,   35,    2, 5712,   18,
          27,  144, 2166,   56,    6,   26,   46,  466, 2014,   27,   40,
        2745,  657,  212,    4, 1376, 3002, 7080,  183,   36,  180,   52,
         920,    8,    2, 4028,   12,  969,    1,  158,   71,   53,   67,
          85, 2754,    4,  734,   51,    1, 1611,  294,   85,    6,    2,
        1164,    6,  163,    4, 3408,   15,   85,    6,  717,   85,   44,
           5,   24, 7158,    3,   48,  604,    7,   11,  225,  384,   73,
          65,   21,  242,   18,   27,  120,  295,    6,   26,  667,  129,
        4028,  948,    6,   67,   48,  158,   93,    1]])>, <tf.Tensor: shape=(), dtype=int32, numpy=0>)

Yukarıda görebileceğiniz gibi, her token bir tamsayı ile değiştirildi. .get_vocabulary() çağırarak her tamsayının karşılık gelen belirteci (dize) .get_vocabulary() .

 print("1287 ---> ",vectorize_layer.get_vocabulary()[1287])
print(" 313 ---> ",vectorize_layer.get_vocabulary()[313])
print('Vocabulary size: {}'.format(len(vectorize_layer.get_vocabulary())))
 
1287 --->  silent
 313 --->  night
Vocabulary size: 10000

Modelinizi eğitmeye neredeyse hazırsınız. Son bir önişleme adımı olarak, daha önce oluşturduğunuz TextVectorization katmanını tren, doğrulama ve test veri kümesine uygulayacaksınız.

 train_ds = raw_train_ds.map(vectorize_text)
val_ds = raw_val_ds.map(vectorize_text)
test_ds = raw_test_ds.map(vectorize_text)
 

Veri kümesini performans için yapılandırma

Bunlar, G / Ç'nin engellenmemesi için veri yüklerken kullanmanız gereken iki önemli yöntemdir.

.cache() verileri diskten yüklendikten sonra bellekte tutar. Bu, modelinizi eğitirken veri kümesinin bir darboğaz haline gelmemesini sağlayacaktır. Veri kümeniz belleğe sığmayacak kadar büyükse, bu yöntemi kullanarak çok sayıda küçük dosyadan daha verimli okunan, performans gösteren bir disk önbelleği de oluşturabilirsiniz.

.prefetch() , eğitim sırasında veri önişleme ve model yürütme ile çakışır.

Her iki yöntem hakkında ve veri performans kılavuzunda verilerin diske nasıl önbelleğe alınacağı hakkında daha fazla bilgi edinebilirsiniz.

 AUTOTUNE = tf.data.experimental.AUTOTUNE

train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
test_ds = test_ds.cache().prefetch(buffer_size=AUTOTUNE)
 

Modeli oluşturun

Sinir ağımızı yaratmanın zamanı geldi:

 embedding_dim = 16
 
 model = tf.keras.Sequential([
  layers.Embedding(max_features + 1, embedding_dim),
  layers.Dropout(0.2),
  layers.GlobalAveragePooling1D(),
  layers.Dropout(0.2),
  layers.Dense(1)])

model.summary()
 
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, None, 16)          160016    
_________________________________________________________________
dropout (Dropout)            (None, None, 16)          0         
_________________________________________________________________
global_average_pooling1d (Gl (None, 16)                0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 16)                0         
_________________________________________________________________
dense (Dense)                (None, 1)                 17        
=================================================================
Total params: 160,033
Trainable params: 160,033
Non-trainable params: 0
_________________________________________________________________

Katmanlar sınıflandırıcıyı oluşturmak için sırayla yığınlanır:

  1. İlk katman bir Embedding katmanıdır. Bu katman, tamsayı olarak kodlanmış incelemeleri alır ve her sözcük dizini için bir gömme vektörü arar. Bu vektörler model tren olarak öğrenilir. Vektörler çıkış dizisine bir boyut ekler. Ortaya çıkan boyutlar: (batch, sequence, embedding) . Düğünler hakkında daha fazla bilgi edinmek için gömme öğreticisine bakın .
  2. Daha sonra, GlobalAveragePooling1D katmanı, sıra boyutu üzerinde ortalamayı alarak her örnek için sabit uzunlukta bir çıktı vektörü döndürür. Bu, modelin değişken uzunluktaki girdileri mümkün olan en basit şekilde işlemesini sağlar.
  3. Bu sabit uzunluklu çıkış vektörü, 16 gizli birim içeren tam bağlı ( Dense ) bir katmandan geçirilir.
  4. Son katman, tek bir çıkış düğümü ile yoğun bir şekilde bağlanır.

Kayıp fonksiyonu ve optimize edici

Bir modelin bir kayıp fonksiyonu ve eğitim için bir optimize ediciye ihtiyacı vardır. Bu bir ikili sınıflandırma sorunu olduğundan ve model bir olasılık (sigmoid aktivasyonlu tek bir birim katman) losses.BinaryCrossentropy kayıpları kullanacaksınız.

Şimdi, modeli optimize edici ve kayıp fonksiyonu kullanacak şekilde yapılandırın:

 model.compile(loss=losses.BinaryCrossentropy(from_logits=True), optimizer='adam', metrics=tf.metrics.BinaryAccuracy(threshold=0.0))
 

Modeli eğitin

dataset nesnesini fit yöntemine ileterek modeli eğiteceksiniz.

 epochs = 10
history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=epochs)
 
Epoch 1/10
625/625 [==============================] - 3s 5ms/step - loss: 0.6632 - binary_accuracy: 0.6931 - val_loss: 0.6135 - val_binary_accuracy: 0.7752
Epoch 2/10
625/625 [==============================] - 3s 4ms/step - loss: 0.5472 - binary_accuracy: 0.8003 - val_loss: 0.4968 - val_binary_accuracy: 0.8220
Epoch 3/10
625/625 [==============================] - 3s 4ms/step - loss: 0.4434 - binary_accuracy: 0.8459 - val_loss: 0.4187 - val_binary_accuracy: 0.8486
Epoch 4/10
625/625 [==============================] - 3s 4ms/step - loss: 0.3770 - binary_accuracy: 0.8660 - val_loss: 0.3726 - val_binary_accuracy: 0.8622
Epoch 5/10
625/625 [==============================] - 2s 4ms/step - loss: 0.3349 - binary_accuracy: 0.8786 - val_loss: 0.3442 - val_binary_accuracy: 0.8678
Epoch 6/10
625/625 [==============================] - 2s 4ms/step - loss: 0.3046 - binary_accuracy: 0.8889 - val_loss: 0.3253 - val_binary_accuracy: 0.8722
Epoch 7/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2807 - binary_accuracy: 0.8977 - val_loss: 0.3118 - val_binary_accuracy: 0.8726
Epoch 8/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2609 - binary_accuracy: 0.9046 - val_loss: 0.3026 - val_binary_accuracy: 0.8762
Epoch 9/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2443 - binary_accuracy: 0.9123 - val_loss: 0.2961 - val_binary_accuracy: 0.8774
Epoch 10/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2309 - binary_accuracy: 0.9163 - val_loss: 0.2915 - val_binary_accuracy: 0.8804

Modeli değerlendirin

Modelin nasıl performans gösterdiğini görelim. İki değer döndürülecektir. Kayıp (hatamızı temsil eden bir sayı, daha düşük değerler daha iyidir) ve doğruluk.

 loss, accuracy = model.evaluate(test_ds)

print("Loss: ", loss)
print("Accuracy: ", accuracy)
 
782/782 [==============================] - 2s 3ms/step - loss: 0.3097 - binary_accuracy: 0.8740
Loss:  0.30967268347740173
Accuracy:  0.8740400075912476

Bu oldukça saf bir yaklaşım yaklaşık% 86'lık bir doğruluk sağlar.

Zaman içinde doğruluk ve kayıp grafiği oluşturun

model.fit() , eğitim sırasında olan her şeyi içeren bir sözlük içeren bir History nesnesi döndürür:

 history_dict = history.history
history_dict.keys()
 
dict_keys(['loss', 'binary_accuracy', 'val_loss', 'val_binary_accuracy'])

Dört giriş vardır: eğitim ve doğrulama sırasında izlenen her metrik için bir giriş. Bunları, karşılaştırma için eğitim ve doğrulama kaybının yanı sıra eğitim ve doğrulama doğruluğunu çizmek için kullanabilirsiniz:

 acc = history_dict['binary_accuracy']
val_acc = history_dict['val_binary_accuracy']
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(acc) + 1)

# "bo" is for "blue dot"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()
 

png

 plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')

plt.show()
 

png

Bu grafikte, noktalar eğitim kaybını ve doğruluğunu temsil eder ve düz çizgiler doğrulama kaybı ve doğruluğudur.

Her çağda egzersiz kaybının azaldığına ve her çağda egzersiz doğruluğunun arttığına dikkat edin. Degrade iniş optimizasyonu kullanılırken bu beklenen bir durumdur - her yinelemede istenen miktarı en aza indirmelidir.

Doğrulama kaybı ve doğruluğu için durum böyle değildir - eğitim doğruluğundan önce zirveye ulaşmış gibi görünmektedir. Bu, aşırı takmanın bir örneğidir: model, eğitim verilerinde daha önce hiç görmediği verilere göre daha iyi performans gösterir. Bu noktadan sonra, model, verileri test etmek için genelleştirilmeyen eğitim verilerine özgü gösterimleri aşırı optimize eder ve öğrenir.

Bu özel durum için, doğrulama doğruluğu artık artmadığında eğitimi durdurarak aşırı sığmayı önleyebilirsiniz. Bunu yapmanın bir yolu da EarlyStopping geri aramasını kullanmaktır.

Modeli dışa aktar

Yukarıdaki kodda, modele metin beslemeden önce veri kümesine TextVectorization katmanını uyguladınız. Modelinizi ham dizeleri işleyebilecek duruma getirmek istiyorsanız (örneğin, dağıtımı basitleştirmek için), modelinize TextVectorization katmanını dahil edebilirsiniz. Bunu yapmak için, az önce eğittiğiniz ağırlıkları kullanarak yeni bir model oluşturabilirsiniz.

 export_model = tf.keras.Sequential([
  vectorize_layer,
  model,
  layers.Activation('sigmoid')
])

export_model.compile(
    loss=losses.BinaryCrossentropy(from_logits=False), optimizer="adam", metrics=['accuracy']
)

# Test it with `raw_test_ds`, which yields raw strings
loss, accuracy = export_model.evaluate(raw_test_ds)
print(accuracy)
 
782/782 [==============================] - 3s 4ms/step - loss: 0.3097 - accuracy: 0.8740
0.8740400075912476

Metin önişleme mantığının modelinize dahil edilmesi, dağıtımı basitleştiren ve tren / test eğriltme potansiyelini azaltan bir modeli üretim için dışa aktarmanıza olanak tanır.

TextVectorization katmanınızı nereye uygulayacağınızı seçerken aklınızda bulundurmanız gereken bir performans farkı vardır. Modelinizin dışında kullanmak GPU eğitimi alırken zaman uyumsuz CPU işleme ve verilerinizin arabelleğe alınmasını sağlar. Bu nedenle, modelinizi GPU üzerinde eğitiyorsanız, modelinizi geliştirirken en iyi performansı elde etmek için muhtemelen bu seçeneğe gitmek istersiniz, ardından konuşlandırmaya hazır olduğunuzda modelinize TextVectorization katmanını dahil etmeye geçin .

Modelleri kaydetme hakkında daha fazla bilgi edinmek için bu öğreticiyi ziyaret edin.

Alıştırma: Stack Overflow sorularında çok sınıflı sınıflandırma

Bu eğitimde, ikili bir sınıflandırıcıyı IMDB veri kümesinde sıfırdan nasıl eğiteceğiniz gösterilmiştir. Bir alıştırma olarak, bu not defterini, Yığın Taşması'ndaki bir programlama sorusunun etiketini tahmin etmek için çok sınıflı bir sınıflandırıcı eğitecek şekilde değiştirebilirsiniz.

Yığın Taşmasına gönderilen birkaç bin programlama sorusunun (örneğin, "Bir sözlüğü Python'da değere göre nasıl sıralayabilirim?") İçeren bir veri kümesi hazırladık. Bunların her biri tam olarak bir etiketle (Python, CSharp, JavaScript veya Java) etiketlenmiştir. Göreviniz bir soruyu girdi olarak almak ve bu durumda Python gibi uygun etiketi tahmin etmektir.

Çalışacağınız veri seti, BigQuery'deki 17 milyondan fazla gönderi içeren çok daha büyük genel Stack Overflow veri kümesinden çıkarılan birkaç bin soru içeriyor.

Veri kümesini indirdikten sonra, daha önce çalıştığınız IMDB veri kümesine benzer bir dizin yapısına sahip olduğunu göreceksiniz:

 train/
...python/
......0.txt
......1.txt
...javascript/
......0.txt
......1.txt
...csharp/
......0.txt
......1.txt
...java/
......0.txt
......1.txt
 

Bu alıştırmayı tamamlamak için, aşağıdaki değişiklikleri yaparak bu not defterini Yığın Taşması veri kümesiyle çalışacak şekilde değiştirmeniz gerekir:

  1. Dizüstü bilgisayarınızın üst kısmında, önceden oluşturduğumuz Yığın Taşması veri kümesini indirmek için IMDB veri kümesini indiren kodu kodla güncelleyin. Yığın Taşması veri kümesi benzer bir dizin yapısına sahip olduğundan, çok fazla değişiklik yapmanız gerekmez.

  2. Şimdi dört çıkış sınıfı olduğu için modelinizin son katmanını Dense(4) okuyacak şekilde değiştirin.

  3. Modelinizi derlerken, kaybı SparseCategoricalCrossentropy olarak değiştirin. Bu, her sınıf için etiketler tamsayı olduğunda (bizim durumumuzda 0, 1 , 2 veya 3 olabilir ) çok sınıflı bir sınıflandırma sorunu için kullanılacak doğru kayıp işlevidir.

  4. Bu değişiklikler tamamlandıktan sonra, çok sınıflı bir sınıflandırıcıyı eğitebileceksiniz.

Sıkışırsanız, burada bir çözüm bulabilirsiniz .

Daha fazla bilgi edinme

Bu öğretici sıfırdan metin sınıflandırması tanıttı. Genel olarak metin sınıflandırma iş akışı hakkında daha fazla bilgi edinmek için bu kılavuzu Google Developers'tan okumanızı öneririz.

 
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.