Khaitan

Khaitan

1635394893

पायथन में ट्रांसफॉर्मर का उपयोग करके BERT को प्रीट्रेन कैसे करें

जानें कि आप पाइथन में हगिंगफेस ट्रांसफॉर्मर्स लाइब्रेरी का उपयोग करके अपने कस्टम डेटासेट पर मास्क्ड लैंग्वेज मॉडलिंग (एमएलएम) कार्य पर बीईआरटी और अन्य ट्रांसफॉर्मर को कैसे दिखा सकते हैं।

एक पूर्व-प्रशिक्षित मॉडल एक ऐसा मॉडल है जिसे पहले बड़े डेटासेट पर प्रशिक्षित किया गया था और प्रत्यक्ष उपयोग या फ़ाइन-ट्यूनिंग के लिए सहेजा गया था । इस ट्यूटोरियल में, आप सीखेंगे कि आप पायथन में हगिंगफेस ट्रांसफॉर्मर लाइब्रेरी की मदद से अपने कस्टम टेक्स्ट डेटासेट पर BERT (या किसी अन्य ट्रांसफॉर्मर मॉडल) को कैसे प्रीट्रेन कर सकते हैं।

आरंभ करने के लिए, हमें 3 पुस्तकालय स्थापित करने की आवश्यकता है:

$ pip install datasets transformers==4.11.2 sentencepiece

यदि आप साथ चलना चाहते हैं, तो एक नई नोटबुक, या पायथन फ़ाइल खोलें और आवश्यक पुस्तकालयों को आयात करें:

from datasets import *
from transformers import *
from tokenizers import *
import os
import json

डेटासेट चुनना

यदि आप एक ट्रांसफॉर्मर को पूर्व-प्रशिक्षित करने के इच्छुक हैं, तो आपके पास एक कस्टम डेटासेट होने की सबसे अधिक संभावना है। लेकिन इस ट्यूटोरियल में प्रदर्शन उद्देश्यों के लिए, हम cc_newsडेटासेट का उपयोग करने जा रहे हैं , हम उसके लिए हगिंगफेस डेटासेट लाइब्रेरी का उपयोग करेंगे । परिणामस्वरूप, अपने कस्टम डेटासेट को लाइब्रेरी में लोड करने के लिए इस लिंक का अनुसरण करना सुनिश्चित करें ।

CC-News डेटासेट में दुनिया भर की समाचार साइटों के समाचार लेख होते हैं। इसमें जनवरी 2017 और दिसंबर 2019 के बीच प्रकाशित अंग्रेजी में 708,241 समाचार लेख शामिल हैं ।

डेटासेट डाउनलोड करना और तैयार करना:

# download and prepare cc_news dataset
dataset = load_dataset("cc_news", split="train")

डेटासेट में केवल एक विभाजन है, इसलिए हमें इसे प्रशिक्षण और परीक्षण सेट में विभाजित करने की आवश्यकता है:

# split the dataset into training (90%) and testing (10%)
d = dataset.train_test_split(test_size=0.1)
d["train"], d["test"]

आप seedपैरामीटर को train_test_split()विधि में भी पास कर सकते हैं ताकि यह कई बार चलने के बाद एक ही सेट हो।

आउटपुट:

(Dataset({
     features: ['title', 'text', 'domain', 'date', 'description', 'url', 'image_url'],
     num_rows: 637416
 }), Dataset({
     features: ['title', 'text', 'domain', 'date', 'description', 'url', 'image_url'],
     num_rows: 70825
 }))

आइए देखें कि यह कैसा दिखता है:

for t in d["train"]["text"][:3]:
  print(t)
  print("="*50)

आउटपुट (छीन):

Pretty sure women wish men did this better too!!
Q: A recent survey showed that 1/3 of men wish they did THIS better. What is...<STRIPPED>
==================================================
× GoDaddy boots neo-Nazi site after a derogatory story on the Charlottesville victim
The Daily Stormer, a white supremacist and neo-Nazi website,...<STRIPPED>
==================================================
French bank Natixis under investigation over subprime losses
PARIS, Feb 15 Natixis has been placed under formal investigation...<STRIPPED>

जैसा कि पहले उल्लेख किया गया है, यदि आपके पास अपना कस्टम डेटासेट है, तो आप या तो ऊपर के रूप में लोड करने के लिए अपने डेटासेट को सेट करने के लिंक का अनुसरण कर सकते हैं, या आप LineByLineTextDatasetकक्षा का उपयोग कर सकते हैं यदि आपका कस्टम डेटासेट एक टेक्स्ट फ़ाइल है जहां सभी वाक्य एक नए द्वारा अलग किए गए हैं रेखा।

हालांकि, उपयोग करने से बेहतर तरीका यह LineByLineTextDatasetहै कि आप अपने कस्टम डेटासेट को सेट करें, splitकमांड या किसी अन्य पायथन कोड का उपयोग करके अपनी टेक्स्ट फ़ाइल को कई चंक फाइलों में विभाजित करें , और load_dataset()जैसा कि हमने ऊपर किया था, वैसे ही लोड करें:

# if you have huge custom dataset separated into files
# load the splitted files
files = ["train1.txt", "train2.txt"] # train3.txt, etc.
dataset = load_dataset("text", data_files=files, split="train")

यदि आपके पास अपना कस्टम डेटा एक विशाल फ़ाइल के रूप में है, तो आपको फ़ंक्शन splitका उपयोग करके उन्हें लोड करने से पहले इसे मुट्ठी भर टेक्स्ट फ़ाइलों (जैसे कि लिनक्स या कोलाब पर कमांड का उपयोग करना) में विभाजित करना चाहिए load_dataset(), क्योंकि यदि यह मेमोरी से अधिक हो जाता है तो रनटाइम क्रैश हो जाएगा। .

टोकनिज़र का प्रशिक्षण

इसके बाद, हमें अपने टोकननाइज़र को प्रशिक्षित करने की आवश्यकता है। ऐसा करने के लिए, हमें अपने डेटासेट को टेक्स्ट फाइलों में लिखना होगा, क्योंकि टोकननाइज़र लाइब्रेरी को इनपुट की आवश्यकता होती है:

# if you want to train the tokenizer from scratch (especially if you have custom
# dataset loaded as datasets object), then run this cell to save it as files
# but if you already have your custom data as text files, there is no point using this
def dataset_to_text(dataset, output_filename="data.txt"):
  """Utility function to save dataset text to disk,
  useful for using the texts to train the tokenizer 
  (as the tokenizer accepts files)"""
  with open(output_filename, "w") as f:
    for t in dataset["text"]:
      print(t, file=f)

# save the training set to train.txt
dataset_to_text(d["train"], "train.txt")
# save the testing set to test.txt
dataset_to_text(d["test"], "test.txt")

उपरोक्त कोड सेल का मुख्य उद्देश्य डेटासेट ऑब्जेक्ट को टेक्स्ट फाइल के रूप में सहेजना है। यदि आपके पास पहले से ही टेक्स्ट फ़ाइल के रूप में आपका डेटासेट है, तो आपको इस चरण को छोड़ देना चाहिए। अगला, आइए कुछ मापदंडों को परिभाषित करें:

special_tokens = [
  "[PAD]", "[UNK]", "[CLS]", "[SEP]", "[MASK]", "<S>", "<T>"
]
# if you want to train the tokenizer on both sets
# files = ["train.txt", "test.txt"]
# training the tokenizer on the training set
files = ["train.txt"]
# 30,522 vocab is BERT's default vocab size, feel free to tweak
vocab_size = 30_522
# maximum sequence length, lowering will result to faster training (when increasing batch size)
max_length = 512
# whether to truncate
truncate_longer_samples = True

filesसूची प्रशिक्षण के लिए टोकननाइज़र को पास करने के लिए फ़ाइलों की सूची है। vocab_sizeटोकन का शब्दावली आकार है। max_lengthअधिकतम अनुक्रम लंबाई है। आइए अब टोकननाइज़र को प्रशिक्षित करें:

# initialize the WordPiece tokenizer
tokenizer = BertWordPieceTokenizer()
# train the tokenizer
tokenizer.train(files=files, vocab_size=vocab_size, special_tokens=special_tokens)
# enable truncation up to the maximum 512 tokens
tokenizer.enable_truncation(max_length=max_length)

चूंकि यह BERT है, डिफ़ॉल्ट टोकननाइज़र WordPiece है । नतीजतन, हम लाइब्रेरी BertWordPieceTokenizer()से टोकननाइज़र क्लास को इनिशियलाइज़ करते हैं tokenizersऔर train()इसे प्रशिक्षित करने के लिए विधि का उपयोग करते हैं । आइए इसे अभी सेव करें:

model_path = "pretrained-bert"
# make the directory if not already there
if not os.path.isdir(model_path):
  os.mkdir(model_path)
# save the tokenizer  
tokenizer.save_model(model_path)
# dumping some of the tokenizer config to config file, 
# including special tokens, whether to lower case and the maximum sequence length
with open(os.path.join(model_path, "config.json"), "w") as f:
  tokenizer_cfg = {
      "do_lower_case": True,
      "unk_token": "[UNK]",
      "sep_token": "[SEP]",
      "pad_token": "[PAD]",
      "cls_token": "[CLS]",
      "mask_token": "[MASK]",
      "model_max_length": max_length,
      "max_len": max_length,
  }
  json.dump(tokenizer_cfg, f)

tokenizer.save_model()विधि है कि रास्ते में शब्दावली फ़ाइल की बचत होती है, हम भी मैन्युअल रूप से इस तरह के विशेष टोकन के रूप में कुछ tokenizer विन्यास, बचाने:

  • unk_token: एक विशेष टोकन जो एक आउट-ऑफ-शब्दावली टोकन का प्रतिनिधित्व करता है, भले ही टोकननाइज़र एक वर्डपीस टोकननाइज़र है, unkटोकन असंभव नहीं हैं, लेकिन दुर्लभ हैं।
  • sep_token: एक विशेष टोकन जो एक ही इनपुट में दो अलग-अलग वाक्यों को अलग करता है।
  • pad_token: एक विशेष टोकन जिसका उपयोग वाक्यों को भरने के लिए किया जाता है जो अधिकतम अनुक्रम लंबाई तक नहीं पहुंचते हैं (क्योंकि टोकन की सरणियों का आकार समान होना चाहिए)।
  • cls_token: इनपुट के वर्ग का प्रतिनिधित्व करने वाला एक विशेष टोकन।
  • mask_token: यह वह मुखौटा टोकन है जिसका उपयोग हम नकाबपोश भाषा मॉडलिंग (एमएलएम) पूर्व-प्रशिक्षण कार्य के लिए करते हैं।

टोकननाइज़र का प्रशिक्षण पूरा होने के बाद (इसमें कई मिनट लगने चाहिए), आइए इसे अभी लोड करें:

# when the tokenizer is trained and configured, load it as BertTokenizerFast
tokenizer = BertTokenizerFast.from_pretrained(model_path)

डेटासेट को टोकन करना

अब जब हमारे पास टोकननाइज़र तैयार है, तो नीचे दिया गया कोड डेटासेट को टोकन करने के लिए ज़िम्मेदार है:

def encode_with_truncation(examples):
  """Mapping function to tokenize the sentences passed with truncation"""
  return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=max_length, return_special_tokens_mask=True)

def encode_without_truncation(examples):
  """Mapping function to tokenize the sentences passed without truncation"""
  return tokenizer(examples["text"], return_special_tokens_mask=True)

