paint-brush
Ürün Odaklı Bir Yönlü Makine Öğrenimi Metin Sınıflandırması Örnek Olay İncelemesiile@bemorelavender
29,341 okumalar
29,341 okumalar

Ürün Odaklı Bir Yönlü Makine Öğrenimi Metin Sınıflandırması Örnek Olay İncelemesi

ile Maria K17m2024/03/12
Read on Terminal Reader

Çok uzun; Okumak

Bu, ürün odaklı bir değişiklik içeren bir makine öğrenimi vaka çalışmasıdır: Geliştirmemiz gereken gerçek bir ürünümüz varmış gibi davranacağız. Bir veri kümesini keşfedeceğiz ve lojistik regresyon, yinelenen sinir ağları ve transformatörler gibi farklı modelleri deneyerek bunların ne kadar doğru olduğuna, ürünü nasıl geliştireceklerine, ne kadar hızlı çalıştıklarına ve hata ayıklamanın kolay olup olmadığına bakacağız. ve ölçeği büyütün.
featured image - Ürün Odaklı Bir Yönlü Makine Öğrenimi Metin Sınıflandırması Örnek Olay İncelemesi
Maria K HackerNoon profile picture


Geliştirmemiz gereken gerçek bir ürünümüz varmış gibi davranacağız. Bir veri kümesini keşfedeceğiz ve lojistik regresyon, yinelenen sinir ağları ve transformatörler gibi farklı modelleri deneyerek bunların ne kadar doğru olduğuna, ürünü nasıl geliştireceklerine, ne kadar hızlı çalıştıklarına ve hata ayıklamanın kolay olup olmadığına bakacağız. ve ölçeği büyütün.


Örnek olay kodunun tamamını GitHub'da okuyabilir ve Jupyter Notebook Viewer'da etkileşimli grafikler içeren analiz not defterini görebilirsiniz.


Heyecanlı? Hadi hadi bakalım!

Görev ayarı

Bir E-ticaret web sitemizin olduğunu düşünün. Satıcı, satmak istediği ürünlerin açıklamalarını bu web sitesine yükleyebilir. Ayrıca öğelerin kategorilerini manuel olarak seçmeleri gerekir, bu da onları yavaşlatabilir.


Görevimiz, öğe açıklamasına göre kategori seçimini otomatikleştirmektir. Ancak yanlış otomatikleştirilmiş bir seçim, hiç otomasyon olmamasından daha kötüdür çünkü bir hata fark edilmeyebilir ve bu da satış kaybına neden olabilir. Bu nedenle emin olmadığımız takdirde otomatik etiket ayarlamamayı tercih edebiliriz.


Bu vaka çalışması için kullanacağımız Zenodo E-ticaret metin veri kümesi , öğe açıklamalarını ve kategorilerini içerir.


İyi ya da kötü? En iyi model nasıl seçilir

Aşağıda birden fazla model mimarisini ele alacağız ve başlamadan önce en iyi seçeneğin nasıl seçileceğine karar vermek her zaman iyi bir uygulamadır. Bu model ürünümüzü nasıl etkileyecek? …altyapımız mı?


Açıkçası, çeşitli modelleri çevrimdışı olarak karşılaştırmak için bir teknik kalite ölçümümüz olacak. Bu durumda, çok sınıflı bir sınıflandırma görevimiz var, bu yüzden dengesiz etiketleri iyi bir şekilde ele alan dengeli bir doğruluk puanı kullanalım.


Elbette, bir adayı test etmenin tipik son aşaması AB testidir; bu, müşterilerin değişiklikten nasıl etkilendiğine dair daha iyi bir resim sağlayan çevrimiçi aşamadır. AB testi genellikle çevrimdışı testten daha fazla zaman alır, bu nedenle yalnızca çevrimdışı aşamadaki en iyi adaylar teste tabi tutulur. Bu bir örnek olaydır ve gerçek kullanıcılarımız olmadığından AB testini ele almayacağız.


