Transformers documentation
Eski model katkısı
Eski model katkısı
Önce daha modüler bir yaklaşım benimseyerek yeni modeller eklemeyi deneyin. Bu, bir modeli Transformers'a katkıda bulunmayı önemli ölçüde kolaylaştırır!
Transformers'taki modellerin çoğu geliştiriciler ve araştırmacılar tarafından katkı sağlanmıştır. Açık kaynak öncelikli bir proje olarak, topluluğun bağımsız ve aktif bir şekilde daha fazla model eklemesini desteklemeye adanmış durumdayız.
Bir modeli Transformers'a eklediğinizde şunları öğrenirsiniz:
- açık kaynak en iyi uygulamalar hakkında daha fazla bilgi
- bir modelin mimarisi hakkında
- Transformers' tasarım ilkeleri hakkında
- büyük modellerin nasıl verimli bir şekilde test edileceği
- temiz ve okunabilir kod oluşturmak için Black ve Ruff gibi Python araçlarını nasıl kullanılır
Zorlu ama ödüllendirici bir süreçtir.
Bu kılavuz, Transformers kütüphanesine örnek bir BrandNewLlama PyTorch modeli eklemenin adımlarını anlatacak. Başlamadan önce, kütüphaneyi tanımanızı öneririz.
Transformers genel bakış
Transformers, kendine özgü bir felsefeye ve tasarım tercihlerine sahip, görüşleri net bir kütüphanedir. Bu tercihler, Transformers'ı sürdürülebilir bir şekilde ölçeklendirmemize ve bakımını yapmamıza yardımcı olur.
Tasarım ilkelerimiz hakkında daha fazla bilgi için Felsefe belgesine göz atın.
Bu tasarım tercihlerinden bazıları şunlardır:
- composition > aşırı soyutlama
- okunabilirliği ve erişilebilirliği büyük ölçüde iyileştiriyorsa, kopyalanmış kod her zaman kötü değildir
- model dosyaları kendi içinde tamdır ve gerekli tüm model kodu
modeling_mymodel.pydosyasında bulunur
Bu tasarım tercihleri, modelle etkileşim kuracak herkes için önemlidir. Okuması, anlaması ve değiştirmesi daha kolaydır.
Bu bölüm, model ve yapılandırma sınıflarının nasıl etkileşime girdiğini ve Transformers kod stilini açıklar.
Model ve yapılandırma
Tüm Transformers modelleri, temel PreTrainedModel ve PreTrainedConfig sınıflarından devralır. Yapılandırma, modellerin planıdır.
Herhangi bir model için kodun okunabilirliğini korumak adına soyutlama seviyesi asla ikiyi geçmez. Buradaki örnek model olan BrandNewLlama, BrandNewLlamaPreTrainedModel ve PreTrainedModel sınıflarından türetilir. Yeni bir modelin yalnızca PreTrainedModel sınıfına bağımlı olması, from_pretrained() ve save_pretrained() yöntemlerini kullanabilmesi açısından önemlidir.
forward yöntemi gibi diğer önemli işlevler modeling.py dosyasında tanımlanır.
Belirli model başları (örneğin, dizi sınıflandırma veya dil modelleme), soyutlamayı düşük tutmak için forward geçişinde temel modeli miras almak yerine çağırmalıdır.
Yeni modeller, PreTrainedModel'in bir özniteliği olarak saklanan ve örneğin BrandNewLlamaConfig gibi bir yapılandırma gerektirir.
model = BrandNewLlamaModel.from_pretrained("username/brand_new_llama")
model.configPreTrainedConfig, from_pretrained() ve save_pretrained() yöntemlerini sağlar.
PreTrainedModel.save_pretrained() kullandığınızda, model ve yapılandırmanın birlikte kaydedilmesi için PreTrainedConfig.save_pretrained() otomatik olarak çağrılır.
Bir model model.safetensors dosyasına, yapılandırma ise config.json dosyasına kaydedilir.
Kod stili
Transformers, daha soyut bir kod stiline tercih olarak temiz ve okunabilir bir kodu benimser. Kod stili tercihlerinden bazıları şunlardır:
Kod, İngilizce bilmeyen kullanıcılar tarafından erişilebilir olmalıdır. Açıklayıcı değişken adları seçin ve kısaltmalardan kaçının. Örneğin, “act” yerine “activation” tercih edilir. Bir for döngüsündeki bir indeks olmadıkça tek harfli değişken adları kesinlikle önerilmez.
Daha kısa kod yerine açık kod tercih edilir - hatta daha uzun olsa bile.
nn.Sequential sınıfını alt sınıflandırmaktan kaçının. Bunun yerine, kodun yazdırma ifadeleri veya duraklama noktalarıyla hızlıca hata ayıklanabilmesi için nn.Module sınıfını alt sınıflandırın.
Fonksiyon imzaları tip etiketli olmalıdır. Aksi takdirde, daha anlaşılır olmaları için iyi değişken adları kullanın.
Yeni model ekleme sorunu
Belirli bir model eklemek için bir Yeni model ekleme sorunu açın.
GitHub'da New model etiketine göre filtreleyerek mevcut model isteklerini görüntüleyebilir ve ekleyebilirsiniz.
Şu an BrandNewLlama ile tanışmak için iyi bir zaman. Bir modelin teknik tasarımını ve uygulamasını anlamak için araştırma makalesini okumak faydalıdır. Teorik detaylarla çok fazla uğraşmak zorunda değilsiniz. Bunun yerine, pratik detaylara odaklanın. Okumanızı yönlendirmek için aşağıdaki soruları kullanın.
- BrandNewLlama hangi türde bir modeldir? Bir encoder, decoder veya encoder-decoder modeli midir?
- BrandNewLlama hangi görevler için kullanılabilir?
- BrandNewLlama'ı diğer modellerden farklı kılan nedir?
- Transformers'ta BrandNewLlama'ya en çok benzeyen modeller hangileridir?
- BrandNewLlama hangi tokenizer'ı kullanır?
Modeliniz hakkında daha fazla bilgi edinmenin yanı sıra, aşağıdaki ipuçları bir model daha hızlı eklemenize yardımcı olacaktır.
Her katkıda bulunanın, modelleri Transformers'a ekleme konusunda kendine özgü bir stili ve iş akışı vardır. Örnek olarak, Gemma'nın nasıl eklendiğine göz atın.
- Tekerleği yeniden icat etmeyin! Kopyalayabileceğinizi ve yeniden kullanabileceğinizi görmek için mevcut modelleri ve tokenizörleri keşfetmek için zaman ayırın. Grep ve ripgrep bunun için harika araçlardır.
- Bu, bilimsel olmaktan çok mühendislik odaklı bir zorluktur. Modelin teorik yönleri yerine daha pratik konulara (örneğin verimli bir hata ayıklama ortamı kurma) odaklanın.
- Yardım istemekten çekinmeyin! Size destek olmak için buradayız. 🤗
Geliştirme ortamı
Transformers deposundaki Fork düğmesine tıklayarak üzerinde çalışmak için kendi kopyanızı oluşturun. Depoyu yerel diskinize klonlayın ve temel depoyu uzak (remote) olarak ekleyin.
git clone https://github.com/[your Github handle]/transformers.git
cd transformers
git remote add upstream https://github.com/huggingface/transformers.gitSanal bir ortam oluşturun ve kütüphanenin “dev” veya geliştirme bağımlılıklarıyla düzenlenebilir kurulumunu gerçekleştirin.
python -m venv .env
source .env/bin/activate
pip install -e ".[dev]"Transformers'ın isteğe bağlı bağımlılıklarının sayısı arttıkça bu komut başarısız olabilir. Bu durumda “quality” bağımlılıklarını yükleyin. Ayrıca derin öğrenme çerçevenizin yüklü olduğundan emin olun.
pip install -e ".[quality]"Üst dizine dönün ve orijinal BrandNewLlama deposunu klonlayıp yükleyin.
git clone https://github.com/org_that_created_brand_new_llama_org/brand_new_llama.git
cd brand_new_bert
pip install -e .BrandNewLlama'ı taşımaya başlamak için Transformers'ın klonunuza dönün.
cd transformersOrijinal modeli çalıştırmak için iki olası hata ayıklama ortamı vardır: bir defter (Google Colab veya Jupyter) veya yerel bir Python betiği.
Orijinal modeli çalıştırmak için bir GPU ortamı kurmanızı önermiyoruz çünkü bu maliyetli olabilir. Bunun yerine, önce bir CPU ortamında çalışarak modelin Transformers içinde çalıştığını doğrulayın. Çalıştığını doğruladıktan sonra, GPU üzerinde de doğrulayabilirsiniz.
Notebook'lar, kodu hücre hücre çalıştırmak için idealdir ve bu, mantıksal bileşenleri birbirinden ayırmaya yardımcı olabilir. Ara sonuçların saklanabilmesi sayesinde hata ayıklama döngülerini de hızlandırır. Diğer katkıcılarla çalışırken notebook'ları paylaşabilirsiniz.
Dezavantajı ise, bunlara alışık değilseniz, alışmanız biraz zaman alabilir.
Model mimarisi mevcut bir modelle aynıysa, mevcut modelin mimarisini yeniden kullanabileceğiniz için kontrol noktasını dönüştürme adımına atlayın.
Aşağıdaki komutu çalıştırarak yeni model hakkında bazı temel bilgilerle anketi başlatın ve tamamlayın. Bu komut, uyarlaması gereken bazı model kodunu otomatik olarak oluşturarak süreci hızlandırır.
transformers add-new-model-like
Bir çekme isteği oluşturun
Kodu uyarlamaya başlamadan önce, ilerlemenizi takip etmek ve Transformers ekibinden geri bildirim almak için bir çekme isteği (pull request) oluşturun. Çekme isteğinizin başlığını [WIP] Add BrandNewLlama olarak belirleyin, böylece bunun bir devam eden iş (work in progress) olduğu açıkça anlaşılsın.
Ana dalınızdan açıklayıcı bir adla bir dal oluşturun.
git checkout -b add_brand_new_bert
Kodu commit edin, ardından main dalını fetch edin ve üzerine rebase yapın.
git add . git commit git fetch upstream git rebase upstream/main
Değişikliklerinizi dalınıza gönderin ve GitHub'ta bir çekme isteği açmak için Compare & pull request düğmesine tıklayın. Çekme isteğini draft olarak açarak bunun üzerinde çalışılan bir iş olduğunu belirtin.
git push -u origin a-descriptive-name-for-my-changes
Sorular, geri bildirimler, yorumlar ve incelemeler için ilgili Hugging Face ekip üyelerini, pull request'e GitHub kullanıcı adlarını ekleyerek dahil edin. Ekip üyelerini, Files changed sekmesine tıklayarak ve ardından satır numarasının solundaki + simgesine tıklayıp yorum ekleyerek, kodun istediğiniz belirli kısımlarına yönlendirin. Bir soru veya sorun çözüldüğünde, sorunun çözüldüğünü belirtmek için Resolve düğmesine tıklayın. Bu, konuşmanın düzenli ve temiz kalmasını sağlar.
Düzenli olarak işlerinizi commit ve push etmeyi ve işlerinizi güncel main dalıyla güncellemeyi unutmayın.
git fetch upstream git merge upstream/main
Orijinal checkpoint
Nasıl çalıştığını anlamak için önce orijinal model uygulaması üzerinde biraz zaman harcamaya özen gösterin.
Orijinal model deposu dokümantasyondan yoksunsa veya kod tabanı karmaşıksa bu zor olabilir. Ancak bunu, modeli Transformers'ta uygulamanız için bir motivasyon olarak kullanmalısınız. Katkınız, modeli herkes için daha erişilebilir ve kullanıcı dostu hale getirir!
Bunu yapmak için orijinal depoyu inceleyin.
- Önceden eğitilmiş ağırlıkları bulun.
- Önceden eğitilmiş ağırlıkları modele nasıl yükleyeceğinizi belirleyin.
- Modelden bağımsız olarak tokenizer'ı nasıl çalıştıracağınızı belirleyin.
- Hangi sınıfların ve fonksiyonların gerekli olduğunu anlamak için tek bir ileri geçişi izleyin. Muhtemelen uygulamanız gereken tek sınıflar ve fonksiyonlar bunlardır.
- Modelin tüm önemli bileşenlerini (model sınıfı, model alt sınıfları, self-attention katmanı vb.) belirleyin.
- Modeli orijinal depoda nasıl hata ayıklamanız gerektiğini belirleyin. Yazdırma ifadeleri ekleyin, ipdb gibi etkileşimli hata ayıklayıcılar veya PyCharm gibi verimli bir entegre geliştirme ortamı (IDE) kullanın.
Son nokta özellikle önemlidir çünkü Transformers'ta yeniden uygulamadan önce orijinal modelin içinde neler olduğunu kapsamlı bir şekilde anlamanız gerekir. Herhangi bir sorunla karşılaşırsanız, orijinal depoda sorun ve çekme isteği (pull request) açmaktan çekinmeyin.
İyi bir ilk adım, küçük bir önceden eğitilmiş kontrol noktası yükleyip örnek bir girdi tamsayı vektörüyle tek bir ileri geçişi yeniden üretmeye çalışmaktır. Örneğin, sözde kodda bu aşağıdaki gibi görünebilir.
model = BrandNewLlamaModel.load_pretrained_checkpoint("/path/to/checkpoint/")
input_ids = [0, 4, 5, 2, 3, 7, 9] # vector of input ids
original_output = model.generate(input_ids)Hata Ayıklama
Sorunlarla karşılaşırsanız, orijinal modelin kod tabanına bağlı olarak aşağıdaki hata ayıklama stratejilerinden birini seçmeniz gerekir.
Bu strateji, kodun kolayca eager modda çalıştırılabildiği durumlarda olduğu gibi, orijinal modelin daha küçük alt bileşenlere ayrılmasına dayanır. Daha zorlu olsa da bu yaklaşımın bazı avantajları vardır.
- Daha sonra orijinal modeli kendi uygulamanızla karşılaştırmak daha kolaydır. Transformers'ın uygulamasındaki her bir bileşenin, bireysel olarak kendi uygulamanızdaki karşılığıyla eşleştiğini otomatik olarak doğrulayabilirsiniz. Bu, print ifadelerine dayalı görsel bir karşılaştırmaya güvenmekten daha iyidir.
- Tüm modeli taşımak yerine bireysel bileşenleri taşımak daha kolaydır.
- Bir modelin nasıl çalıştığını anlamak, onu daha küçük parçalara ayırarak daha kolay hale gelir.
- Bileşen bazlı testler sayesinde kodunuzu değiştirdiğinizde, sonraki aşamalarda regresyonları önlemek daha kolaydır.
Bir modeli daha küçük bileşenlere ayırmanın iyi bir örneği için ELECTRA entegrasyon kontrollerine bakın.
Bu strateji, orijinal kod tabanı çok karmaşıksa, yalnızca ara bileşenlerin derlenmiş modda çalıştırılmasına izin veriyorsa veya modeli daha küçük alt bileşenlere ayırmak çok zaman alıyorsa (hatta imkânsızsa) uygulanabilir.
Örneğin, T5'in MeshTensorFlow uygulaması çok karmaşıktır ve modelin alt bileşenlerine ayrılmasını sağlayan basit bir yöntem sunmaz. Bu durumda, doğrulamayı print ifadelerine dayanarak yapmanız gerekir.
Hangi stratejiyi seçerseniz seçin, önce başlangıç katmanlarını, en son ise son katmanları hata ayıklamanız önerilir. Aşağıdaki katmanların çıktılarını bu sırayla, ister yazdırma ifadeleriyle ister alt bileşen işlevleriyle alın.
- modele geçirilen girdi kimlikleri
- kelime gömlemleri
- ilk Transformer katmanının girdisi
- ilk Transformer katmanının çıktısı
- aşağıdaki n-1 Transformer katmanının çıktısı
- tüm modelin çıktısı
Girdi kimlikleri yalnızca input_ids = [0, 4, 4, 3, 2, 4, 1, 7, 19] gibi bir tamsayı dizisi olmalıdır.
Katman çıktıları genellikle çok boyutlu float dizilerinden oluşur.
[[
[-0.1465, -0.6501, 0.1993, ..., 0.1451, 0.3430, 0.6024],
[-0.4417, -0.5920, 0.3450, ..., -0.3062, 0.6182, 0.7132],
[-0.5009, -0.7122, 0.4548, ..., -0.3662, 0.6091, 0.7648],
...,
[-0.5613, -0.6332, 0.4324, ..., -0.3792, 0.7372, 0.9288],
[-0.5416, -0.6345, 0.4180, ..., -0.3564, 0.6992, 0.9191],
[-0.5334, -0.6403, 0.4271, ..., -0.3339, 0.6533, 0.8694]]],Her Transformers model çıktısının hassasiyeti veya hata toleransı 1e-3 olmalıdır. Bu, farklı bir kütüphane çerçevesi kullanılması nedeniyle ortaya çıkabilecek çıktı farklarını karşılar. Neredeyse aynı olduklarından emin olmak için orijinal modelin ara çıktılarını Transformers uygulamasıyla karşılaştırın. Bu adım için verimli bir hata ayıklama ortamına sahip olmak hayati önem taşır.
Verimli bir hata ayıklama ortamı için bazı ipuçları:
Ara sonuçları hata ayıklamak için, orijinal model deposunun kullandığı makine öğrenimi çerçevesine bağlıdır. PyTorch için, ara değerleri almak üzere orijinal modeli daha küçük alt bileşenlere ayıran bir betik yazmalısınız.
İleri geçişin 10 saniyeden fazla sürdüğü büyük bir checkpoint yerine daha küçük bir önceden eğitilmiş checkpoint ile hata ayıklama yapmak daha hızlıdır. Yalnızca büyük checkpoint'ler mevcut ise, Transformers uygulamasıyla karşılaştırmak için rastgele başlatılmış ağırlıklara sahip sahte bir model oluşturun ve bu ağırlıkları kaydedin.
Modelin ileri geçişini çağıran en kolay yolu bulun. İdeal olarak bu fonksiyon (
predict,evaluate,forwardveya__call__olarak adlandırılabilir) ileri geçişi yalnızca bir kez çağırmalıdır. İleri geçişi birden fazla kez çağıran bir fonksiyonu hata ayıklamak daha zordur.Tokenizasyonu ileri geçişten ayırın. İleri geçişte bir dize girdisinin girdi kimliklerine dönüştürüldüğü yeri bulun ve buradan başlayın. Girdi kimliklerini bir girdi dizesi yerine doğrudan girmek için küçük bir betik oluşturmanız veya orijinal kodu değiştirmeniz gerekebilir.
Modelin eğitim modunda olmadığından emin olun. Modeldeki birden fazla dropout katmanı nedeniyle rastgele çıktılar üretebilir. Hata ayıklama ortamınızdaki ileri geçiş, dropout katmanlarının kullanılmaması için deterministik olmalıdır.
Orijinal kontrol noktasını çalıştırabildiğinizde, modeli Transformers için uyarlamaya başlayabilirsiniz.
Model kodunu uyarla
transformers add-new-model-like komutu bir model ve yapılandırma dosyası oluşturmuş olmalıdır.
src/transformers/models/brand_new_llama/modeling_brand_new_llama.pysrc/transformers/models/brand_new_llama/configuration_brand_new_llama.py
modeling.py dosyasındaki otomatik olarak oluşturulan kod, yalnızca bir çözücü modeli olduğunu belirtirseniz Llama ile aynı mimariye sahip olur; bir kodlayıcı-çözücü modeli olduğunu belirtirseniz BART ile aynı mimariye sahip olur. Oluşturulan kod yalnızca bir başlangıç noktasıdır. Yeni modelle ilgili araştırmanıza dayanarak, oluşturulan kodu uyarlayarak bu spesifik değişiklikleri uygulamanız gerekecektir. Bu, öz-dikkat katmanında, normalizasyon katmanının sıralamasında ve benzeri yerlerde değişiklikler gerektirebilir.
Model başlatma
Bu aşamada kodunuzun temiz veya hatta tamamen doğru olması gerekmez. Önce hızlıca bir taslak oluşturup ardından onu iteratif olarak geliştirmek daha verimlidir. En önemli nokta, modelinizin Transformers üzerinden örneklenmesidir. Aşağıdaki komut, rastgele ağırlıklarla yapılandırmadan bir model oluşturarak __init__ metodunun çalıştığını doğrular.
from transformers import BrandNewLlama, BrandNewLlamaConfig
model = BrandNewLlama(BrandNewLlamaConfig())Rastgele başlatma, BrandNewLlamaPreTrainedModel sınıfının _init_weights yönteminde gerçekleşir. Tüm yaprak modüller, yapılandırmanın değişkenlerine bağlı olarak başlatılır. Değerleri ayarlamak için doğrudan bir ağırlık veya onun .data özniteliği üzerinde yerinde işlemler çağırmak yerine, transformers.initialization modülündeki yardımcıları kullanın.
from transformers import initialization as init
def _init_weights(self, module):
"""Initialize the weights"""
if isinstance(module, nn.Linear):
init.normal_(module.weight, mean=0.0, std=self.config.initializer_range)
if module.bias is not None:
init.zeros_(module.bias)
elif isinstance(module, nn.Embedding):
init.normal_(module.weight, mean=0.0, std=self.config.initializer_range)
if module.padding_idx is not None:
init.zeros_(module.weight[module.padding_idx])
elif isinstance(module, nn.LayerNorm):
init.zeros_(module.bias)
init.ones_(module.weight)Ağırlıkları her zaman transformers.initialization yardımcıları üzerinden başlatın. module.bias.zero_() veya module.weight.data ile etkileşen yerinde (in-place) işlemler, hangi parametrelerin zaten yüklendiğini işaretleyen _is_hf_initialized mekanizmasını atlar. from_pretrained(), checkpoint'i yükledikten sonra _init_weights çalıştırır; bu nedenle yerinde işlemler, yüklenen ağırlıkları sessizce rastgele değerlerle üzerine yazar. Bu kural, Transformers modelleri için TRF012 kuralı ile zorunlu kılınmıştır.
from_pretrained() sırasında modeller genellikle
metacihazında başlatılır. Yükleyici kalıcı olmayan tamponları boş tensörler olarak yeniden oluşturur, bu nedenle__init__içinde atanan değerler korunmaz. Bu tamponların yükleme sonrasında doğru değerlere sahip olması için bunları_init_weightsiçinde başlatın. Bir örnek için, BERT'in konum kimliklerini ve jeton türü kimliklerini nasıl başlattığına bakın.
Başlatma şeması, modeli uyarlamak için farklı görünebilir. Kendine ait bir reset_parameters yöntemi olan bir alt modül bunu doğrudan çağırabilir. Örneğin, Wav2Vec2ForPreTraining, son iki doğrusal katmanında nn.Linear bileşenlerini başlatır. Bu çağrı güvenlidir çünkü from_pretrained(), _init_weights çalışırken alttaki torch.nn.init işlevlerini _is_hf_initialized bayrağına saygı gösterecek şekilde yamalar, böylece yüklenen ağırlıklar üzerine yazılmaz.
def _init_weights(self, module):
"""Initialize the weights"""
if isinstance(module, Wav2Vec2ForPreTraining):
module.project_hid.reset_parameters()
module.project_q.reset_parameters()Kontrol noktalarını Transformers'a dönüştürme
Orijinal checkpoint, Transformers ile uyumlu bir checkpoint'e dönüştürülmelidir.
Modeliniz için kopyalanacak, uyarlanacak ve yeniden kullanılacak mevcut bir dönüştürme betiği aramayı deneyin!
- TensorFlow'dan PyTorch'a bir model taşıyorsanız, iyi bir başlangıç noktası BERT dönüştürme betiği olabilir.
- PyTorch'tan PyTorch'a bir model taşıyorsanız, iyi bir başlangıç noktası BART dönüştürme betiği olabilir.
Gerekli tüm ağırlıkların başlatıldığından ve modelin doğru şekilde dönüştürüldüğünden emin olmak için, başlatma için kullanılmayan tüm kontrol noktası ağırlıklarını yazdırın.
Dönüştürme sırasında yanlış şekil ifadeleri veya ad atamalarıyla karşılaşabilirsiniz. Bunun en olası nedeni, BrandNewLlamaConfig içindeki hatalı parametreler, yanlış mimari, uygulamanızdaki init yönteminde bir hata veya kontrol noktası ağırlıklarından birinin transpoze edilmesi gerekliliğidir.
Tüm checkpoint ağırlıkları doğru şekilde yüklenene kadar Model kodunu uyarla bölümünde tekrarlamaya devam edin. Modelinizde bir checkpoint yükleyebildiğinizde, onu bir klasöre kaydedin. Bu klasör bir model.safetensors dosyası ve bir config.json dosyası içermelidir.
model.save_pretrained("/path/to/converted/checkpoint/folder")Dönüşüme yardımcı olmak için, sonraki bölüm PyTorch modellerinin katman ağırlıklarını ve adlarını nasıl sakladığını ve tanımladığını kısaca açıklar.
PyTorch katman ağırlıkları ve adları
Kat adlarının nasıl tanımlandığını ve ağırlıkların nasıl başlatıldığını anlamak için temel bir PyTorch modeli oluşturmak faydalıdır.
from torch import nn
class SimpleModel(nn.Module):
def __init__(self):
super().__init__()
self.dense = nn.Linear(10, 10)
self.intermediate = nn.Linear(10, 10)
self.layer_norm = nn.LayerNorm(10)PyTorch katman adları, katmanın sınıf özniteliği adıyla tanımlanır (dense, intermediate, layer_norm). Tüm katmanları rastgele ağırlıklarla doldurmak için SimpleModel sınıfından bir örnek oluşturun.
model = SimpleModel()
print(model)
SimpleModel(
(dense): Linear(in_features=10, out_features=10, bias=True)
(intermediate): Linear(in_features=10, out_features=10, bias=True)
(layer_norm): LayerNorm((10,), eps=1e-05, elementwise_affine=True)
)Belirli bir katmanın ağırlık değerleri rastgele başlatılır.
print(model.dense.weight.data)
tensor([[-0.0818, 0.2207, -0.0749, -0.0030, 0.0045, -0.1569, -0.1598, 0.0212,
-0.2077, 0.2157],
[ 0.1044, 0.0201, 0.0990, 0.2482, 0.3116, 0.2509, 0.2866, -0.2190,
0.2166, -0.0212],
[-0.2000, 0.1107, -0.1999, -0.3119, 0.1559, 0.0993, 0.1776, -0.1950,
-0.1023, -0.0447],
[-0.0888, -0.1092, 0.2281, 0.0336, 0.1817, -0.0115, 0.2096, 0.1415,
-0.1876, -0.2467],
[ 0.2208, -0.2352, -0.1426, -0.2636, -0.2889, -0.2061, -0.2849, -0.0465,
0.2577, 0.0402],
[ 0.1502, 0.2465, 0.2566, 0.0693, 0.2352, -0.0530, 0.1859, -0.0604,
0.2132, 0.1680],
[ 0.1733, -0.2407, -0.1721, 0.1484, 0.0358, -0.0633, -0.0721, -0.0090,
0.2707, -0.2509],
[-0.1173, 0.1561, 0.2945, 0.0595, -0.1996, 0.2988, -0.0802, 0.0407,
0.1829, -0.1568],
[-0.1164, -0.2228, -0.0403, 0.0428, 0.1339, 0.0047, 0.1967, 0.2923,
0.0333, -0.0536],
[-0.1492, -0.1616, 0.1057, 0.1950, -0.2807, -0.2710, -0.1586, 0.0739,
0.2220, 0.2358]]).Dönüştürme betiğinde, rastgele ağırlıklar, orijinal kontrol noktasındaki ilgili katmandaki tam ağırlıklarla değiştirilmelidir.
# retrieve matching layer weights with recursive algorithm
layer_name = "dense"
pretrained_weight = array_of_dense_layer
model_pointer = getattr(model, "dense")
model_pointer.weight.data = torch.from_numpy(pretrained_weight)Rastgele başlatılmış ağırlıkların ve bunlara karşılık gelen önceden eğitilmiş kontrol noktası ağırlıklarının shape ve name değerlerinin aynı olduğunu doğrulayın. Şekil için assert ifadeleri ekleyin ve kontrol noktası ağırlık adlarını yazdırın.
assert (
model_pointer.weight.shape == pretrained_weight.shape
), f"Pointer shape of random weight {model_pointer.shape} and array shape of checkpoint weight {pretrained_weight.shape} mismatched"
logger.info(f"Initialize PyTorch weight {layer_name} from {pretrained_weight.name}")Şekil veya ad eşleşmediğinde, rastgele başlatılmış bir katmana yanlış kontrol noktası ağırlığını atamış olabilirsiniz. Yanlış şekil, BrandNewLlama parametrelerinin orijinal modelin parametreleriyle tam olarak eşleşmemesinden kaynaklanabilir. Ancak PyTorch katman uygulamasının ağırlıkların önce transpoze edilmesini gerektirmesi de mümkündür.
İleri geçişi uygulayın
Model doğru şekilde yükleniyorsa, sıradaki adım ileri geçişin (forward pass) uygulanmasıdır. Bu işlem bazı girdileri alır ve model çıktısını döndürür.
model = BrandNewLlamaModel.from_pretrained("/path/to/converted/checkpoint/folder")
input_ids = [0, 4, 4, 3, 2, 4, 1, 7, 19]
output = model.generate(input_ids).last_hidden_statesİleri geçişinizin orijinal modelin çıktısıyla birebir aynı olmaması veya bir hata döndürmesi durumunda moralinizi bozmayın. İleri geçişin herhangi bir hata fırlatmadığından emin olun. Bu genellikle boyutların yanlış olması veya yanlış veri türünün kullanılması (torch.long yerine torch.float32) nedeniyle olur.
Çıktınızın hassasiyeti 1e-3 olmalıdır. Çıktı şekillerinin ve çıktı değerlerinin birebir aynı olduğundan emin olun. Çıktıların birebir aynı olmamasının yaygın nedenleri şunlardır:
- Bazı katmanlar eklenmedi (aktivasyon katmanı veya artımsal bağlantı).
- Kelime gömme matrisi bağlı değildir.
- Orijinal uygulama bir ofset içerdiği için yanlış konumsal gömlemeler kullanılmaktadır.
- Dropout, ileri geçiş sırasında uygulanır. Bu hatayı,
model.training'inFalseolduğundan emin olarak veself.training'yi torch.nn.functional.dropout'e geçirerek düzeltin.
Orijinal modelin ve sizin uygulamanızın ileri geçişini karşılaştırarak herhangi bir fark olup olmadığını kontrol edin. İdeal olarak, ileri geçişin her iki uygulamasının ara çıktıları hata ayıklama ve yazdırma yoluyla incelenmeli ve orijinal uygulamanın sizinkinden nerede farklılaştığı tespit edilmelidir.
- Her iki uygulamadaki sabit kodlanmış
input_ids'in aynı olduğundan emin olun. input_ids'nin ilk dönüşümünün (genellikle kelme gömme değerlerinin) çıktılarının aynı olduğunu doğrulayın ve son katmana kadar ilerleyin.
İki uygulama arasındaki herhangi bir fark, uygulamanızdaki hataya işaret etmelidir.
En iyi stratejilerden biri, her iki uygulamada da aynı konumlara birçok yazdırma ifadesi eklemek ve ardından ara çıktılar için aynı değerleri ürettiklerinde bunları sırayla kaldırmaktır.
Her iki uygulama da aynı çıktıyı ürettiğinde, çıktıların 1e-3 hassasiyetinde olduğunu doğrulayın.
torch.allclose(original_output, output, atol=1e-3)Bu, sürecin genellikle en zorlu kısmıdır. Bu noktaya kadar geldiyseniz tebrikler!
Ve bu adımda takılıp kaldıysanız veya zorlanıyorsanız, pull request'inizde yardım istemekten çekinmeyin.
Model testleri ekle
Model çalışırken, Transformers ile uyumlu olduğundan emin olmak için testler eklemeniz hâlâ gerekir. Testler önemlidir çünkü kullanıcıların belirli testlere bakarak işinizi anlamasına yardımcı olurlar ve gelecekte herhangi bir değişiklik yapıldığında modelinizin bozulmasını önlerler.
Cookiecutter, modeliniz için bir test dosyası eklemiş olmalıdır. Tüm ortak testlerin geçtiğinden emin olmak için aşağıdaki test dosyasını çalıştırın.
pytest tests/models/brand_new_llama/test_modeling_brand_new_llama.py
Entegrasyon testleri, daha önce Transformers'ta yeni modeli uygulamak için kullandığınız hata ayıklama betikleriyle aynı amaca hizmet ettikleri için önce eklenmelidir. Bu model testlerinin bir şablonu olan BrandNewLlamaModelIntegrationTests, Cookiecutter tarafından eklendi ve doldurulmalıdır. Geçerli olduğundan emin olmak için aşağıdaki komutu çalıştırın.
RUN_SLOW=1 pytest -sv tests/models/brand_new_llama/test_modeling_brand_new_llama.py::BrandNewLlamaModelIntegrationTests
SET RUN_SLOW=1 pytest -sv tests/models/brand_new_llama/test_modeling_brand_new_llama.py::BrandNewLlamaModelIntegrationTests
BrandNewLlama'ya özgü tüm özellikler, BrandNewLlamaModelTester/BrandNewLlamaModelTest altında ayrı bir testte test edilmelidir. Bu test genellikle gözden kaçırılır, ancak son derece önemlidir çünkü:
- süreç boyunca edindiğiniz bilgileri topluluğa aktarmaya yardımcı olur; modelin yenilikçi özelliklerinin nasıl çalıştığını göstererek
- gelecekteki katkıda bulunanlar, bu özel testleri çalıştırarak modeldeki değişiklikleri hızla test edebilir
Tokenizör uygulayın
Kullanıcılara en iyi performansı sağlamak için hızlı bir tokenizer (PreTrainedTokenizerFast) eklemenizi öneririz. PreTrainedTokenizerFast nasıl ekleneceği konusunda yardım almak için PR'ınızda @ArthurZucker veya @itazap etiketini kullanmaktan çekinmeyin.
Model halledildikten sıra tokenizer'a odaklanmaya geldi. Tokenizer, Transformers'taki mevcut bir tokenizer ile aynı veya çok benzer olmalıdır.
Orijinal tokenizer dosyasını bulun ve uygulamanıza yükleyin. Orijinal depoda bir dizeyi girdi olarak alıp input_ids döndüren bir betik oluşturun. Sahte kod aşağıdaki kodla benzer görünmelidir.
input_str = "This is a long example input string containing special characters .$?-, numbers 2872 234 12 and words."
model = BrandNewLlamaModel.load_pretrained_checkpoint("/path/to/checkpoint/")
input_ids = model.tokenize(input_str)Doğru tokenizer işlevini bulmak için orijinal depoyu aramanız veya orijinal depoyun klonunuzdaki mevcut tokenizer'ı yalnızca input_ids döndürecek şekilde değiştirmeniz gerekebilir. Tokenizer'ınız için betik aşağıdakine benzer görünmelidir.
from transformers import BrandNewLlamaTokenizer
input_str = "This is a long example input string containing special characters .$?-, numbers 2872 234 12 and words."
tokenizer = BrandNewLlamaTokenizer.from_pretrained("/path/to/tokenizer/folder/")
input_ids = tokenizer(input_str).input_idsHer iki uygulamanın da aynı input_ids'a sahip olması durumunda, bir tokenizer test dosyası ekleyin. Bu dosya, modelleme test dosyalarına benzerdir. Tokenizer test dosyaları, birkaç sabit kodlanmış entegrasyon testi içermelidir.
Görüntü işleyici uygulayın
Görüntü işleyiciler artık arka uç tabanlı bir mimari kullanır. Varsayılan arka uç, torchvision kütüphanesini kullanan ve GPU üzerinde görüntü işleme yapabilen TorchvisionBackend'dir. Bir PIL/NumPy alternatif arka ucu (PilBackend) de sağlanmaktadır. Her iki arka uç da
image_processing_backendsiçinden içe aktarılır. Yardım için @yonigozlan etiketlemekten çekinmeyin.
Bu örnek bir görüntü işleyici içermese de, modeliniz görüntü girdileri gerektiriyorsa bir tane uygulamanız gerekebilir. Görüntü işleyici, görüntüleri modeliniz için uygun bir formata dönüştürmekten sorumludur. Yeni bir tane uygulamadan önce, birçok modelin benzer görüntü işleme tekniklerini paylaştığı için Transformers kütüphanesindeki mevcut bir görüntü işleyicinin yeniden kullanılıp kullanılamayacağını kontrol edin. Ayrıca, mevcut bileşenleri yeniden kullanmak için görüntü işleyicilerde de modüler yapısını kullanabilirsiniz.
Yeni bir görüntü işleyici (image processor) uygulamanız gerekiyorsa, her modelin iki işleyici dosyası vardır:
image_processing_<model>.py: varsayılan torchvision destekli işlemci (<Model>ImageProcessor), TorchvisionBackend sınıfından türetilir. Bu, eski “fast” işlemcinin yerini alır.image_processing_pil_<model>.py: PIL/NumPy alternatif işlemcisi (<Model>ImageProcessorPil), PilBackend sınıfından türetilir. Bu, eski “yavaş” işlemcinin yerini alır.
torchvision backend dosyası, PIL dosyasının içe aktardığı özel kwargs sınıfını da tanımlar. Her iki dosya da @auto_docstring dekoratörünü kullanır — manuel sınıf docstring'leri eklemeyin. Adım adım anlatım ve tam örnekler için IMAGE_PROCESSOR_REFACTORING_GUIDE.md dosyasına başvurun.
tests/models/your_model_name/test_image_processing_your_model_name.py dosyasında görüntü işleyici için testler ekleyin. Bu testler, diğer görüntü işleyicilerinkilere benzer olmalı ve görüntü işleyicinin görüntü girdilerini doğru şekilde işlediğini doğrulamalıdır. Görüntü işleyiciniz benzersiz özellikler veya işleme yöntemleri içeriyorsa, bunlar için de özel testler eklediğinizden emin olun.
İşleyici uygulayın
Modeliniz metin ve görüntüler gibi birden çok modaliteyi kabul ediyorsa, bir işlemci (processor) eklemeniz gerekir. İşlemci, farklı modallere ait ön işlemleri merkezi olarak yönetir ve bunları modele iletmeden önce hazırlar.
İşleyici, her türdeki girdiyi doğru şekilde işlemek için __call__ işlevi içinde uygun modallara özgü işleyicileri çağırmalıdır. Beklenen yapılarını anlamak için kütüphanedeki mevcut işleyicileri kontrol etmeyi unutmayın. Transformers, __call__ işlevi imzasında aşağıdaki sözleşmeyi kullanır.
def __call__(
self,
images: ImageInput = None,
text: Union[TextInput, PreTokenizedInput, list[TextInput], list[PreTokenizedInput]] = None,
audio=None,
videos=None,
**kwargs: Unpack[YourModelProcessorKwargs],
) -> BatchFeature:
...YourModelProcessorKwargs, tipik işleme argümanlarının yanı sıra belirli bir işleyicinin gerektirebileceği ek argümanları içeren bir TypedDict'tir.
tests/models/your_model_name/test_processor_your_model_name.py dosyasında işlemci için testler ekleyin. Bu testler, diğer işlemciler için yazılan testlere benzer olmalı ve işlemcinin farklı modaliteleri doğru şekilde işlediğini doğrulamalıdır.
Entegrasyon testleri
Artık bir model ve tokenizer'a sahip olduğunuz için, model ve tokenizer için uçtan uca entegrasyon testlerini tests/models/brand_new_llama/test_modeling_brand_new_llama.py dosyasına ekleyin.
Test, modelin beklenildiği gibi çalıştığını göstermek için anlamlı bir metinden-metne örneği sağlamalıdır. Örneğin, kaynak-hedef çeviri çifti, makale-özet çifti veya soru-cevap çifti dahil edebilirsiniz.
Eğer kontrol noktası, bir aşağı akış görevinde ince ayarlanmadıysa, model testleri yeterlidir.
Son olarak, modellerin iç tensörlerine .to(self.device) ifadelerini ekleyerek testlerinizin bir GPU üzerinde çalışabildiğinden emin olmaya çalışın. GPU erişiminiz yoksa, bunu sizin için hallederiz.
Belgelendirme ekle
Modeliniz, kullanıcılar onu nasıl kullanacaklarını bildikleri sürece işe yarar. Bu nedenle dokümantasyon ve docstring eklemek önemlidir. Cookiecutter, modelinizle ilgili bilgilerle doldurabileceğiniz bir şablon dosyası olan docs/source/model_doc/brand_new_llama.md ekledi.
Bu genellikle bir kullanıcının bir modelle ilk etkileşimi olduğundan, dokümantasyonun açık ve öz olması gerekir. Modelin nasıl kullanılacağına dair örnekler eklemek çoğu zaman çok faydalıdır.
src/transformers/models/brand_new_llama/modeling_brand_new_llama.py dosyasına docstring'lerin eklendiğinden ve tüm gerekli girdilerin ve çıktıların dahil olduğundan emin olun. Belgeleme ve docstring yazımı için kılavuzumuza göz atın.
Yeniden yapılandır
Şimdi düzenlemeler yapma ve kod stilinin kütüphanenin geri kalanıyla tutarlı olduğundan emin olma zamanı. Yanlış stilleri otomatik olarak düzeltmek için aşağıdaki komutu çalıştırın.
make style
Kod stilinin kalite kontrollerinden geçtiğini doğrulamak için aşağıdaki komutu çalıştırın.
make check-repo
Transformers'ın katı tasarım testleri nedeniyle, gönderdiğiniz pull request'te diğer başarısız testler veya kontroller (eksik docstring veya hatalı adlandırma) olabilir. Bu konularda takılırsanız size yardımcı olabiliriz.
Kodun doğru çalıştığından emin olduktan sonra, daha okunabilir veya daha temiz hale getirmek için yeniden yapılandırabilirsiniz.
Hub'a Yükle
Tüm checkpoint'leri Hub'a dönüştürüp yükleyin. Model hakkında daha fazla şeffaflık ve bağlam sağlamak için bir model kartı ekleyin. Model kartı, bir checkpoint'in belirli özelliklerini, modelin nasıl eğitildiğini ve nasıl kullanılacağına dair kod örneklerini vurgulamalıdır.
Birçok durumda, kullanıcıların çalıştırabileceği etkileşimli bir defter eklemek, modelin çıkarım için nasıl kullanılacağını veya bir aşağı akış görevinde nasıl ince ayarlanacağını göstermenin harika bir yoludur. Zorunlu olmamakla birlikte, bir defter dahil etmek modelinizin daha geniş bir kitle tarafından benimsenmesini sağlayabilir.
Ayrıca, model için uygun bir ad belirlemek ve modeli yüklemek için gerekli erişim izinlerini almak üzere Transformers ekibiyle de görüşmelisiniz.
Modeli yüklemek için push_to_hub() yöntemini kullanın.
brand_new_bert.push_to_hub("brand_new_llama")Hub'a model yükleme hakkında daha fazla bilgi için Paylaşım kılavuzuna bakın.
Modelinizi birleştirin
Sonunda pull request'inizi birleştirmeye ve modeli resmi olarak Transformers'a eklemeye hazırsınız! Tüm testlerin geçtiğinden ve tüm yorumların ve geri bildirimlerin ele alındığından emin olun.
Transformers'a yeni bir model eklediğiniz için tebrikler! 🥳
Bu çok önemli bir katkıdır. Çalışmanız, Transformers'ı dünya genelindeki geliştiriciler ve araştırmacılar için daha erişilebilir hale getiriyor. Katkınızla gurur duymalı ve bu başarıyı toplulukla paylaşmalısınız!
Bkz.
- Model yapı kuralları — tüm
modeling_*.pyveconfiguration_*.pydosyalarında uygulanan statik kurallar. Bir PR açmadan önce bunları kontrol etmek içinmake typingkomutunu çalıştırın. - Pull request kontrolleri — PR'nizde çalışan CI kontrollerinin ve bunları nasıl geçeceğinize dair tam referans.