# the encode function will depend on the truncate_longer_samples variable
encode = encode_with_truncation if truncate_longer_samples else encode_without_truncation

# tokenizing the train dataset
train_dataset = d["train"].map(encode, batched=True)
# tokenizing the testing dataset
test_dataset = d["test"].map(encode, batched=True)
if truncate_longer_samples:
  # remove other columns and set input_ids and attention_mask as 
  train_dataset.set_format(type="torch", columns=["input_ids", "attention_mask"])
  test_dataset.set_format(type="torch", columns=["input_ids", "attention_mask"])
else:
  test_dataset.set_format(columns=["input_ids", "attention_mask", "special_tokens_mask"])
  train_dataset.set_format(columns=["input_ids", "attention_mask", "special_tokens_mask"])
train_dataset, test_dataset

encodeहमारे डेटासेट को टोकन करने के लिए हम जिस कॉलबैक का उपयोग करते हैं, वह truncate_longer_samplesबूलियन वैरिएबल पर निर्भर करता है । यदि सेट किया जाता है True, तो हम अधिकतम अनुक्रम लंबाई ( max_lengthपैरामीटर) से अधिक वाक्यों को काट देते हैं । अन्यथा, हम नहीं।

अगला, पर सेट truncate_longer_samplesकरने के मामले में False, हमें अपने असंबद्ध नमूनों को एक साथ जोड़ने और उन्हें निश्चित आकार के वैक्टर में काटने की आवश्यकता है क्योंकि मॉडल प्रशिक्षण के दौरान एक निश्चित आकार के अनुक्रम की अपेक्षा करता है:

# Main data processing function that will concatenate all texts from our dataset and generate chunks of
# max_seq_length.
def group_texts(examples):
    # Concatenate all texts.
    concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()}
    total_length = len(concatenated_examples[list(examples.keys())[0]])
    # We drop the small remainder, we could add padding if the model supported it instead of this drop, you can
    # customize this part to your needs.
    if total_length >= max_length:
        total_length = (total_length // max_length) * max_length
    # Split by chunks of max_len.
    result = {
        k: [t[i : i + max_length] for i in range(0, total_length, max_length)]
        for k, t in concatenated_examples.items()
    }
    return result
# Note that with `batched=True`, this map processes 1,000 texts together, so group_texts throws away a
# remainder for each of those groups of 1,000 texts. You can adjust that batch_size here but a higher value
# might be slower to preprocess.
#
# To speed up this part, we use multiprocessing. See the documentation of the map method for more information:
# https://huggingface.co/docs/datasets/package_reference/main_classes.html#datasets.Dataset.map
if not truncate_longer_samples:
  train_dataset = train_dataset.map(group_texts, batched=True, batch_size=2_000,
                                    desc=f"Grouping texts in chunks of {max_length}")
  test_dataset = test_dataset.map(group_texts, batched=True, batch_size=2_000,
                                  num_proc=4, desc=f"Grouping texts in chunks of {max_length}")

उपरोक्त अधिकांश कोड run_mlm.pyस्क्रिप्ट से हगिंगफेस ट्रांसफॉर्मर उदाहरणों से लाए गए थे , इसलिए यह वास्तव में पुस्तकालय द्वारा ही उपयोग किया जाता है।

यदि आप सभी पाठों को संयोजित नहीं करना चाहते हैं और फिर उन्हें 512 टोकन के टुकड़ों में विभाजित करना चाहते हैं, तो सुनिश्चित करें कि आपने पर सेट truncate_longer_samplesकिया है True, इसलिए यह प्रत्येक पंक्ति को उसकी लंबाई की परवाह किए बिना एक व्यक्तिगत नमूने के रूप में मानेगा। ध्यान दें कि यदि आप पर सेट truncate_longer_samplesकरते हैं True, तो उपरोक्त कोड सेल बिल्कुल भी निष्पादित नहीं किया जाएगा।

मॉडल लोड हो रहा है

इस ट्यूटोरियल के लिए, हम BERT को चुन रहे हैं, लेकिन हगिंगफेस ट्रांसफॉर्मर लाइब्रेरी द्वारा समर्थित किसी भी ट्रांसफॉर्मर मॉडल को चुनने के लिए स्वतंत्र महसूस करें, जैसे RobertaForMaskedLMया DistilBertForMaskedLM:

# initialize the model with the config
model_config = BertConfig(vocab_size=vocab_size, max_position_embeddings=max_length)
model = BertForMaskedLM(config=model_config)

हम मॉडल कॉन्फ़िगरेशन का उपयोग करके प्रारंभ करते हैं BertConfig, और शब्दावली आकार के साथ-साथ अधिकतम अनुक्रम लंबाई पास करते हैं। फिर हम BertForMaskedLMमॉडल को इनिशियलाइज़ करने के लिए कॉन्फिगरेशन पास करते हैं ।

पूर्व प्रशिक्षण

इससे पहले कि हम अपने मॉडल का ढोंग करना शुरू करें, हमें नकाबपोश भाषा मॉडल (एमएलएम) कार्य के लिए अपने डेटासेट में बेतरतीब ढंग से टोकन को मास्क करने का एक तरीका चाहिए। सौभाग्य से, पुस्तकालय केवल एक DataCollatorForLanguageModelingवस्तु का निर्माण करके हमारे लिए इसे आसान बनाता है :

# initialize the data collator, randomly masking 20% (default is 15%) of the tokens for the Masked Language
# Modeling (MLM) task
data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer, mlm=True, mlm_probability=0.2
)

हम पास करते हैं tokenizerऔर सेट mlmकरते हैं True, और प्रत्येक टोकन को 20% संभावना से यादृच्छिक रूप से बदलने के mlm_probabilityलिए 0.2 पर भी सेट करते हैं [MASK]

अगला, आइए हमारे प्रशिक्षण तर्कों को आरंभ करें:

training_args = TrainingArguments(
    output_dir=model_path,          # output directory to where save model checkpoint
    evaluation_strategy="steps",    # evaluate each `logging_steps` steps
    overwrite_output_dir=True,      
    num_train_epochs=10,            # number of training epochs, feel free to tweak
    per_device_train_batch_size=10, # the training batch size, put it as high as your GPU memory fits
    gradient_accumulation_steps=8,  # accumulating the gradients before updating the weights
    per_device_eval_batch_size=64,  # evaluation batch size
    logging_steps=500,             # evaluate, log and save model checkpoints every 1000 step
    save_steps=500,
    # load_best_model_at_end=True,  # whether to load the best model (in terms of loss) at the end of training
    # save_total_limit=3,           # whether you don't have much space so you let only 3 model weights saved in the disk
)

प्रत्येक तर्क टिप्पणी में समझाया गया है, का उल्लेख डॉक्स अधिक जानकारी के लिए। आइए अब अपना ट्रेनर बनाएं:TrainingArguments

# initialize the trainer and pass everything to it
trainer = Trainer(
    model=model,
    args=training_args,
    data_collator=data_collator,
    train_dataset=train_dataset,
    eval_dataset=test_dataset,
)

हम अपने प्रशिक्षण तर्कों को Trainer, साथ ही साथ मॉडल, डेटा कोलेटर और प्रशिक्षण सेट को पास करते हैं। हम train()प्रशिक्षण शुरू करने के लिए अभी कॉल करते हैं:

# train the model
trainer.train()
[10135/79670 18:53:08 < 129:35:53, 0.15 it/s, Epoch 1.27/10]
Step	Training Loss	Validation Loss
1000	6.904000	6.558231
2000	6.498800	6.401168
3000	6.362600	6.277831
4000	6.251000	6.172856
5000	6.155800	6.071129
6000	6.052800	5.942584
7000	5.834900	5.546123
8000	5.537200	5.248503
9000	5.272700	4.934949
10000	4.915900	4.549236

डेटासेट के आकार, प्रशिक्षण बैच के आकार (यानी इसे आपकी GPU मेमोरी के अनुसार बढ़ाएँ), और GPU की गति के आधार पर प्रशिक्षण में कई घंटे से लेकर कई दिनों तक का समय लगेगा।

जैसा कि आप आउटपुट में देख सकते हैं, मॉडल में अभी भी सुधार हो रहा है और सत्यापन हानि अभी भी कम हो रही है। सत्यापन हानि कम होने के बाद आपको आमतौर पर प्रशिक्षण रद्द करना होगा।

जब से हम की स्थापना की है logging_stepsऔर save_steps1000 के लिए है, तो ट्रेनर का मूल्यांकन करने और हर 1000 चरणों के बाद मॉडल की बचत होगी (यानी चरणों एक्स पर प्रशिक्षित gradient_accumulation_stepएक्स per_device_train_size=  1000x8x10 = 80,000 नमूने)। नतीजतन, मैंने लगभग 19 घंटे के प्रशिक्षण, या 10000 चरणों (यानी लगभग 1.27 युगों, या 800,000 नमूनों पर प्रशिक्षित ) के बाद प्रशिक्षण रद्द कर दिया है , और मॉडल का उपयोग करना शुरू कर दिया है। अगले भाग में, हम देखेंगे कि हम अनुमान के लिए मॉडल का उपयोग कैसे कर सकते हैं।

मॉडल का उपयोग करना

इससे पहले कि हम मॉडल का उपयोग, मान लेते हैं हमारे पास नहीं है जाने modelऔर tokenizerवर्तमान क्रम में चर। इसलिए, हमें उन्हें फिर से लोड करने की आवश्यकता है:

# load the model checkpoint
model = BertForMaskedLM.from_pretrained(os.path.join(model_path, "checkpoint-10000"))
# load the tokenizer
tokenizer = BertTokenizerFast.from_pretrained(model_path)

यदि आप Google Colab पर हैं, तो आपको बाद में उपयोग के लिए अपनी चौकियों को Google ड्राइव में सहेजना होगा, आप model_pathस्थानीय पथ के बजाय ड्राइव पथ पर सेट करके ऐसा कर सकते हैं जैसे हमने यहां किया था, बस सुनिश्चित करें कि आपके पास वहां पर्याप्त जगह है .

वैकल्पिक रूप से, आप अपने मॉडल और टोकननाइज़र को हगिंगफेस हब में धकेल सकते हैं, इसे करने के लिए इस उपयोगी मार्गदर्शिका की जाँच करें ।

आइए अब हमारे मॉडल का उपयोग करें:

fill_mask = pipeline("fill-mask", model=model, tokenizer=tokenizer)

हम साधारण पाइपलाइन एपीआई का उपयोग करते हैं , और दोनों को पास modelकरते हैं tokenizer। आइए कुछ उदाहरणों की भविष्यवाणी करें:

# perform predictions
examples = [
  "Today's most trending hashtags on [MASK] is Donald Trump",
  "The [MASK] was cloudy yesterday, but today it's rainy.",
]
for example in examples:
  for prediction in fill_mask(example):
    print(f"{prediction['sequence']}, confidence: {prediction['score']}")
  print("="*50)

आउटपुट:

today's most trending hashtags on twitter is donald trump, confidence: 0.1027069091796875
today's most trending hashtags on monday is donald trump, confidence: 0.09271949529647827
today's most trending hashtags on tuesday is donald trump, confidence: 0.08099588006734848
today's most trending hashtags on facebook is donald trump, confidence: 0.04266013577580452
today's most trending hashtags on wednesday is donald trump, confidence: 0.04120611026883125
==================================================
the weather was cloudy yesterday, but today it's rainy., confidence: 0.04445931687951088
the day was cloudy yesterday, but today it's rainy., confidence: 0.037249673157930374
the morning was cloudy yesterday, but today it's rainy., confidence: 0.023775646463036537
the weekend was cloudy yesterday, but today it's rainy., confidence: 0.022554103285074234
the storm was cloudy yesterday, but today it's rainy., confidence: 0.019406016916036606
==================================================