Bir adayı AB testi için ilerletmeden önce başka neleri göz önünde bulundurmalıyız? Çevrimiçi test süresinden tasarruf etmek ve mümkün olan en iyi çözümü gerçekten test ettiğimizden emin olmak için çevrimdışı aşamada ne düşünebiliriz?


Teknik metrikleri etki odaklı metriklere dönüştürme

Dengeli doğruluk harikadır ancak bu puan "Modelin ürünü tam olarak nasıl etkileyeceği?" sorusuna yanıt vermez. Daha fazla ürün odaklı puan bulmak için modeli nasıl kullanacağımızı anlamalıyız.


Bizim ortamımızda hata yapmak, cevap vermemekten daha kötüdür çünkü satıcının hatayı fark etmesi ve kategoriyi manuel olarak değiştirmesi gerekecektir. Fark edilmeyen bir hata satışları düşürecek ve satıcının kullanıcı deneyimini kötüleştirecek, müşteri kaybetme riskiyle karşı karşıya kalacağız.


Bundan kaçınmak için, modelin puanı için eşikler seçeceğiz, böylece kendimize yalnızca %1 hata payı bırakacağız. Ürün odaklı metrik daha sonra aşağıdaki gibi ayarlanabilir:


Hata toleransımız yalnızca %1 ise öğelerin yüzde kaçını otomatik olarak kategorize edebiliriz?


En iyi modeli seçerken buna aşağıda Automatic categorisation percentage olarak değineceğiz. Eşik seçim kodunun tamamını burada bulabilirsiniz.


Çıkarım süresi

Bir modelin bir isteği işleme koyması ne kadar sürer?


Bu, kabaca, bir model diğerine tercih edilirse, bir hizmetin görev yükünü karşılaması için ne kadar daha fazla kaynağı korumamız gerektiğini karşılaştırmamıza olanak tanıyacaktır.


Ölçeklenebilirlik

Ürünümüz büyüdüğünde, verilen mimariyi kullanarak büyümeyi yönetmek ne kadar kolay olacak?


Büyüme derken şunu kastedebiliriz:

  • daha fazla kategori, daha yüksek kategori ayrıntı düzeyi
  • daha uzun açıklamalar
  • daha büyük veri kümeleri
  • vesaire

Büyümeyi idare etmek için model seçimini yeniden düşünmek zorunda mı kalacağız yoksa basit bir yeniden eğitim yeterli olacak mı?


Yorumlanabilirlik

Eğitim sırasında ve dağıtım sonrasında modelin hatalarını ayıklamak ne kadar kolay olacak?


Modeli boyutu

Model boyutu şu durumlarda önemlidir:

  • modelimizin müşteri tarafında değerlendirilmesini istiyoruz
  • RAM'e sığmayacak kadar büyük


Daha sonra yukarıdaki her iki öğenin de alakalı olmadığını göreceğiz, ancak yine de kısaca düşünmeye değer.

Veri Kümesi Araştırması ve Temizleme

Neyle çalışıyoruz? Verilere bakalım ve temizlenmesi gerekip gerekmediğini görelim!


Veri kümesi 2 sütun içerir: öğe açıklaması ve kategori, toplam 50,5 bin satır.

 file_name = "ecommerceDataset.csv" data = pd.read_csv(file_name, header=None) data.columns = ["category", "description"] print("Rows, cols:", data.shape) # >>> Rows, cols: (50425, 2)