यह प्रभावशाली है, मैंने प्रशिक्षण रद्द कर दिया है और मॉडल अभी भी दिलचस्प परिणाम दे रहा है!

निष्कर्ष

और वहां आपके पास हगिंगफेस लाइब्रेरी का उपयोग करके बीईआरटी या अन्य ट्रांसफॉर्मर को पूर्व-प्रशिक्षित करने के लिए एक पूरा कोड है, नीचे कुछ सुझाव दिए गए हैं:

  • जैसा कि ऊपर उल्लेख किया गया है, प्रशिक्षण की गति GPU की गति, डेटासेट में नमूनों की संख्या और बैच आकार पर निर्भर करेगी। मैंने प्रशिक्षण बैच का आकार 10 पर सेट किया है, क्योंकि यह अधिकतम है जो कोलाब पर मेरी GPU मेमोरी को फिट कर सकता है। यदि आपके पास अधिक मेमोरी है, तो इसे बढ़ाना सुनिश्चित करें ताकि आप प्रशिक्षण की गति को काफी बढ़ा सकें।
  • प्रशिक्षण के दौरान, यदि आप देखते हैं कि सत्यापन हानि बढ़ने लगती है, तो उस चेकपॉइंट को याद रखना सुनिश्चित करें जहां सबसे कम सत्यापन हानि होती है ताकि आप उस चेकपॉइंट को बाद में उपयोग के लिए लोड कर सकें। आप यह भी सेट कर सकते हैं load_best_model_at_endकि Trueक्या आप नुकसान का ट्रैक नहीं रखना चाहते हैं, क्योंकि प्रशिक्षण समाप्त होने पर यह नुकसान के मामले में सबसे अच्छा भार लोड करेगा।
  • शब्दावली का आकार मूल बीईआरटी कॉन्फ़िगरेशन के आधार पर चुना गया था, क्योंकि इसका आकार 30,522 था , अगर आपको लगता है कि आपके डेटासेट की भाषा में एक बड़ी शब्दावली है, या आप इसके साथ प्रयोग कर सकते हैं, तो इसे बढ़ाने के लिए स्वतंत्र महसूस करें।
  • यदि आप पर सेट truncate_longer_samplesकरते हैं False, तो कोड मानता है कि आपके पास एक वाक्य (यानी पंक्ति) पर बड़ा टेक्स्ट है, आप देखेंगे कि इसे संसाधित करने में अधिक समय लगता है, खासकर यदि आप विधि batch_sizeपर एक बड़ा सेट करते हैं map()। यह प्रक्रिया घंटे का एक बहुत लेता है, तो आप या तो सेट कर सकते हैं truncate_longer_samplesकरने के लिए Trueताकि आप वाक्य है कि से अधिक काट-छांट max_lengthटोकन या आप उपयोग कर संसाधित करने के बाद डाटासेट बचा सकता है save_to_disk()विधि, ताकि आप इसे एक बार संसाधित करने और कई बार इसे लोड।

यदि आप पाठ वर्गीकरण जैसे डाउनस्ट्रीम कार्य के लिए BERT को ठीक करने में रुचि रखते हैं, तो यह ट्यूटोरियल आपको इसके माध्यम से मार्गदर्शन करता है।

#python

What is GEEK

Buddha Community

पायथन में ट्रांसफॉर्मर का उपयोग करके BERT को प्रीट्रेन कैसे करें
Khaitan

Khaitan

1635394893

पायथन में ट्रांसफॉर्मर का उपयोग करके BERT को प्रीट्रेन कैसे करें

जानें कि आप पाइथन में हगिंगफेस ट्रांसफॉर्मर्स लाइब्रेरी का उपयोग करके अपने कस्टम डेटासेट पर मास्क्ड लैंग्वेज मॉडलिंग (एमएलएम) कार्य पर बीईआरटी और अन्य ट्रांसफॉर्मर को कैसे दिखा सकते हैं।

एक पूर्व-प्रशिक्षित मॉडल एक ऐसा मॉडल है जिसे पहले बड़े डेटासेट पर प्रशिक्षित किया गया था और प्रत्यक्ष उपयोग या फ़ाइन-ट्यूनिंग के लिए सहेजा गया था । इस ट्यूटोरियल में, आप सीखेंगे कि आप पायथन में हगिंगफेस ट्रांसफॉर्मर लाइब्रेरी की मदद से अपने कस्टम टेक्स्ट डेटासेट पर BERT (या किसी अन्य ट्रांसफॉर्मर मॉडल) को कैसे प्रीट्रेन कर सकते हैं।

आरंभ करने के लिए, हमें 3 पुस्तकालय स्थापित करने की आवश्यकता है:

$ pip install datasets transformers==4.11.2 sentencepiece

यदि आप साथ चलना चाहते हैं, तो एक नई नोटबुक, या पायथन फ़ाइल खोलें और आवश्यक पुस्तकालयों को आयात करें:

from datasets import *
from transformers import *
from tokenizers import *
import os
import json

डेटासेट चुनना

यदि आप एक ट्रांसफॉर्मर को पूर्व-प्रशिक्षित करने के इच्छुक हैं, तो आपके पास एक कस्टम डेटासेट होने की सबसे अधिक संभावना है। लेकिन इस ट्यूटोरियल में प्रदर्शन उद्देश्यों के लिए, हम cc_newsडेटासेट का उपयोग करने जा रहे हैं , हम उसके लिए हगिंगफेस डेटासेट लाइब्रेरी का उपयोग करेंगे । परिणामस्वरूप, अपने कस्टम डेटासेट को लाइब्रेरी में लोड करने के लिए इस लिंक का अनुसरण करना सुनिश्चित करें ।

CC-News डेटासेट में दुनिया भर की समाचार साइटों के समाचार लेख होते हैं। इसमें जनवरी 2017 और दिसंबर 2019 के बीच प्रकाशित अंग्रेजी में 708,241 समाचार लेख शामिल हैं ।

डेटासेट डाउनलोड करना और तैयार करना:

# download and prepare cc_news dataset
dataset = load_dataset("cc_news", split="train")

डेटासेट में केवल एक विभाजन है, इसलिए हमें इसे प्रशिक्षण और परीक्षण सेट में विभाजित करने की आवश्यकता है:

# split the dataset into training (90%) and testing (10%)
d = dataset.train_test_split(test_size=0.1)
d["train"], d["test"]

आप seedपैरामीटर को train_test_split()विधि में भी पास कर सकते हैं ताकि यह कई बार चलने के बाद एक ही सेट हो।

आउटपुट:

(Dataset({
     features: ['title', 'text', 'domain', 'date', 'description', 'url', 'image_url'],
     num_rows: 637416
 }), Dataset({
     features: ['title', 'text', 'domain', 'date', 'description', 'url', 'image_url'],
     num_rows: 70825
 }))

आइए देखें कि यह कैसा दिखता है:

for t in d["train"]["text"][:3]:
  print(t)
  print("="*50)

आउटपुट (छीन):

Pretty sure women wish men did this better too!!
Q: A recent survey showed that 1/3 of men wish they did THIS better. What is...<STRIPPED>
==================================================
× GoDaddy boots neo-Nazi site after a derogatory story on the Charlottesville victim
The Daily Stormer, a white supremacist and neo-Nazi website,...<STRIPPED>
==================================================
French bank Natixis under investigation over subprime losses
PARIS, Feb 15 Natixis has been placed under formal investigation...<STRIPPED>

जैसा कि पहले उल्लेख किया गया है, यदि आपके पास अपना कस्टम डेटासेट है, तो आप या तो ऊपर के रूप में लोड करने के लिए अपने डेटासेट को सेट करने के लिंक का अनुसरण कर सकते हैं, या आप LineByLineTextDatasetकक्षा का उपयोग कर सकते हैं यदि आपका कस्टम डेटासेट एक टेक्स्ट फ़ाइल है जहां सभी वाक्य एक नए द्वारा अलग किए गए हैं रेखा।

हालांकि, उपयोग करने से बेहतर तरीका यह LineByLineTextDatasetहै कि आप अपने कस्टम डेटासेट को सेट करें, splitकमांड या किसी अन्य पायथन कोड का उपयोग करके अपनी टेक्स्ट फ़ाइल को कई चंक फाइलों में विभाजित करें , और load_dataset()जैसा कि हमने ऊपर किया था, वैसे ही लोड करें:

# if you have huge custom dataset separated into files
# load the splitted files
files = ["train1.txt", "train2.txt"] # train3.txt, etc.
dataset = load_dataset("text", data_files=files, split="train")

यदि आपके पास अपना कस्टम डेटा एक विशाल फ़ाइल के रूप में है, तो आपको फ़ंक्शन splitका उपयोग करके उन्हें लोड करने से पहले इसे मुट्ठी भर टेक्स्ट फ़ाइलों (जैसे कि लिनक्स या कोलाब पर कमांड का उपयोग करना) में विभाजित करना चाहिए load_dataset(), क्योंकि यदि यह मेमोरी से अधिक हो जाता है तो रनटाइम क्रैश हो जाएगा। .

टोकनिज़र का प्रशिक्षण

इसके बाद, हमें अपने टोकननाइज़र को प्रशिक्षित करने की आवश्यकता है। ऐसा करने के लिए, हमें अपने डेटासेट को टेक्स्ट फाइलों में लिखना होगा, क्योंकि टोकननाइज़र लाइब्रेरी को इनपुट की आवश्यकता होती है:

# if you want to train the tokenizer from scratch (especially if you have custom
# dataset loaded as datasets object), then run this cell to save it as files
# but if you already have your custom data as text files, there is no point using this
def dataset_to_text(dataset, output_filename="data.txt"):
  """Utility function to save dataset text to disk,
  useful for using the texts to train the tokenizer 
  (as the tokenizer accepts files)"""
  with open(output_filename, "w") as f:
    for t in dataset["text"]:
      print(t, file=f)

# save the training set to train.txt
dataset_to_text(d["train"], "train.txt")
# save the testing set to test.txt
dataset_to_text(d["test"], "test.txt")

उपरोक्त कोड सेल का मुख्य उद्देश्य डेटासेट ऑब्जेक्ट को टेक्स्ट फाइल के रूप में सहेजना है। यदि आपके पास पहले से ही टेक्स्ट फ़ाइल के रूप में आपका डेटासेट है, तो आपको इस चरण को छोड़ देना चाहिए। अगला, आइए कुछ मापदंडों को परिभाषित करें:

special_tokens = [
  "[PAD]", "[UNK]", "[CLS]", "[SEP]", "[MASK]", "<S>", "<T>"
]
# if you want to train the tokenizer on both sets
# files = ["train.txt", "test.txt"]
# training the tokenizer on the training set
files = ["train.txt"]
# 30,522 vocab is BERT's default vocab size, feel free to tweak
vocab_size = 30_522
# maximum sequence length, lowering will result to faster training (when increasing batch size)
max_length = 512
# whether to truncate
truncate_longer_samples = True

filesसूची प्रशिक्षण के लिए टोकननाइज़र को पास करने के लिए फ़ाइलों की सूची है। vocab_sizeटोकन का शब्दावली आकार है। max_lengthअधिकतम अनुक्रम लंबाई है। आइए अब टोकननाइज़र को प्रशिक्षित करें:

# initialize the WordPiece tokenizer
tokenizer = BertWordPieceTokenizer()
# train the tokenizer
tokenizer.train(files=files, vocab_size=vocab_size, special_tokens=special_tokens)
# enable truncation up to the maximum 512 tokens
tokenizer.enable_truncation(max_length=max_length)

चूंकि यह BERT है, डिफ़ॉल्ट टोकननाइज़र WordPiece है । नतीजतन, हम लाइब्रेरी BertWordPieceTokenizer()से टोकननाइज़र क्लास को इनिशियलाइज़ करते हैं tokenizersऔर train()इसे प्रशिक्षित करने के लिए विधि का उपयोग करते हैं । आइए इसे अभी सेव करें:

model_path = "pretrained-bert"
# make the directory if not already there
if not os.path.isdir(model_path):
  os.mkdir(model_path)
# save the tokenizer  
tokenizer.save_model(model_path)
# dumping some of the tokenizer config to config file, 
# including special tokens, whether to lower case and the maximum sequence length
with open(os.path.join(model_path, "config.json"), "w") as f:
  tokenizer_cfg = {
      "do_lower_case": True,
      "unk_token": "[UNK]",
      "sep_token": "[SEP]",
      "pad_token": "[PAD]",
      "cls_token": "[CLS]",
      "mask_token": "[MASK]",
      "model_max_length": max_length,
      "max_len": max_length,
  }
  json.dump(tokenizer_cfg, f)

tokenizer.save_model()विधि है कि रास्ते में शब्दावली फ़ाइल की बचत होती है, हम भी मैन्युअल रूप से इस तरह के विशेष टोकन के रूप में कुछ tokenizer विन्यास, बचाने:

  • unk_token: एक विशेष टोकन जो एक आउट-ऑफ-शब्दावली टोकन का प्रतिनिधित्व करता है, भले ही टोकननाइज़र एक वर्डपीस टोकननाइज़र है, unkटोकन असंभव नहीं हैं, लेकिन दुर्लभ हैं।
  • sep_token: एक विशेष टोकन जो एक ही इनपुट में दो अलग-अलग वाक्यों को अलग करता है।
  • pad_token: एक विशेष टोकन जिसका उपयोग वाक्यों को भरने के लिए किया जाता है जो अधिकतम अनुक्रम लंबाई तक नहीं पहुंचते हैं (क्योंकि टोकन की सरणियों का आकार समान होना चाहिए)।
  • cls_token: इनपुट के वर्ग का प्रतिनिधित्व करने वाला एक विशेष टोकन।
  • mask_token: यह वह मुखौटा टोकन है जिसका उपयोग हम नकाबपोश भाषा मॉडलिंग (एमएलएम) पूर्व-प्रशिक्षण कार्य के लिए करते हैं।

टोकननाइज़र का प्रशिक्षण पूरा होने के बाद (इसमें कई मिनट लगने चाहिए), आइए इसे अभी लोड करें:

# when the tokenizer is trained and configured, load it as BertTokenizerFast
tokenizer = BertTokenizerFast.from_pretrained(model_path)

डेटासेट को टोकन करना

अब जब हमारे पास टोकननाइज़र तैयार है, तो नीचे दिया गया कोड डेटासेट को टोकन करने के लिए ज़िम्मेदार है:

def encode_with_truncation(examples):
  """Mapping function to tokenize the sentences passed with truncation"""
  return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=max_length, return_special_tokens_mask=True)

def encode_without_truncation(examples):
  """Mapping function to tokenize the sentences passed without truncation"""
  return tokenizer(examples["text"], return_special_tokens_mask=True)

# the encode function will depend on the truncate_longer_samples variable
encode = encode_with_truncation if truncate_longer_samples else encode_without_truncation

# tokenizing the train dataset
train_dataset = d["train"].map(encode, batched=True)
# tokenizing the testing dataset
test_dataset = d["test"].map(encode, batched=True)
if truncate_longer_samples:
  # remove other columns and set input_ids and attention_mask as 
  train_dataset.set_format(type="torch", columns=["input_ids", "attention_mask"])
  test_dataset.set_format(type="torch", columns=["input_ids", "attention_mask"])
else:
  test_dataset.set_format(columns=["input_ids", "attention_mask", "special_tokens_mask"])
  train_dataset.set_format(columns=["input_ids", "attention_mask", "special_tokens_mask"])
train_dataset, test_dataset

encodeहमारे डेटासेट को टोकन करने के लिए हम जिस कॉलबैक का उपयोग करते हैं, वह truncate_longer_samplesबूलियन वैरिएबल पर निर्भर करता है । यदि सेट किया जाता है True, तो हम अधिकतम अनुक्रम लंबाई ( max_lengthपैरामीटर) से अधिक वाक्यों को काट देते हैं । अन्यथा, हम नहीं।

अगला, पर सेट truncate_longer_samplesकरने के मामले में False, हमें अपने असंबद्ध नमूनों को एक साथ जोड़ने और उन्हें निश्चित आकार के वैक्टर में काटने की आवश्यकता है क्योंकि मॉडल प्रशिक्षण के दौरान एक निश्चित आकार के अनुक्रम की अपेक्षा करता है:

# Main data processing function that will concatenate all texts from our dataset and generate chunks of
# max_seq_length.
def group_texts(examples):
    # Concatenate all texts.
    concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()}
    total_length = len(concatenated_examples[list(examples.keys())[0]])
    # We drop the small remainder, we could add padding if the model supported it instead of this drop, you can
    # customize this part to your needs.
    if total_length >= max_length:
        total_length = (total_length // max_length) * max_length
    # Split by chunks of max_len.
    result = {
        k: [t[i : i + max_length] for i in range(0, total_length, max_length)]
        for k, t in concatenated_examples.items()
    }
    return result
# Note that with `batched=True`, this map processes 1,000 texts together, so group_texts throws away a
# remainder for each of those groups of 1,000 texts. You can adjust that batch_size here but a higher value
# might be slower to preprocess.
#
# To speed up this part, we use multiprocessing. See the documentation of the map method for more information:
# https://huggingface.co/docs/datasets/package_reference/main_classes.html#datasets.Dataset.map
if not truncate_longer_samples:
  train_dataset = train_dataset.map(group_texts, batched=True, batch_size=2_000,
                                    desc=f"Grouping texts in chunks of {max_length}")
  test_dataset = test_dataset.map(group_texts, batched=True, batch_size=2_000,
                                  num_proc=4, desc=f"Grouping texts in chunks of {max_length}")

उपरोक्त अधिकांश कोड run_mlm.pyस्क्रिप्ट से हगिंगफेस ट्रांसफॉर्मर उदाहरणों से लाए गए थे , इसलिए यह वास्तव में पुस्तकालय द्वारा ही उपयोग किया जाता है।

यदि आप सभी पाठों को संयोजित नहीं करना चाहते हैं और फिर उन्हें 512 टोकन के टुकड़ों में विभाजित करना चाहते हैं, तो सुनिश्चित करें कि आपने पर सेट truncate_longer_samplesकिया है True, इसलिए यह प्रत्येक पंक्ति को उसकी लंबाई की परवाह किए बिना एक व्यक्तिगत नमूने के रूप में मानेगा। ध्यान दें कि यदि आप पर सेट truncate_longer_samplesकरते हैं True, तो उपरोक्त कोड सेल बिल्कुल भी निष्पादित नहीं किया जाएगा।

मॉडल लोड हो रहा है

इस ट्यूटोरियल के लिए, हम BERT को चुन रहे हैं, लेकिन हगिंगफेस ट्रांसफॉर्मर लाइब्रेरी द्वारा समर्थित किसी भी ट्रांसफॉर्मर मॉडल को चुनने के लिए स्वतंत्र महसूस करें, जैसे RobertaForMaskedLMया DistilBertForMaskedLM:

# initialize the model with the config
model_config = BertConfig(vocab_size=vocab_size, max_position_embeddings=max_length)
model = BertForMaskedLM(config=model_config)

हम मॉडल कॉन्फ़िगरेशन का उपयोग करके प्रारंभ करते हैं BertConfig, और शब्दावली आकार के साथ-साथ अधिकतम अनुक्रम लंबाई पास करते हैं। फिर हम BertForMaskedLMमॉडल को इनिशियलाइज़ करने के लिए कॉन्फिगरेशन पास करते हैं ।

पूर्व प्रशिक्षण

इससे पहले कि हम अपने मॉडल का ढोंग करना शुरू करें, हमें नकाबपोश भाषा मॉडल (एमएलएम) कार्य के लिए अपने डेटासेट में बेतरतीब ढंग से टोकन को मास्क करने का एक तरीका चाहिए। सौभाग्य से, पुस्तकालय केवल एक DataCollatorForLanguageModelingवस्तु का निर्माण करके हमारे लिए इसे आसान बनाता है :

# initialize the data collator, randomly masking 20% (default is 15%) of the tokens for the Masked Language
# Modeling (MLM) task
data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer, mlm=True, mlm_probability=0.2
)

हम पास करते हैं tokenizerऔर सेट mlmकरते हैं True, और प्रत्येक टोकन को 20% संभावना से यादृच्छिक रूप से बदलने के mlm_probabilityलिए 0.2 पर भी सेट करते हैं [MASK]

अगला, आइए हमारे प्रशिक्षण तर्कों को आरंभ करें:

training_args = TrainingArguments(
    output_dir=model_path,          # output directory to where save model checkpoint
    evaluation_strategy="steps",    # evaluate each `logging_steps` steps
    overwrite_output_dir=True,      
    num_train_epochs=10,            # number of training epochs, feel free to tweak
    per_device_train_batch_size=10, # the training batch size, put it as high as your GPU memory fits
    gradient_accumulation_steps=8,  # accumulating the gradients before updating the weights
    per_device_eval_batch_size=64,  # evaluation batch size
    logging_steps=500,             # evaluate, log and save model checkpoints every 1000 step
    save_steps=500,
    # load_best_model_at_end=True,  # whether to load the best model (in terms of loss) at the end of training
    # save_total_limit=3,           # whether you don't have much space so you let only 3 model weights saved in the disk
)

प्रत्येक तर्क टिप्पणी में समझाया गया है, का उल्लेख डॉक्स अधिक जानकारी के लिए। आइए अब अपना ट्रेनर बनाएं:TrainingArguments

# initialize the trainer and pass everything to it
trainer = Trainer(
    model=model,
    args=training_args,
    data_collator=data_collator,
    train_dataset=train_dataset,
    eval_dataset=test_dataset,
)

हम अपने प्रशिक्षण तर्कों को Trainer, साथ ही साथ मॉडल, डेटा कोलेटर और प्रशिक्षण सेट को पास करते हैं। हम train()प्रशिक्षण शुरू करने के लिए अभी कॉल करते हैं:

# train the model
trainer.train()
[10135/79670 18:53:08 < 129:35:53, 0.15 it/s, Epoch 1.27/10]
Step	Training Loss	Validation Loss
1000	6.904000	6.558231
2000	6.498800	6.401168
3000	6.362600	6.277831
4000	6.251000	6.172856
5000	6.155800	6.071129
6000	6.052800	5.942584
7000	5.834900	5.546123
8000	5.537200	5.248503
9000	5.272700	4.934949
10000	4.915900	4.549236

डेटासेट के आकार, प्रशिक्षण बैच के आकार (यानी इसे आपकी GPU मेमोरी के अनुसार बढ़ाएँ), और GPU की गति के आधार पर प्रशिक्षण में कई घंटे से लेकर कई दिनों तक का समय लगेगा।