Her öğeye mevcut 4 kategoriden 1'i atanır: Household , Books , Electronics veya Clothing & Accessories . Kategori başına 1 öğe açıklaması örneğini burada bulabilirsiniz:


  • Ev Dekorasyonu SPK Ev dekorasyonu Kil El Yapımı Duvar Asma Yüzü (Çok Renkli, Y35xG12cm) Bu el yapımı Pişmiş Toprak Hint Yüz Maskesi duvar askısıyla evinizi daha güzel hale getirin, bu el yapımı şeyi daha önce piyasada bulamazsınız. Bunu oturma odanıza/Giriş Lobinize ekleyebilirsiniz.


  • Kitaplar BEGF101/FEG1-İngilizce Temel Kursu-1 (Neeraj Yayınları 2018 baskısı) BEGF101/FEG1-İngilizce Temel Kursu-1


  • Giyim ve Aksesuar Broadstar Kadın Denim Tulum Broadstar tulum giyerek tam erişim kartı kazanın. Denimden yapılmış bu tulumlar sizi rahat ettirecek. Gündelik görünümünüzü tamamlamak için bunları beyaz veya siyah renkli bir üstle eşleştirin.


  • Electronics Caprigo Ağır Hizmet - 2 Feet Premium Projektör Tavana Montaj Stand Braketi (Ayarlanabilir - Beyaz - Ağırlık Kapasitesi 15 Kg)


Kayıp değerler

Veri kümesinde kaldıracağımız tek bir boş değer var.

 print(data.info()) # <class 'pandas.core.frame.DataFrame'> # RangeIndex: 50425 entries, 0 to 50424 # Data columns (total 2 columns): # # Column Non-Null Count Dtype # --- ------ -------------- ----- # 0 category 50425 non-null object # 1 description 50424 non-null object # dtypes: object(2) # memory usage: 788.0+ KB data.dropna(inplace=True)


Kopyalar

Ancak yinelenen çok sayıda açıklama var. Neyse ki tüm kopyalar tek bir kategoriye ait olduğundan bunları güvenli bir şekilde bırakabiliriz.

 repeated_messages = data \ .groupby("description", as_index=False) \ .agg( n_repeats=("category", "count"), n_unique_categories=("category", lambda x: len(np.unique(x))) ) repeated_messages = repeated_messages[repeated_messages["n_repeats"] > 1] print(f"Count of repeated messages (unique): {repeated_messages.shape[0]}") print(f"Total number: {repeated_messages['n_repeats'].sum()} out of {data.shape[0]}") # >>> Count of repeated messages (unique): 13979 # >>> Total number: 36601 out of 50424


Kopyaları çıkardıktan sonra elimizde orijinal veri kümesinin %55'i kalır. Veri seti iyi dengelenmiştir.

 data.drop_duplicates(inplace=True) print(f"New dataset size: {data.shape}") print(data["category"].value_counts()) # New dataset size: (27802, 2) # Household 10564 # Books 6256 # Clothing & Accessories 5674 # Electronics 5308 # Name: category, dtype: int64


Açıklama Dili

Veri kümesi açıklamasına göre,

Veri seti Hint e-ticaret platformundan alınmıştır.


Açıklamaların mutlaka İngilizce yazılmış olması gerekmez. Bazıları Hintçe veya ASCII olmayan semboller kullanılarak diğer dillerde yazılmış veya Latin alfabesine çevrilmiş veya çeşitli dillerin karışımı kullanılmıştır. Books kategorisinden örnekler:


  • यू जी सी – नेट जूनियर रिसर्च फैलोशिप एवं सहायक प्रोफेसर योग्यता …
  • Prarambhik Bhartiy Itihas
  • History of NORTH INDIA/வட இந்திய வரலாறு/ …


Açıklamalarda İngilizce olmayan kelimelerin varlığını değerlendirmek için 2 puan hesaplayalım:


  • ASCII puanı: bir açıklamadaki ASCII olmayan sembollerin yüzdesi
  • Geçerli İngilizce kelimeler puanı: Yalnızca latin harfleri dikkate alırsak, açıklamadaki kelimelerin yüzde kaçı İngilizce'de geçerlidir? Diyelim ki geçerli İngilizce kelimeler, İngilizce derlem üzerinde eğitilmiş Word2Vec-300 bulunan kelimelerdir.


ASCII puanını kullanarak açıklamaların yalnızca %2,3'ünün %1'den fazlasının ASCII olmayan sembollerden oluştuğunu öğreniyoruz.

 def get_ascii_score(description): total_sym_cnt = 0 ascii_sym_cnt = 0 for sym in description: total_sym_cnt += 1 if sym.isascii(): ascii_sym_cnt += 1 return ascii_sym_cnt / total_sym_cnt data["ascii_score"] = data["description"].apply(get_ascii_score) data[data["ascii_score"] < 0.99].shape[0] / data.shape[0] # >>> 0.023


Geçerli İngilizce kelimeler puanı, açıklamaların yalnızca %1,5'inin ASCII kelimeler arasında geçerli İngilizce kelimelerin %70'inden azına sahip olduğunu gösterir.

 w2v_eng = gensim.models.KeyedVectors.load_word2vec_format(w2v_path, binary=True) def get_valid_eng_score(description): description = re.sub("[^az \t]+", " ", description.lower()) total_word_cnt = 0 eng_word_cnt = 0 for word in description.split(): total_word_cnt += 1 if word.lower() in w2v_eng: eng_word_cnt += 1 return eng_word_cnt / total_word_cnt data["eng_score"] = data["description"].apply(get_valid_eng_score) data[data["eng_score"] < 0.7].shape[0] / data.shape[0] # >>> 0.015


Bu nedenle açıklamaların çoğunluğu (%96 civarında) İngilizce veya çoğunlukla İngilizcedir. Diğer tüm açıklamaları kaldırabiliriz, ancak bunun yerine onları olduğu gibi bırakalım ve ardından her modelin bunları nasıl ele aldığını görelim.

Modelleme

Veri setimizi 3 gruba ayıralım:

  • Eğitimin %70'i - modellerin eğitimi için (19 bin mesaj)

  • Test %15 - parametre ve eşik seçimi için (4,1k mesaj)

  • %15 Değerlendirin - son modeli seçtiğiniz için (4,1k mesaj)


 from sklearn.model_selection import train_test_split data_train, data_test = train_test_split(data, test_size=0.3) data_test, data_eval = train_test_split(data_test, test_size=0.5) data_train.shape, data_test.shape, data_eval.shape # >>> ((19461, 3), (4170, 3), (4171, 3))


Temel model: kelime çantası + lojistik regresyon

İyi bir temel elde etmek için ilk başta basit ve önemsiz bir şey yapmak yararlı olacaktır. Temel olarak tren veri kümesini temel alan bir kelime torbası yapısı oluşturalım.


Sözlük boyutunu da 100 kelimeyle sınırlayalım.

 count_vectorizer = CountVectorizer(max_features=100, stop_words="english") x_train_baseline = count_vectorizer.fit_transform(data_train["description"]) y_train_baseline = data_train["category"] x_test_baseline = count_vectorizer.transform(data_test["description"]) y_test_baseline = data_test["category"] x_train_baseline = x_train_baseline.toarray() x_test_baseline = x_test_baseline.toarray()


Model olarak lojistik regresyonu kullanmayı planlıyorum, bu nedenle eğitimden önce sayaç özelliklerini normalleştirmem gerekiyor.

 ss = StandardScaler() x_train_baseline = ss.fit_transform(x_train_baseline) x_test_baseline = ss.transform(x_test_baseline) lr = LogisticRegression() lr.fit(x_train_baseline, y_train_baseline) balanced_accuracy_score(y_test_baseline, lr.predict(x_test_baseline)) # >>> 0.752


Çok sınıflı lojistik regresyon %75,2 dengeli doğruluk gösterdi. Bu harika bir temel!


Genel sınıflandırma kalitesi çok iyi olmasa da model bize yine de bazı bilgiler verebilir. Tahmin edilen etiketlerin sayısına göre normalize edilen karışıklık matrisine bakalım. X ekseni öngörülen kategoriyi, Y ekseni ise gerçek kategoriyi belirtir. Her sütuna baktığımızda, belirli bir kategori tahmin edildiğinde gerçek kategorilerin dağılımını görebiliriz.


Temel çözüm için karışıklık matrisi.


Örneğin Electronics sıklıkla Household ile karıştırılır. Ancak bu basit model bile Clothing & Accessories oldukça hassas bir şekilde yakalayabilir.