जैसा कि आप आउटपुट में देख सकते हैं, मॉडल में अभी भी सुधार हो रहा है और सत्यापन हानि अभी भी कम हो रही है। सत्यापन हानि कम होने के बाद आपको आमतौर पर प्रशिक्षण रद्द करना होगा।

जब से हम की स्थापना की है logging_stepsऔर save_steps1000 के लिए है, तो ट्रेनर का मूल्यांकन करने और हर 1000 चरणों के बाद मॉडल की बचत होगी (यानी चरणों एक्स पर प्रशिक्षित gradient_accumulation_stepएक्स per_device_train_size=  1000x8x10 = 80,000 नमूने)। नतीजतन, मैंने लगभग 19 घंटे के प्रशिक्षण, या 10000 चरणों (यानी लगभग 1.27 युगों, या 800,000 नमूनों पर प्रशिक्षित ) के बाद प्रशिक्षण रद्द कर दिया है , और मॉडल का उपयोग करना शुरू कर दिया है। अगले भाग में, हम देखेंगे कि हम अनुमान के लिए मॉडल का उपयोग कैसे कर सकते हैं।

मॉडल का उपयोग करना

इससे पहले कि हम मॉडल का उपयोग, मान लेते हैं हमारे पास नहीं है जाने modelऔर tokenizerवर्तमान क्रम में चर। इसलिए, हमें उन्हें फिर से लोड करने की आवश्यकता है:

# load the model checkpoint
model = BertForMaskedLM.from_pretrained(os.path.join(model_path, "checkpoint-10000"))
# load the tokenizer
tokenizer = BertTokenizerFast.from_pretrained(model_path)

यदि आप Google Colab पर हैं, तो आपको बाद में उपयोग के लिए अपनी चौकियों को Google ड्राइव में सहेजना होगा, आप model_pathस्थानीय पथ के बजाय ड्राइव पथ पर सेट करके ऐसा कर सकते हैं जैसे हमने यहां किया था, बस सुनिश्चित करें कि आपके पास वहां पर्याप्त जगह है .

वैकल्पिक रूप से, आप अपने मॉडल और टोकननाइज़र को हगिंगफेस हब में धकेल सकते हैं, इसे करने के लिए इस उपयोगी मार्गदर्शिका की जाँच करें ।

आइए अब हमारे मॉडल का उपयोग करें:

fill_mask = pipeline("fill-mask", model=model, tokenizer=tokenizer)

हम साधारण पाइपलाइन एपीआई का उपयोग करते हैं , और दोनों को पास modelकरते हैं tokenizer। आइए कुछ उदाहरणों की भविष्यवाणी करें:

# perform predictions
examples = [
  "Today's most trending hashtags on [MASK] is Donald Trump",
  "The [MASK] was cloudy yesterday, but today it's rainy.",
]
for example in examples:
  for prediction in fill_mask(example):
    print(f"{prediction['sequence']}, confidence: {prediction['score']}")
  print("="*50)

आउटपुट:

today's most trending hashtags on twitter is donald trump, confidence: 0.1027069091796875
today's most trending hashtags on monday is donald trump, confidence: 0.09271949529647827
today's most trending hashtags on tuesday is donald trump, confidence: 0.08099588006734848
today's most trending hashtags on facebook is donald trump, confidence: 0.04266013577580452
today's most trending hashtags on wednesday is donald trump, confidence: 0.04120611026883125
==================================================
the weather was cloudy yesterday, but today it's rainy., confidence: 0.04445931687951088
the day was cloudy yesterday, but today it's rainy., confidence: 0.037249673157930374
the morning was cloudy yesterday, but today it's rainy., confidence: 0.023775646463036537
the weekend was cloudy yesterday, but today it's rainy., confidence: 0.022554103285074234
the storm was cloudy yesterday, but today it's rainy., confidence: 0.019406016916036606
==================================================

यह प्रभावशाली है, मैंने प्रशिक्षण रद्द कर दिया है और मॉडल अभी भी दिलचस्प परिणाम दे रहा है!

निष्कर्ष

और वहां आपके पास हगिंगफेस लाइब्रेरी का उपयोग करके बीईआरटी या अन्य ट्रांसफॉर्मर को पूर्व-प्रशिक्षित करने के लिए एक पूरा कोड है, नीचे कुछ सुझाव दिए गए हैं:

  • जैसा कि ऊपर उल्लेख किया गया है, प्रशिक्षण की गति GPU की गति, डेटासेट में नमूनों की संख्या और बैच आकार पर निर्भर करेगी। मैंने प्रशिक्षण बैच का आकार 10 पर सेट किया है, क्योंकि यह अधिकतम है जो कोलाब पर मेरी GPU मेमोरी को फिट कर सकता है। यदि आपके पास अधिक मेमोरी है, तो इसे बढ़ाना सुनिश्चित करें ताकि आप प्रशिक्षण की गति को काफी बढ़ा सकें।
  • प्रशिक्षण के दौरान, यदि आप देखते हैं कि सत्यापन हानि बढ़ने लगती है, तो उस चेकपॉइंट को याद रखना सुनिश्चित करें जहां सबसे कम सत्यापन हानि होती है ताकि आप उस चेकपॉइंट को बाद में उपयोग के लिए लोड कर सकें। आप यह भी सेट कर सकते हैं load_best_model_at_endकि Trueक्या आप नुकसान का ट्रैक नहीं रखना चाहते हैं, क्योंकि प्रशिक्षण समाप्त होने पर यह नुकसान के मामले में सबसे अच्छा भार लोड करेगा।
  • शब्दावली का आकार मूल बीईआरटी कॉन्फ़िगरेशन के आधार पर चुना गया था, क्योंकि इसका आकार 30,522 था , अगर आपको लगता है कि आपके डेटासेट की भाषा में एक बड़ी शब्दावली है, या आप इसके साथ प्रयोग कर सकते हैं, तो इसे बढ़ाने के लिए स्वतंत्र महसूस करें।
  • यदि आप पर सेट truncate_longer_samplesकरते हैं False, तो कोड मानता है कि आपके पास एक वाक्य (यानी पंक्ति) पर बड़ा टेक्स्ट है, आप देखेंगे कि इसे संसाधित करने में अधिक समय लगता है, खासकर यदि आप विधि batch_sizeपर एक बड़ा सेट करते हैं map()। यह प्रक्रिया घंटे का एक बहुत लेता है, तो आप या तो सेट कर सकते हैं truncate_longer_samplesकरने के लिए Trueताकि आप वाक्य है कि से अधिक काट-छांट max_lengthटोकन या आप उपयोग कर संसाधित करने के बाद डाटासेट बचा सकता है save_to_disk()विधि, ताकि आप इसे एक बार संसाधित करने और कई बार इसे लोड।

यदि आप पाठ वर्गीकरण जैसे डाउनस्ट्रीम कार्य के लिए BERT को ठीक करने में रुचि रखते हैं, तो यह ट्यूटोरियल आपको इसके माध्यम से मार्गदर्शन करता है।

#python

Khaitan

Khaitan

1633624080

पायथन में ओपनसीवी का उपयोग करके आयु का पता लगाना

पायथन में ओपनसीवी लाइब्रेरी का उपयोग करके किसी के सामने के चेहरे की तस्वीर से किसी की उम्र का अनुमान लगाना सीखें

हाल ही में, कंप्यूटर विज़न के क्षेत्र में व्यापक ध्यान बढ़ा है , विशेष रूप से चेहरे की पहचान, पहचान और चेहरे के स्थलों के स्थानीयकरण में। कई महत्वपूर्ण विशेषताएं सीधे मानव चेहरे से प्राप्त की जा सकती हैं, जैसे कि उम्र, लिंग और भावनाएं।

आयु अनुमान को चेहरे की छवि को सटीक आयु या किसी विशिष्ट आयु सीमा में वर्गीकृत करने की स्वचालित प्रक्रिया के रूप में परिभाषित किया जा सकता है। मूल रूप से, चेहरे से उम्र का अनुमान अभी भी एक चुनौतीपूर्ण समस्या है, और मेकअप, प्रकाश व्यवस्था, अवरोधों और चेहरे के भाव जैसे कारकों के कारण एक ही छवि से सटीक उम्र का अनुमान लगाना बहुत मुश्किल है।

Android पर "AgeBot" की तरह कई चैनलों भर में कई सर्वव्यापक अनुप्रयोगों प्रसार से प्रेरित होकर, "आयु कैलक्यूलेटर" iPhone पर, हम का उपयोग कर एक सरल उम्र आकलनकर्ता निर्माण करने जा रहे OpenCV अजगर में। 

इस ट्यूटोरियल का प्राथमिक लक्ष्य पायथन-आधारित मॉड्यूल के माध्यम से एक हल्की कमांड-लाइन-आधारित उपयोगिता विकसित करना है और इसका उद्देश्य एक स्थिर छवि में चेहरों का स्वचालित रूप से पता लगाने के लिए चरणों का वर्णन करना और एक का उपयोग करके धब्बेदार व्यक्तियों की आयु का अनुमान लगाना है। डीप लर्निंग-बेस्ड एज डिटेक्शन मॉडल।

निम्नलिखित घटक खेल में आते हैं:

  • OpenCV : कंप्यूटर विज़न, मशीन लर्निंग और इमेज प्रोसेसिंग के लिए एक ओपन-सोर्स लाइब्रेरी है । ओपनसीवी विभिन्न प्रकार की प्रोग्रामिंग भाषाओं जैसे पायथन, सी ++, जावा का समर्थन करता है और इसका उपयोग सभी प्रकार की छवि और वीडियो विश्लेषण जैसे चेहरे की पहचान और पहचान, फोटो संपादन, ऑप्टिकल चरित्र पहचान, और एक संपूर्ण ढेर के लिए किया जाता है। OpenCV का उपयोग करने से कई लाभ मिलते हैं जिनमें से:
    • OpenCV एक ओपन-सोर्स लाइब्रेरी है और यह मुफ़्त है।
    • OpenCV तेज़ है क्योंकि यह C/C++ में लिखा गया है।
    • OpenCV अधिकांश ऑपरेटिंग सिस्टम जैसे विंडोज, लिनक्स और मैकओएस का समर्थन करता है।
      सुझाव: अधिक OpenCV उपयोग के मामलों के लिए हमारे कंप्यूटर विज़न ट्यूटोरियल देखें
  • filetype : फ़ाइल और MIME प्रकारों का अनुमान लगाने के लिए एक छोटा और निर्भरता मुक्त पायथन पैकेज है।

इस लेख के प्रयोजन के लिए, हम पूर्व-प्रशिक्षित कैफ मॉडल का उपयोग करेंगे, एक चेहरा पहचान ट्यूटोरियल से लिए गए चेहरे का पता लगाने के लिए, और दूसरा मॉडल उम्र का पता लगाने के लिए। हमारी परियोजना निर्देशिका में शामिल करने के लिए आवश्यक फाइलों की सूची नीचे दी गई है:

  • age_net.caffemodel: यह आयु का पता लगाने के लिए पूर्व-प्रशिक्षित मॉडल भार है। आप इसे यहां डाउनलोड कर सकते हैं
  • deploy_age.prototxt: उम्र का पता लगाने वाले मॉडल के लिए मॉडल आर्किटेक्चर है (एक सादा पाठ फ़ाइल जिसमें JSON जैसी संरचना होती है जिसमें सभी तंत्रिका नेटवर्क परत की परिभाषाएं होती हैं)। इसे यहाँ प्राप्त करें
  • res10_300x300_ssd_iter_140000_fp16.caffemodel: चेहरे का पता लगाने के लिए पूर्व-प्रशिक्षित मॉडल वजन, यहां डाउनलोड करें
  • deploy.prototxt.txt: यह फेस डिटेक्शन मॉडल के लिए मॉडल आर्किटेक्चर है, यहां डाउनलोड करें

4 आवश्यक फाइलों को डाउनलोड करने के बाद, उन्हें एक फोल्डर में रखें और इसे "वेट्स" कहें :

वजन फ़ोल्डर

आरंभ करने के लिए, आइए OpenCV और NumPy स्थापित करें:

$ pip install opencv-python numpy

एक नई पायथन फ़ाइल खोलें:

# Import Libraries
import cv2
import os
import filetype
import numpy as np

# The model architecture
# download from: https://drive.google.com/open?id=1kiusFljZc9QfcIYdU2s7xrtWHTraHwmW
AGE_MODEL = 'weights/deploy_age.prototxt'
# The model pre-trained weights
# download from: https://drive.google.com/open?id=1kWv0AjxGSN0g31OeJa02eBGM0R_jcjIl
AGE_PROTO = 'weights/age_net.caffemodel'
# Each Caffe Model impose the shape of the input image also image preprocessing is required like mean
# substraction to eliminate the effect of illunination changes
MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
# Represent the 8 age classes of this CNN probability layer
AGE_INTERVALS = ['(0, 2)', '(4, 6)', '(8, 12)', '(15, 20)',
                 '(25, 32)', '(38, 43)', '(48, 53)', '(60, 100)']
# download from: https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt
FACE_PROTO = "weights/deploy.prototxt.txt"
# download from: https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel
FACE_MODEL = "weights/res10_300x300_ssd_iter_140000_fp16.caffemodel"
# Initialize frame size
frame_width = 1280
frame_height = 720
# load face Caffe model
face_net = cv2.dnn.readNetFromCaffe(FACE_PROTO, FACE_MODEL)
# Load age prediction model
age_net = cv2.dnn.readNetFromCaffe(AGE_MODEL, AGE_PROTO)

यहां हमने अपने मॉडल के वजन और वास्तुकला के पथों को आरंभ किया, जिस छवि का आकार हम आकार बदलना चाहते हैं, और अंत में मॉडल लोड करना।

चर AGE_INTERVALSआयु का पता लगाने वाले मॉडल के आयु वर्गों की एक सूची है।

अगला, एक फ़ंक्शन बनाते हैं जो एक छवि को इनपुट के रूप में लेता है, और पहचाने गए चेहरों की एक सूची देता है:

def get_faces(frame, confidence_threshold=0.5):
    """Returns the box coordinates of all detected faces"""
    # convert the frame into a blob to be ready for NN input
    blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), (104, 177.0, 123.0))
    # set the image as input to the NN
    face_net.setInput(blob)
    # perform inference and get predictions
    output = np.squeeze(face_net.forward())
    # initialize the result list
    faces = []
    # Loop over the faces detected
    for i in range(output.shape[0]):
        confidence = output[i, 2]
        if confidence > confidence_threshold:
            box = output[i, 3:7] * np.array([frame_width, frame_height, frame_width, frame_height])
            # convert to integers
            start_x, start_y, end_x, end_y = box.astype(np.int)
            # widen the box a little
            start_x, start_y, end_x, end_y = start_x - \
                10, start_y - 10, end_x + 10, end_y + 10
            start_x = 0 if start_x < 0 else start_x
            start_y = 0 if start_y < 0 else start_y
            end_x = 0 if end_x < 0 else end_x
            end_y = 0 if end_y < 0 else end_y
            # append to our list
            faces.append((start_x, start_y, end_x, end_y))
    return faces

अधिकांश कोड फेस डिटेक्शन ट्यूटोरियल से लिए गए थे , इसे कैसे किया जाता है, इसके बारे में अधिक जानकारी के लिए इसे देखें।

आइए एक उपयोगिता फ़ंक्शन बनाएं जो किसी दिए गए चित्र को प्रदर्शित करता है:

def display_img(title, img):
    """Displays an image on screen and maintains the output until the user presses a key"""
    # Display Image on screen
    cv2.imshow(title, img)
    # Mantain output until user presses a key
    cv2.waitKey(0)
    # Destroy windows when user presses a key
    cv2.destroyAllWindows()

अगला, नीचे दो उपयोगिता कार्य हैं, एक छवि पर टेक्स्ट प्रिंट करते समय उपयुक्त फ़ॉन्ट आकार खोजने के लिए, और दूसरा छवि को गतिशील रूप से आकार देने के लिए:

def get_optimal_font_scale(text, width):
    """Determine the optimal font scale based on the hosting frame width"""
    for scale in reversed(range(0, 60, 1)):
        textSize = cv2.getTextSize(text, fontFace=cv2.FONT_HERSHEY_DUPLEX, fontScale=scale/10, thickness=1)
        new_width = textSize[0][0]
        if (new_width <= width):
            return scale/10
    return 1

# from: https://stackoverflow.com/questions/44650888/resize-an-image-without-distortion-opencv
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
    # initialize the dimensions of the image to be resized and
    # grab the image size
    dim = None
    (h, w) = image.shape[:2]
    # if both the width and height are None, then return the
    # original image
    if width is None and height is None:
        return image
    # check to see if the width is None
    if width is None:
        # calculate the ratio of the height and construct the
        # dimensions
        r = height / float(h)
        dim = (int(w * r), height)
    # otherwise, the height is None
    else:
        # calculate the ratio of the width and construct the
        # dimensions
        r = width / float(w)
        dim = (width, int(h * r))
    # resize the image
    return cv2.resize(image, dim, interpolation = inter)

अब हम जानते हैं कि चेहरों का पता कैसे लगाया जाता है, नीचे दिए गए फ़ंक्शन का पता लगाने वाले प्रत्येक चेहरे की उम्र की भविष्यवाणी करने के लिए जिम्मेदार है:

def predict_age(input_path: str):
    """Predict the age of the faces showing in the image"""
    # Read Input Image
    img = cv2.imread(input_path)
    # Take a copy of the initial image and resize it
    frame = img.copy()
    if frame.shape[1] > frame_width:
        frame = image_resize(frame, width=frame_width)
    faces = get_faces(frame)
    for i, (start_x, start_y, end_x, end_y) in enumerate(faces):
        face_img = frame[start_y: end_y, start_x: end_x]
        # image --> Input image to preprocess before passing it through our dnn for classification.
        blob = cv2.dnn.blobFromImage(
            image=face_img, scalefactor=1.0, size=(227, 227), 
            mean=MODEL_MEAN_VALUES, swapRB=False
        )
        # Predict Age
        age_net.setInput(blob)
        age_preds = age_net.forward()
        print("="*30, f"Face {i+1} Prediction Probabilities", "="*30)
        for i in range(age_preds[0].shape[0]):
            print(f"{AGE_INTERVALS[i]}: {age_preds[0, i]*100:.2f}%")
        i = age_preds[0].argmax()
        age = AGE_INTERVALS[i]
        age_confidence_score = age_preds[0][i]
        # Draw the box
        label = f"Age:{age} - {age_confidence_score*100:.2f}%"
        print(label)
        # get the position where to put the text
        yPos = start_y - 15
        while yPos < 15:
            yPos += 15
        # write the text into the frame
        cv2.putText(frame, label, (start_x, yPos),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), thickness=2)
        # draw the rectangle around the face
        cv2.rectangle(frame, (start_x, start_y), (end_x, end_y), color=(255, 0, 0), thickness=2)
    # Display processed image
    display_img('Age Estimator', frame)
    # save the image if you want
    # cv2.imwrite("predicted_age.jpg", frame)

यहाँ उपरोक्त फ़ंक्शन की पूरी प्रक्रिया है:

  • हम cv2.imread()विधि का उपयोग करके छवि को पढ़ते हैं ।
  • छवि को उपयुक्त आकार में बदलने के बाद, हम get_faces()सभी पहचाने गए चेहरों को प्राप्त करने के लिए अपने फ़ंक्शन का उपयोग करते हैं।
  • हम प्रत्येक चेहरे की छवि पर पुनरावृति करते हैं, हम इसे उम्र की भविष्यवाणी करने के लिए आयु भविष्यवाणी मॉडल के इनपुट के रूप में सेट करते हैं।
  • हम प्रत्येक वर्ग की संभावनाओं को प्रिंट करते हैं, साथ ही साथ प्रमुख भी।
  • छवि पर आयु वाला एक आयत और पाठ खींचा गया है।
  • अंत में, हम अंतिम छवि दिखाते हैं।

cv2.imwrite()नई छवि को सहेजने के लिए आप हमेशा लाइन को अनकम्मेंट कर सकते हैं ।

अब अपना मुख्य कोड लिखते हैं:

if __name__ == '__main__':
    # Parsing command line arguments entered by user
    import sys
    image_path = sys.argv[1]
    predict_age(image_path)

हम उपयोगकर्ता इनपुट प्राप्त करने के लिए केवल पायथन के अंतर्निहित sys मॉड्यूल का उपयोग करते हैं, क्योंकि हमें उपयोगकर्ता से केवल एक तर्क की आवश्यकता होती है और वह है छवि पथ, argparseमॉड्यूल ओवरकिल होगा।

आइए इस स्टॉक फोटो पर कोड का परीक्षण करें :

$ python predict_age.py 3-people.jpg

आउटपुट:

============================== Face 1 Prediction Probabilities ==============================
(0, 2): 0.00%
(4, 6): 0.00%
(8, 12): 31.59%
(15, 20): 0.52%
(25, 32): 52.80%
(38, 43): 14.89%
(48, 53): 0.18%
(60, 100): 0.01%
Age:(25, 32) - 52.80%
============================== Face 2 Prediction Probabilities ==============================
(0, 2): 0.00%
(4, 6): 0.05%
(8, 12): 17.63%
(15, 20): 0.02%
(25, 32): 82.22%
(38, 43): 0.06%
(48, 53): 0.01%
(60, 100): 0.00%
Age:(25, 32) - 82.22%
============================== Face 3 Prediction Probabilities ==============================
(0, 2): 0.05%
(4, 6): 0.03%
(8, 12): 0.07%
(15, 20): 0.00%
(25, 32): 1.05%
(38, 43): 0.96%
(48, 53): 86.54%
(60, 100): 11.31%
Age:(48, 53) - 86.54%

और यह परिणामी छवि है:

पायथन में ओपनसीवी का उपयोग करके आयु की भविष्यवाणी

लपेटें

आयु का पता लगाने वाला मॉडल आयु वर्ग के प्रति अत्यधिक पक्षपाती है [25-32]। इसलिए आप इस उपयोगिता का परीक्षण करते समय इस विसंगति को इंगित कर सकते हैं।

मॉडल को अधिक सटीक बनाने के लिए आप हमेशा कुछ मापदंडों में बदलाव कर सकते हैं। उदाहरण के लिए, get_faces()फ़ंक्शन में, मैंने बॉक्स को सभी तरफ से 10 पिक्सेल तक चौड़ा कर दिया है, आप इसे हमेशा किसी भी मूल्य में बदल सकते हैं जिसके बारे में आपको अच्छा लगता है। बदलना frame_widthऔर frame_heightभविष्यवाणी की सटीकता को परिष्कृत करने का एक तरीका भी है।