Clothing & Accessories kategorisini tahmin ederken öne çıkan özellikler şunlardır:

'Kıyafet ve Aksesuarlar' etiketi için temel çözüm için özellik önemleri


Clothing & Accessories kategorisine yönelik ve aleyhine en çok katkıda bulunan 6 kelime:

 women 1.49 book -2.03 men 0.93 table -1.47 cotton 0.92 author -1.11 wear 0.69 books -1.10 fit 0.40 led -0.90 stainless 0.36 cable -0.85


RNN'ler

Şimdi dizilerle ( yinelenen sinir ağları) çalışmak üzere özel olarak tasarlanmış daha gelişmiş modelleri ele alalım. GRU ve LSTM, basit RNN'lerde meydana gelen patlayan gradyanlarla mücadele eden yaygın gelişmiş katmanlardır.


Açıklamaları tokenize etmek ve bir model oluşturup eğitmek için pytorch kütüphanesini kullanacağız.


Öncelikle metinleri sayılara dönüştürmemiz gerekiyor:

  1. Açıklamaları kelimelere ayırın
  2. Eğitim veri kümesine dayalı olarak derlemdeki her kelimeye bir dizin atayın
  3. Bilinmeyen kelimeler ve dolgular için özel indeksler ayırın
  4. Eğitim ve test veri kümelerindeki her açıklamayı endeks vektörlerine dönüştürün.


Tren veri kümesini basitçe tokenize ederek elde ettiğimiz kelime dağarcığı büyüktür - neredeyse 90 bin kelime. Ne kadar çok kelimemiz varsa, modelin öğrenmesi gereken yerleştirme alanı da o kadar büyük olur. Eğitimi basitleştirmek için, en nadir kelimeleri çıkaralım ve yalnızca açıklamaların en az %3'ünde görünenleri bırakalım. Bu, kelime dağarcığını 340 kelimeye indirecektir.

(tüm CorpusDictionary uygulamasını burada bulabilirsiniz)


 corpus_dict = util.CorpusDictionary(data_train["description"]) corpus_dict.truncate_dictionary(min_frequency=0.03) data_train["vector"] = corpus_dict.transform(data_train["description"]) data_test["vector"] = corpus_dict.transform(data_test["description"]) print(data_train["vector"].head()) # 28453 [1, 1, 1, 1, 12, 1, 2, 1, 6, 1, 1, 1, 1, 1, 6,... # 48884 [1, 1, 13, 34, 3, 1, 1, 38, 12, 21, 2, 1, 37, ... # 36550 [1, 60, 61, 1, 62, 60, 61, 1, 1, 1, 1, 10, 1, ... # 34999 [1, 34, 1, 1, 75, 60, 61, 1, 1, 72, 1, 1, 67, ... # 19183 [1, 83, 1, 1, 87, 1, 1, 1, 12, 21, 42, 1, 2, 1... # Name: vector, dtype: object


Karar vermemiz gereken bir sonraki şey, RNN'ye girdi olarak besleyeceğimiz vektörlerin ortak uzunluğudur. Tam vektörleri kullanmak istemiyoruz çünkü en uzun açıklama 9,4k jeton içeriyor.


Bununla birlikte, tren veri kümesindeki açıklamaların %95'i 352 jetondan uzun değildir; bu, kırpma için iyi bir uzunluktur. Daha kısa açıklamalarla ne olacak?


Ortak uzunluğa kadar dolgu indeksi ile doldurulacaktır.

 print(max(data_train["vector"].apply(len))) # >>> 9388 print(int(np.quantile(data_train["vector"].apply(len), q=0.95))) # >>> 352


Daha sonra, kaybı hesaplamak ve her eğitim adımında geri yayılımı gerçekleştirmek için hedef kategorilerini 0-1 vektörlerine dönüştürmemiz gerekiyor.

 def get_target(label, total_labels=4): target = [0] * total_labels target[label_2_idx.get(label)] = 1 return target data_train["target"] = data_train["category"].apply(get_target) data_test["target"] = data_test["category"].apply(get_target)