यदि आप अपने वेबकैम पर इस मॉडल का उपयोग करना चाहते हैं, तो मैंने यह कोड केवल इसके लिए बनाया है।

पूर्ण कोड संस्करण के लिए यह पृष्ठ देखें ।

#opencv #python 

Khaitan

Khaitan

1633507777

पायथन में वीडियो फ़ाइलों को कैसे संयोजित करें

इस ट्यूटोरियल में, आप सीखेंगे कि मूवीपी लाइब्रेरी की मदद से पायथन का उपयोग करके दो या दो से अधिक वीडियो फ़ाइलों को एक साथ कैसे जोड़ा जाए।

आरंभ करने के लिए, आइए पहले MoviePy को स्थापित करें:

$ pip install moviepy

MoviePy हुड के तहत FFmpeg सॉफ़्टवेयर का उपयोग करता है और जब आप पहली बार MoviePy कोड निष्पादित करते हैं तो इसे इंस्टॉल कर देगा। एक नई पायथन फ़ाइल खोलें और निम्नलिखित कोड लिखें:

def concatenate(video_clip_paths, output_path, method="compose"):
    """Concatenates several video files into one video file
    and save it to `output_path`. Note that extension (mp4, etc.) must be added to `output_path`
    `method` can be either 'compose' or 'reduce':
        `reduce`: Reduce the quality of the video to the lowest quality on the list of `video_clip_paths`.
        `compose`: type help(concatenate_videoclips) for the info"""
    # create VideoFileClip object for each video file
    clips = [VideoFileClip(c) for c in video_clip_paths]
    if method == "reduce":
        # calculate minimum width & height across all clips
        min_height = min([c.h for c in clips])
        min_width = min([c.w for c in clips])
        # resize the videos to the minimum
        clips = [c.resize(newsize=(min_width, min_height)) for c in clips]
        # concatenate the final video
        final_clip = concatenate_videoclips(clips)
    elif method == "compose":
        # concatenate the final video with the compose method provided by moviepy
        final_clip = concatenate_videoclips(clips, method="compose")
    # write the output video file
    final_clip.write_videofile(output_path)

ठीक है, यहाँ कवर करने के लिए बहुत कुछ है। concatenate()हमने जो फ़ंक्शन लिखा है वह वीडियो फ़ाइलों की सूची ( video_clip_paths), आउटपुट वीडियो फ़ाइल पथ और जुड़ने की विधि को स्वीकार करता है ।

सबसे पहले, हम वीडियो फ़ाइलों की सूची पर लूप करते हैं और VideoFileClip()MoviePy से ऑब्जेक्ट का उपयोग करके उन्हें लोड करते हैं । विधि पैरामीटर दो संभावित मान स्वीकार करता है:

  • reduce: यह विधि वीडियो की गुणवत्ता को सूची में निम्नतम स्तर तक कम कर देती है। उदाहरण के लिए, यदि एक वीडियो है 1280x720और दूसरा है 320x240, तो परिणामी फ़ाइल 320x240. इसलिए हम resize()विधि का उपयोग सबसे कम ऊंचाई और चौड़ाई तक करते हैं।
  • compose: MoviePy हमें इस पद्धति का उपयोग करने की सलाह देता है जब विभिन्न गुणों वाले वीडियो पर संयोजन किया जाता है। अंतिम क्लिप में उच्चतम क्लिप की ऊंचाई और सूची की सबसे चौड़ी क्लिप की चौड़ाई होती है। छोटे आयामों वाली सभी क्लिप बीच में दिखाई देंगी।

बेझिझक दोनों का उपयोग करें और देखें कि कौन सा आपके मामले में सबसे अच्छा है।

आइए अब कमांड-लाइन तर्कों को पार्स करने के लिए argparse मॉड्यूल का उपयोग करें :

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(
        description="Simple Video Concatenation script in Python with MoviePy Library")
    parser.add_argument("-c", "--clips", nargs="+",
                        help="List of audio or video clip paths")
    parser.add_argument("-r", "--reduce", action="store_true", 
                        help="Whether to use the `reduce` method to reduce to the lowest quality on the resulting clip")
    parser.add_argument("-o", "--output", help="Output file name")
    args = parser.parse_args()
    clips = args.clips
    output_path = args.output
    reduce = args.reduce
    method = "reduce" if reduce else "compose"
    concatenate(clips, output_path, method)

चूंकि हम वीडियो फ़ाइलों की एक सूची को एक साथ जोड़ने की उम्मीद कर रहे हैं, इसलिए हमें एक या अधिक वीडियो फ़ाइलों को स्वीकार "+"करने nargsके लिए पार्सर को पास करने की आवश्यकता है ।

आइए पास करें --help:

$ python concatenate_video.py --help

आउटपुट:

usage: concatenate_video.py [-h] [-c CLIPS [CLIPS ...]] [-r REDUCE] [-o OUTPUT]

Simple Video Concatenation script in Python with MoviePy Library

optional arguments:
  -h, --help            show this help message and exit
  -c CLIPS [CLIPS ...], --clips CLIPS [CLIPS ...]
                        List of audio or video clip paths
  -r REDUCE, --reduce REDUCE
                        Whether to use the `reduce` method to reduce to the lowest quality on the resulting clip
  -o OUTPUT, --output OUTPUT
                        Output file name

आइए इसका परीक्षण करें:

$ python concatenate_video.py -c zoo.mp4 directed-by-robert.mp4 -o output.mp4

यहां मैं फाइलों के zoo.mp4साथ directed-by-robert.mp4उत्पादन करने के लिए जुड़ रहा हूं output.mp4। ध्यान दें कि आदेश महत्वपूर्ण है, इसलिए आपको उन्हें अपने इच्छित क्रम में पारित करने की आवश्यकता है। आप जितनी चाहें उतनी वीडियो फाइल पास कर सकते हैं। output.mp4मौजूदा निर्देशिका में दिखाई देगा और आप इस के समान उत्पादन देखेंगे:

Moviepy - Building video output.mp4.
MoviePy - Writing audio in outputTEMP_MPY_wvf_snd.mp3
MoviePy - Done.
Moviepy - Writing video output.mp4

Moviepy - Done !
Moviepy - video ready output.mp4

आप reduceनिम्न आदेश के साथ विधि का भी उपयोग कर सकते हैं :

$ python concatenate_video.py -c zoo.mp4 directed-by-robert.mp4 --reduce -o output-reduced.mp4

#python

Khaitan

Khaitan

1633696993

पायथन में पीडीएफ फाइलों को कैसे कंप्रेस करें

पीडीएफट्रॉन एसडीके के रैपर का उपयोग करके पायथन में पीडीएफ फाइलों को संपीड़ित करना सीखें।

पीडीएफ को संपीड़ित करने से आप उस पीडीएफ फाइल में मीडिया की गुणवत्ता को बनाए रखते हुए फ़ाइल का आकार जितना संभव हो उतना छोटा कर सकते हैं। नतीजतन, यह प्रभावशीलता और साझा करने की क्षमता में काफी वृद्धि करता है।

इस ट्यूटोरियल में, आप सीखेंगे कि आप पायथन में पीडीएफट्रॉन लाइब्रेरी का उपयोग करके पीडीएफ फाइलों को कैसे कंप्रेस कर सकते हैं।

PDFNetPython3 PDFTron SDK के लिए एक आवरण है । PDFTron घटकों के साथ आप विश्वसनीय और तेज़ एप्लिकेशन बना सकते हैं जो विभिन्न ऑपरेटिंग सिस्टम में PDF को देख, बना सकते हैं, प्रिंट कर सकते हैं, संपादित कर सकते हैं और एनोटेट कर सकते हैं। डेवलपर PDF विनिर्देशों के सभी प्रकाशित संस्करणों (नवीनतम ISO32000 सहित ) के साथ संगत PDF दस्तावेज़ों को पढ़ने, लिखने और संपादित करने के लिए PDFTron SDK का उपयोग करते हैं ।

PDFTron फ्रीवेयर नहीं है यह 2 प्रकार के लाइसेंस प्रदान करता है जो इस पर निर्भर करता है कि आप बाहरी/वाणिज्यिक उत्पाद विकसित कर रहे हैं या आंतरिक समाधान।

इस ट्यूटोरियल के प्रयोजन के लिए, हम इस SDK के निःशुल्क परीक्षण संस्करण का उपयोग करेंगे। इस ट्यूटोरियल का लक्ष्य पाइथन-आधारित मॉड्यूल के माध्यम से पाइथन पारिस्थितिकी तंत्र (जैसे घोस्टस्क्रिप्ट ) के बाहर बाहरी उपयोगिताओं पर भरोसा किए बिना हल्के कमांड-लाइन-आधारित उपयोगिता को विकसित करना है , ताकि पीडीएफ फाइलों को संपीड़ित किया जा सके।

आरंभ करने के लिए, आइए पाइप का उपयोग करके पायथन रैपर स्थापित करें:

$ pip install PDFNetPython3==8.1.0

एक नई पायथन फ़ाइल खोलें और आवश्यक मॉड्यूल आयात करें:

# Import Libraries
import os
import sys
from PDFNetPython3.PDFNetPython import PDFDoc, Optimizer, SDFDoc, PDFNet

इसके बाद, आइए एक फ़ंक्शन को परिभाषित करें जो फ़ाइल आकार को उपयुक्त प्रारूप में प्रिंट करता है ( इस ट्यूटोरियल से लिया गया ):

def get_size_format(b, factor=1024, suffix="B"):
    """
    Scale bytes to its proper byte format
    e.g:
        1253656 => '1.20MB'
        1253656678 => '1.17GB'
    """
    for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
        if b < factor:
            return f"{b:.2f}{unit}{suffix}"
        b /= factor
    return f"{b:.2f}Y{suffix}"

अब हमारे मुख्य कार्य को परिभाषित करते हैं:

def compress_file(input_file: str, output_file: str):
    """Compress PDF file"""
    if not output_file:
        output_file = input_file
    initial_size = os.path.getsize(input_file)
    try:
        # Initialize the library
        PDFNet.Initialize()
        doc = PDFDoc(input_file)
        # Optimize PDF with the default settings
        doc.InitSecurityHandler()
        # Reduce PDF size by removing redundant information and compressing data streams
        Optimizer.Optimize(doc)
        doc.Save(output_file, SDFDoc.e_linearized)
        doc.Close()
    except Exception as e:
        print("Error compress_file=", e)
        doc.Close()
        return False
    compressed_size = os.path.getsize(output_file)
    ratio = 1 - (compressed_size / initial_size)
    summary = {
        "Input File": input_file, "Initial Size": get_size_format(initial_size),
        "Output File": output_file, f"Compressed Size": get_size_format(compressed_size),
        "Compression Ratio": "{0:.3%}.".format(ratio)
    }
    # Printing Summary
    print("## Summary ########################################################")
    print("\n".join("{}:{}".format(i, j) for i, j in summary.items()))
    print("###################################################################")
    return True

यह फ़ंक्शन अनावश्यक जानकारी को हटाकर और डेटा स्ट्रीम को संपीड़ित करके एक पीडीएफ फाइल को संपीड़ित करता है, फिर यह संपीड़न अनुपात और संपीड़न के बाद फ़ाइल के आकार को दिखाते हुए एक सारांश प्रिंट करता है। यह पीडीएफ लेता है input_fileऔर संपीड़ित पीडीएफ का उत्पादन करता है output_file

अब हमारे मुख्य कोड को परिभाषित करते हैं:

if __name__ == "__main__":
    # Parsing command line arguments entered by user
    input_file = sys.argv[1]
    output_file = sys.argv[2]
    compress_file(input_file, output_file)

हम केवल कमांड-लाइन तर्कों से इनपुट और आउटपुट फाइल प्राप्त करते हैं और फिर compress_file()पीडीएफ फाइल को संपीड़ित करने के लिए हमारे परिभाषित फ़ंक्शन का उपयोग करते हैं ।

आइए इसका परीक्षण करें:

$ python pdf_compressor.py bert-paper.pdf bert-paper-min.pdf

निम्नलिखित आउटपुट है:

PDFNet is running in demo mode.
Permission: read     
Permission: optimizer
Permission: write
## Summary ########################################################
Input File:bert-paper.pdf
Initial Size:757.00KB
Output File:bert-paper-min.pdf
Compressed Size:498.33KB
Compression Ratio:34.171%.
###################################################################

जैसा कि आप देख सकते हैं, के 498KBबजाय के आकार के साथ एक नई संपीड़ित पीडीएफ फाइल, इसे देखें 757KB:

संपीड़ित पीडीएफ फाइल

निष्कर्ष

मुझे आशा है कि आपने ट्यूटोरियल का आनंद लिया और यह पीडीएफ कंप्रेसर आपके कार्यों के लिए उपयोगी पाया।

#python

Khaitan

Khaitan

1633509157

पायथन में ऑडियो फाइलों को कैसे संयोजित करें

Python में MoviePy, wave और PyDub लाइब्रेरी का उपयोग करके दो या दो से अधिक ऑडियो फ़ाइलों को जोड़ने के लिए विभिन्न विधियों का अन्वेषण करें।

यदि आप दो या दो से अधिक ऑडियो फाइलों को पायथन के साथ एक में जोड़ना चाहते हैं, तो इस ट्यूटोरियल में, आप मूवीपी , वेव या पाइडब लाइब्रेरी का उपयोग करके पायथन में ऑडियो फाइलों को संयोजित करने के लिए 3 अलग-अलग तरीके सीखेंगे , और आप किसी का भी उपयोग करने के लिए स्वतंत्र हैं उन्हीं में से एक है।

आरंभ करने के लिए, आइए आवश्यक पुस्तकालय स्थापित करें:

$ pip install moviepy pydub tqdm

विधि 1: MoviePy का उपयोग करना

शुरू करने के लिए, हमें अपनी स्क्रिप्ट बनाने के लिए MoviePy आयात करने की आवश्यकता है:

from moviepy.editor import concatenate_audioclips, AudioFileClip

MoviePy एक बहुत ही सरल पुस्तकालय है, और इसमें बहुत अधिक कोड शामिल नहीं है, निम्न फ़ंक्शन मूवीपी लाइब्रेरी के साथ ऑडियो फ़ाइलों की एक सूची में शामिल हो जाता है:

def concatenate_audio_moviepy(audio_clip_paths, output_path):
    """Concatenates several audio files into one audio file using MoviePy
    and save it to `output_path`. Note that extension (mp3, etc.) must be added to `output_path`"""
    clips = [AudioFileClip(c) for c in audio_clip_paths]
    final_clip = concatenate_audioclips(clips)
    final_clip.write_audiofile(output_path)

audio_clip_pathsऑडियो फाइलों को रास्तों की एक सूची है, हम एक दृष्टांत AudioFileClipप्रत्येक ऑडियो क्लिप के लिए वस्तु, और फिर हम का उपयोग concatenate_audioclips()ऑडियो फ़ाइलें गठबंधन करने के लिए MoviePy द्वारा प्रदान की कार्य करते हैं। अंत में, हम write_audiofile()विधि के साथ अंतिम क्लिप लिखते हैं ।

कमांड लाइन तर्कों को पार्स करने के लिए कोड नीचे दिया गया है:

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="Simple Audio file combiner using MoviePy library in Python")
    parser.add_argument("-c", "--clips", nargs="+",
                        help="List of audio clip paths")
    parser.add_argument("-o", "--output", help="The output audio file, extension must be included (such as mp3, etc.)")
    args = parser.parse_args()
    concatenate_audio_moviepy(args.clips, args.output)

नीचे स्क्रिप्ट का उपयोग करने का तरीका बताया गया है:

$ python concatenate_audio_moviepy.py -c zoo.mp3 directed-by-robert.mp3 -o output_moviepy.mp3
MoviePy - Writing audio in output_moviepy.mp3
MoviePy - Done.

व्यक्तिगत रूप से, कुछ ऑडियो फाइलों को पढ़ते समय मूवीपी के साथ मुझे कुछ अजीब त्रुटियां थीं। नतीजतन, मैंने अन्य तरीकों का उपयोग करने का प्रयास किया।

विधि 2: वेव का उपयोग करना

लहर के फायदों में से एक यह है कि यह पायथन मानक पुस्तकालय में है , जिसका अर्थ है कि हमें पाइप के साथ कुछ भी स्थापित करने की आवश्यकता नहीं है । निम्न फ़ंक्शन दो या दो से अधिक wavऑडियो फ़ाइलों को एक में जोड़ता है :

import wave

def concatenate_audio_wave(audio_clip_paths, output_path):
    """Concatenates several audio files into one audio file using Python's built-in wav module
    and save it to `output_path`. Note that extension (wav) must be added to `output_path`"""
    data = []
    for clip in audio_clip_paths:
        w = wave.open(clip, "rb")
        data.append([w.getparams(), w.readframes(w.getnframes())])
        w.close()
    output = wave.open(output_path, "wb")
    output.setparams(data[0][0])
    for i in range(len(data)):
        output.writeframes(data[i][1])
    output.close()

यह विधि विश्वसनीय और बहुत तेज है। हालाँकि, वेव लाइब्रेरी का नकारात्मक पक्ष यह है कि केवल wavएक्सटेंशन समर्थित है, इसलिए यदि आपकी ऑडियो फ़ाइलें वेव प्रारूप में नहीं हैं, तो तीसरी विधि पर जाएं।

इस स्क्रिप्ट के साथ कमांड-लाइन तर्कों को पार्स करने के लिए विशिष्ट argparse बॉयलरप्लेट कोड नीचे दिया गया है :

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="Simple Audio file combiner using wave module in Python")
    parser.add_argument("-c", "--clips", nargs="+",
                        help="List of audio clip paths")
    parser.add_argument("-o", "--output", help="The output audio file, extension (wav) must be included")
    args = parser.parse_args()
    concatenate_audio_wave(args.clips, args.output)

आप पहले की तरह स्क्रिप्ट को निष्पादित करने के समान प्रारूप का बहुत अधिक उपयोग कर सकते हैं।

विधि 3: PyDub का उपयोग करना

मैं व्यक्तिगत रूप से कई ऑडियो फ़ाइलों को एक में संयोजित करने के लिए इस विधि का उपयोग करता हूं, क्योंकि यह बहुत सारे ऑडियो फ़ाइल एक्सटेंशन का समर्थन करता है और ऑडियो फ़ाइलों को लोड करते समय कोई अजीब त्रुटि उत्पन्न नहीं करता है:

from pydub import AudioSegment
from tqdm import tqdm
import os


def concatenate_audio_pydub(audio_clip_paths, output_path, verbose=1):
    """
    Concatenates two or more audio files into one audio file using PyDub library
    and save it to `output_path`. A lot of extensions are supported, more on PyDub's doc.
    """
    def get_file_extension(filename):
        """A helper function to get a file's extension"""
        return os.path.splitext(filename)[1].lstrip(".")

    clips = []
    # wrap the audio clip paths with tqdm if verbose
    audio_clip_paths = tqdm(audio_clip_paths, "Reading audio file") if verbose else audio_clip_paths
    for clip_path in audio_clip_paths:
        # get extension of the audio file
        extension = get_file_extension(clip_path)
        # load the audio clip and append it to our list
        clip = AudioSegment.from_file(clip_path, extension)
        clips.append(clip)

    final_clip = clips[0]
    range_loop = tqdm(list(range(1, len(clips))), "Concatenating audio") if verbose else range(1, len(clips))
    for i in range_loop:
        # looping on all audio files and concatenating them together
        # ofc order is important
        final_clip = final_clip + clips[i]
    # export the final clip
    final_clip_extension = get_file_extension(output_path)
    if verbose:
        print(f"Exporting resulting audio file to {output_path}")
    final_clip.export(output_path, format=final_clip_extension)

जैसा कि आप देख सकते हैं, यह थोड़ा लंबा है:

  • सबसे पहले, हम पायथन के साथ किसी भी फ़ाइल का एक्सटेंशन प्राप्त करने के लिए एक सहायक फ़ंक्शन लिखते हैं, हम इसका उपयोग ऑडियो फ़ाइल के एक्सटेंशन को स्वचालित रूप से प्राप्त करने के लिए करेंगे ताकि हम इसे PyDub को पास कर सकें।
  • दूसरा, हम ऑडियो फ़ाइलों को उस AudioSegment.from_file()विधि का उपयोग करके लोड करते हैं जो ऑडियो पथ और एक्सटेंशन की अपेक्षा करता है। अगर हम tqdm के साथ फैंसी प्रोग्रेस बार प्रिंट करना चाहते हैं तो हम tqdm के साथ ऑडियो फाइलों की सूची भी लपेटते हैं ।
  • इसके बाद, हम उन ऑडियो फाइलों को जोड़ते हैं जिन्हें हमने अभी साधारण '+'ऑपरेटर के साथ लोड किया है ।
  • अंत में, हम परिणामी ऑडियो फ़ाइल को export()विधि के साथ निर्यात करते हैं और एक्सटेंशन को formatतर्क में पास करते हैं।

आइए कमांड-लाइन तर्कों को पार्स करें:

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="Simple Audio file combiner using PyDub library in Python")
    parser.add_argument("-c", "--clips", nargs="+",
                        help="List of audio clip paths")
    parser.add_argument("-o", "--output", help="The output audio file, extension must be included (such as mp3, etc.)")
    args = parser.parse_args()
    concatenate_audio_pydub(args.clips, args.output)

आइए इसका परीक्षण करें:

usage: concatenate_audio_pydub.py [-h] [-c CLIPS [CLIPS ...]] [-o OUTPUT]

Simple Audio file combiner using PyDub library in Python

optional arguments:
  -h, --help            show this help message and exit
  -c CLIPS [CLIPS ...], --clips CLIPS [CLIPS ...]
                        List of audio clip paths
  -o OUTPUT, --output OUTPUT
                        The output audio file, the extension must be included (such as mp3, etc.)

ठीक है, आइए 2 ऑडियो फाइलों को मिलाएं:

$ python concatenate_audio_pydub.py -c zoo.mp3 directed-by-robert.mp3 -o output_pydub.mp3
Reading audio file: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00,  8.40it/s]
Concatenating audio: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 18.81it/s]
Exporting resulting audio file to output_pydub.mp3

निष्कर्ष

बहुत बढ़िया! इतना ही!

तीसरी विधि में सावधान रहें, जब आप एक ही बार में बहुत सारी ऑडियो फाइलों को मिलाते हैं, तो आपको export()विधि में कुछ देरी का सामना करना पड़ सकता है । यह सामान्य है, लेकिन यदि आप इसे और तेज़ बनाना चाहते हैं, तो सुनिश्चित करें कि आप अपनी ऑडियो फ़ाइलों को एक बार में शामिल न करें।

#python