Artık modele beslemek için özel bir pytorch Veri Kümesi ve Veri Yükleyici oluşturmaya hazırız. Tam PaddedTextVectorDataset uygulamasını burada bulabilirsiniz.

 ds_train = util.PaddedTextVectorDataset( data_train["description"], data_train["target"], corpus_dict, max_vector_len=352, ) ds_test = util.PaddedTextVectorDataset( data_test["description"], data_test["target"], corpus_dict, max_vector_len=352, ) train_dl = DataLoader(ds_train, batch_size=512, shuffle=True) test_dl = DataLoader(ds_test, batch_size=512, shuffle=False)


Son olarak bir model oluşturalım.


Minimal mimari:

  • gömme katmanı
  • RNN katmanı
  • doğrusal katman
  • etkinleştirme katmanı


Küçük parametre değerleriyle (gömme vektörünün boyutu, RNN'deki gizli katmanın boyutu, RNN katmanlarının sayısı) başlayarak ve hiçbir düzenleme olmadan, aşırı uyumun güçlü işaretlerini gösterene kadar modeli kademeli olarak daha karmaşık hale getirebiliriz ve ardından dengeleyebiliriz. düzenlileştirme (RNN katmanındaki ve son doğrusal katmandan önceki bırakmalar).


 class GRU(nn.Module): def __init__(self, vocab_size, embedding_dim, n_hidden, n_out): super().__init__() self.vocab_size = vocab_size self.embedding_dim = embedding_dim self.n_hidden = n_hidden self.n_out = n_out self.emb = nn.Embedding(self.vocab_size, self.embedding_dim) self.gru = nn.GRU(self.embedding_dim, self.n_hidden) self.dropout = nn.Dropout(0.3) self.out = nn.Linear(self.n_hidden, self.n_out) def forward(self, sequence, lengths): batch_size = sequence.size(1) self.hidden = self._init_hidden(batch_size) embs = self.emb(sequence) embs = pack_padded_sequence(embs, lengths, enforce_sorted=True) gru_out, self.hidden = self.gru(embs, self.hidden) gru_out, lengths = pad_packed_sequence(gru_out) dropout = self.dropout(self.hidden[-1]) output = self.out(dropout) return F.log_softmax(output, dim=-1) def _init_hidden(self, batch_size): return Variable(torch.zeros((1, batch_size, self.n_hidden)))


Kayıp fonksiyonu olarak Adam optimizasyonunu ve cross_entropy kullanacağız.


 vocab_size = len(corpus_dict.word_to_idx) emb_dim = 4 n_hidden = 15 n_out = len(label_2_idx) model = GRU(vocab_size, emb_dim, n_hidden, n_out) opt = optim.Adam(model.parameters(), 1e-2) util.fit( model=model, train_dl=train_dl, test_dl=test_dl, loss_fn=F.cross_entropy, opt=opt, epochs=35 ) # >>> Train loss: 0.3783 # >>> Val loss: 0.4730 

Dönem başına eğitim ve test kayıpları, RNN modeli

Bu model, değerlendirme veri kümesinde %84,3 dengeli doğruluk gösterdi. Vay, ne büyük ilerleme!


Önceden eğitilmiş yerleştirmelerle tanışın

RNN modelini sıfırdan eğitmenin en büyük dezavantajı, kelimelerin anlamını öğrenmek zorunda olmasıdır; bu, yerleştirme katmanının işidir. Önceden eğitilmiş word2vec modelleri, parametre sayısını azaltan ve belirteçlere çok daha fazla anlam katan hazır bir gömme katmanı olarak kullanılabilir. pytorch - glove, dim=300 bulunan word2vec modellerinden birini kullanalım.


Veri Kümesi oluşturmada yalnızca küçük değişiklikler yapmamız gerekiyor; şimdi her açıklama ve model mimarisi için önceden tanımlanmış glove oluşan bir vektör oluşturmak istiyoruz.

 ds_emb_train = util.PaddedTextVectorDataset( data_train["description"], data_train["target"], emb=glove, max_vector_len=max_len, ) ds_emb_test = util.PaddedTextVectorDataset( data_test["description"], data_test["target"], emb=glove, max_vector_len=max_len, ) dl_emb_train = DataLoader(ds_emb_train, batch_size=512, shuffle=True) dl_emb_test = DataLoader(ds_emb_test, batch_size=512, shuffle=False)
 import torchtext.vocab as vocab glove = vocab.GloVe(name='6B', dim=300) class LSTMPretrained(nn.Module): def __init__(self, n_hidden, n_out): super().__init__() self.emb = nn.Embedding.from_pretrained(glove.vectors) self.emb.requires_grad_ = False self.embedding_dim = 300 self.n_hidden = n_hidden self.n_out = n_out self.lstm = nn.LSTM(self.embedding_dim, self.n_hidden, num_layers=1) self.dropout = nn.Dropout(0.5) self.out = nn.Linear(self.n_hidden, self.n_out) def forward(self, sequence, lengths): batch_size = sequence.size(1) self.hidden = self.init_hidden(batch_size) embs = self.emb(sequence) embs = pack_padded_sequence(embs, lengths, enforce_sorted=True) lstm_out, (self.hidden, _) = self.lstm(embs) lstm_out, lengths = pad_packed_sequence(lstm_out) dropout = self.dropout(self.hidden[-1]) output = self.out(dropout) return F.log_softmax(output, dim=-1) def init_hidden(self, batch_size): return Variable(torch.zeros((1, batch_size, self.n_hidden)))


Ve antrenmana hazırız!

 n_hidden = 50 n_out = len(label_2_idx) emb_model = LSTMPretrained(n_hidden, n_out) opt = optim.Adam(emb_model.parameters(), 1e-2) util.fit(model=emb_model, train_dl=dl_emb_train, test_dl=dl_emb_test, loss_fn=F.cross_entropy, opt=opt, epochs=11) 

Dönem başına eğitim ve test kayıpları, RNN modeli + önceden eğitilmiş yerleştirmeler

Artık değerlendirme veri kümesinde %93,7 dengeli doğruluk elde ediyoruz. Vay!


BERT

Dizilerle çalışmak için en son teknolojiye sahip modeller transformatörlerdir. Ancak bir transformatörü sıfırdan eğitmek için çok büyük miktarda veriye ve hesaplama kaynağına ihtiyacımız olacak. Burada deneyebileceğimiz şey, önceden eğitilmiş modellerden birine amacımıza hizmet edecek şekilde ince ayar yapmaktır. Bunu yapmak için önceden eğitilmiş bir BERT modeli indirmemiz ve son tahmini elde etmek için bırakma ve doğrusal katman eklememiz gerekiyor. Ayarlanmış bir modelin 4 dönem boyunca eğitilmesi önerilir. Zamandan tasarruf etmek için fazladan yalnızca 2 dönem çalıştım; bunu yapmam 40 dakikamı aldı.


 from transformers import BertModel class BERTModel(nn.Module): def __init__(self, n_out=12): super(BERTModel, self).__init__() self.l1 = BertModel.from_pretrained('bert-base-uncased') self.l2 = nn.Dropout(0.3) self.l3 = nn.Linear(768, n_out) def forward(self, ids, mask, token_type_ids): output_1 = self.l1(ids, attention_mask = mask, token_type_ids = token_type_ids) output_2 = self.l2(output_1.pooler_output) output = self.l3(output_2) return output


 ds_train_bert = bert.get_dataset( list(data_train["description"]), list(data_train["target"]), max_vector_len=64 ) ds_test_bert = bert.get_dataset( list(data_test["description"]), list(data_test["target"]), max_vector_len=64 ) dl_train_bert = DataLoader(ds_train_bert, sampler=RandomSampler(ds_train_bert), batch_size=batch_size) dl_test_bert = DataLoader(ds_test_bert, sampler=SequentialSampler(ds_test_bert), batch_size=batch_size)


 b_model = bert.BERTModel(n_out=4) b_model.to(torch.device("cpu")) def loss_fn(outputs, targets): return torch.nn.BCEWithLogitsLoss()(outputs, targets) optimizer = optim.AdamW(b_model.parameters(), lr=2e-5, eps=1e-8) epochs = 2 scheduler = get_linear_schedule_with_warmup( optimizer, num_warmup_steps=0, num_training_steps=total_steps ) bert.fit(b_model, dl_train_bert, dl_test_bert, optimizer, scheduler, loss_fn, device, epochs=epochs) torch.save(b_model, "models/bert_fine_tuned")


Eğitim günlüğü:

 2024-02-29 19:38:13.383953 Epoch 1 / 2 Training... 2024-02-29 19:40:39.303002 step 40 / 305 done 2024-02-29 19:43:04.482043 step 80 / 305 done 2024-02-29 19:45:27.767488 step 120 / 305 done 2024-02-29 19:47:53.156420 step 160 / 305 done 2024-02-29 19:50:20.117272 step 200 / 305 done 2024-02-29 19:52:47.988203 step 240 / 305 done 2024-02-29 19:55:16.812437 step 280 / 305 done 2024-02-29 19:56:46.990367 Average training loss: 0.18 2024-02-29 19:56:46.990932 Validating... 2024-02-29 19:57:51.182859 Average validation loss: 0.10 2024-02-29 19:57:51.182948 Epoch 2 / 2 Training... 2024-02-29 20:00:25.110818 step 40 / 305 done 2024-02-29 20:02:56.240693 step 80 / 305 done 2024-02-29 20:05:25.647311 step 120 / 305 done 2024-02-29 20:07:53.668489 step 160 / 305 done 2024-02-29 20:10:33.936778 step 200 / 305 done 2024-02-29 20:13:03.217450 step 240 / 305 done 2024-02-29 20:15:28.384958 step 280 / 305 done 2024-02-29 20:16:57.004078 Average training loss: 0.08 2024-02-29 20:16:57.004657 Validating... 2024-02-29 20:18:01.546235 Average validation loss: 0.09


Son olarak, ince ayarlı BERT modeli, değerlendirme veri kümesinde %95,1 oranında dengeli doğruluk gösterir.


Kazananımızı seçiyoruz

Son olarak iyi bilgilendirilmiş bir seçim yapmak için dikkate alınması gereken hususların bir listesini zaten oluşturduk.

Ölçülebilir parametreleri gösteren grafikler:

Modellerin performans metrikleri


İnce ayarlı BERT kalite açısından lider olmasına rağmen, önceden eğitilmiş yerleştirme katmanı LSTM+EMB sahip RNN, otomatik kategori atamalarının yalnızca %3'ünün gerisinde kalarak hemen hemen ikinci sırada yer alıyor.


Öte yandan ince ayarlı BERT'in çıkarım süresi LSTM+EMB 14 kat daha uzundur. Bu, arka uç bakım maliyetlerini artıracak ve bu da muhtemelen ince ayarlı BERT LSTM+EMB getirdiği avantajlardan daha ağır basacaktır.


Birlikte çalışabilirliğe gelince, temel lojistik regresyon modelimiz açık ara en yorumlanabilir modeldir ve bu bakımdan herhangi bir sinir ağı bu modele karşı kaybeder. Aynı zamanda, taban çizgisi muhtemelen en az ölçeklenebilir olanıdır; kategorilerin eklenmesi, taban çizgisinin zaten düşük olan kalitesini azaltacaktır.


BERT yüksek doğruluğuyla süperstar gibi görünse de, önceden eğitilmiş bir yerleştirme katmanına sahip RNN'yi tercih ediyoruz. Neden? Oldukça doğru, çok yavaş değil ve işler büyüdüğünde üstesinden gelinemeyecek kadar karmaşık olmuyor.


Umarım bu vaka çalışmasını beğenmişsinizdir. Hangi modeli seçerdiniz ve neden?