Bert

نویسنده: محمد صالح علی اکبری

دانشجوی مقطع کارشناسی ارشد

دانشکده: مرکز آموزش الکترونیکی

رشته: مهندسی کامپیوتر گرایش هوش مصنوعی و رباتیک

مدل‌های زبانی

چند سال پیش مربی یک کلاس برنامه و تفکر الگوریتمی بودم. در بین پروژه‌هایی که دانش‌آموزان انجام می‌دادن یک روز یکی از دانش‌آموزان کلاس ایده ساختن محصولی مشابه کورتانا ویندوز پیش اومد.

این دانش‌آموز می‌خواست به کمک مجموعه بزرگی از شرط‌ها شرایط رو برای یک گفت و گو اولیه فراهم کنه.
اگر گفت:«سلام.» برنامه بگه :«سلام چطوری؟» و … . خوب این کار برای یک دانش‌آموز ممکن نبود. حتی برای یک گروه عظیم از کارمندان یک شرکت هم حتی شاید ممکن نباشه. پس اینجا به یک برنامه‌ای نیاز داریم که جملات و گفت و گوها رو بیشتر از یک string خشک و ساده ببینه.

تبدیل کردن به قطعات کوچک تر از جمله و عبارت

برای این که کامپیوتر بتونه برای خودش دیکشنری از معانی و مفاهیم جملات درست کنه درست کردن دیکشنری از کل عبارت‌های ممکن کار سختی هست. در طرف دیگر اگر زبان را از دید بخش‌های کوچک تر از کلمه یعنی حرف ببینیم کامپیوتر به سختی درکی از زبان بدست می‌آورد.

Tokenization

گاهی ممکن است نیاز باشد که درباره کلماتی جدید صحبت به میان بیاد پس به حروف کوچک و تعیین کردن شرط و شروط در مورد حروف داریم ولی اگر فقط حروف باشد پیچیده می‌شود پس کلمات هم باید باشند. از طرفی پسوندهای معنی دار هم جایگاه مهمی در زبان دارند و تعیین کردن شرط برای آن‌ها هم می‌تواند کمک کننده باشد پس با معرفی کردن همه آن‌ها به ماشین شاید به حل مسئله چت بات برسیم.

کلمه دارای پیشوند پیوشند کلمه دارای پسوند پسوند
می‌روم می## خانه‌ام ##ام

به فرایند تبدیل کردن جملات و عبارت‌های متنی به این بخش‌های قابل فهم برای کامپیوتر Tokenization می‌گویند.
روش‌های متفاوتی برای این کار وجود دارد. در مقاله BERT از روش WordPiece Tokenization استفاده شده است.

در این روش، برخلاف روش‌های ساده‌تری مثل جدا کردن جمله بر اساس فاصله‌ها (space) یا استفاده از فهرستی ثابت از کلمات، مدل ابتدا یک واژگان (vocabulary) پایه دارد و سپس سعی می‌کند کلمات جدید را به ترکیبی از قطعات کوچک‌تر که در آن واژگان موجود هستند تبدیل کند.

برای مثال اگر واژه‌ی «playing» در واژگان نباشد، مدل می‌تواند آن را به صورت «play» و «##ing» بنویسد. علامت «##» نشان می‌دهد که بخش دوم در ادامه‌ی بخش قبلی آمده است، نه در ابتدای یک کلمه‌ی جدید.

این ایده از روش‌های مشابهی مانند Byte Pair Encoding (BPE) الهام گرفته است. در روش BPE، پرتکرارترین جفت نویسه‌ها به تدریج ترکیب می‌شوند تا یک واژگان فشرده و کارآمد ساخته شود. WordPiece نیز فرآیندی شبیه دارد، با این تفاوت که به جای تکرار ساده‌ی نویسه‌ها، احتمال وقوع توالی‌ها را در کل داده‌های آموزشی بررسی می‌کند و بر اساس آن تصمیم می‌گیرد چه ترکیب‌هایی باید در واژگان بمانند.

هدف از این روش ایجاد تعادلی بین فهم دقیق واژه‌ها و توانایی برخورد با کلمات ناشناخته است. به این ترتیب مدل می‌تواند هم واژه‌های پرتکرار را به عنوان یک واحد مستقل یاد بگیرد، و هم واژه‌های جدید را از ترکیب قطعات شناخته‌شده بسازد.

به کمک این نوع Tokenization، مدل BERT قادر است با متون بسیار متنوعی روبه‌رو شود و در عین حال معنا و ساختار واژه‌ها را تا حد زیادی حفظ کند. این مرحله یکی از کلیدهای اصلی موفقیت BERT در درک زبان طبیعی به شمار می‌رود.

پیش بینی کلمه بعدی

حالا که تونستیم اجزای زبان موجود در گفت و گو رو برای ماشین تعریف کنیم یک ایده برای ساختن توالی از این اجزا پیش بینی مرحله به مرحله جزئ در این دنباله‌ها است ولی یک مشکل وجود دارد. به این دو عبارت دقت کنید:

«شیر آب چکه می‌کند.»

«شیر تشنه است و آب می‌خواهد.»

این دو جمله در ارتباط با یک مشکل هستند. اگر در ادامه بنویسیم:«راهکار تو برای حل مشکل چیست؟» این ماشین باید برای جمله اول در ارتباط با تعمیر شیر آب صحبت کند و برای جمله دوم در مورد آب رسانی به شیر صحبت کند.

درک معنای پویای کلمات

حال این سؤال پیش می‌آید: چگونه می‌توان به مدل آموخت که یک توکن مانند «شیر» در دو جمله مختلف، معانی کاملاً متفاوتی دارد؟

پاسخ در معماری‌های پیشرفته‌ای نهفته است که از مکانیزم توجه (Attention) استفاده می‌کنند. در این معماری‌ها، هر کلمه نه به صورت مجزا، بلکه در بستر کامل جمله پردازش می‌شود.

وقتی جمله وارد مدل می‌شود، نمایش اولیه هر کلمه (embedding اولیه) ثابت است، اما در حین پردازش، این نمایش‌ها به طور پویا بر اساس همه کلمات موجود در جمله به‌روزرسانی می‌شوند.

مکانیزم توجه چگونه عمل می‌کند؟

هر کلمه در جمله با تمام کلمات دیگر (از جمله خودش) تعامل برقرار می‌کند. مدل به طور خودکار یاد می‌گیرد که برای درک هر کلمه، به کدام کلمات دیگر باید «توجه» بیشتری کند.

  • در جمله «شیر آب چکه می‌کند»:

    • کلمه «شیر» با «آب»، «چکه» و «می‌کند» ارتباط معنایی قوی برقرار می‌کند
    • در نتیجه، نمایش نهایی آن به سمت مفاهیم مرتبط با شیرآلات و لوازم خانگی حرکت می‌کند
  • در جمله «شیر تشنه است و آب می‌خواهد»:

    • کلمه «شیر» با «تشنه»، «آب» و «می‌خواهد» تعامل می‌کند
    • نمایش نهایی آن به موجود زنده، حیوان و طبیعت نزدیک می‌شود

نتیجه این فرآیند چیست؟

پس از گذر از چندین لایه پردازش، هر کلمه یک نمایش زمینه‌ای (Contextualized Representation) پیدا می‌کند. این نمایش نه تنها معنای اصلی کلمه، بلکه نقش و معنای آن در جمله فعلی را نیز در بر می‌گیرد.

به این ترتیب، مدل می‌تواند به طور خودکار ابهام‌زدایی کند و برای یک توالی یکسان از کلمات («راهکار تو برای حل مشکل چیست؟») پاسخ‌های متناسب با زمینه ارائه دهد - بدون نیاز به قواعد دستی یا شرط‌های از پیش تعریف شده.

این توانایی درک پویای زبان، پایه و اساس مدل‌های زبانی مدرن است که می‌توانند گفت‌وگوهای طبیعی و معناداری با انسان برقرار کنند.

شیر با شیر چه فرقی داره؟

در زیر یک کد ارائه می‌کنم که کلمه شیر به همراه چند کلمه دیگر در جملات مختلف را بررسی می‌کند. نمودار آن نکات جالبی دارد.

import torch
import numpy as np
import os
from transformers import AutoTokenizer, AutoModel
from sklearn.manifold import TSNE
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio

# --- بارگذاری مدل و توکنایزر ---
model_path = os.path.abspath("persian_bert_tiny_final_model_large_2")
tokenizer = AutoTokenizer.from_pretrained(model_path, local_files_only=True)
model = AutoModel.from_pretrained(model_path, local_files_only=True)
model.eval()

# --- داده‌های ورودی ---

# لیست کلمات یا جملات نمونه
sentences = [
    "شیر در بیابان گرسنه است.",
    "شیر حیوان وحشی است.",
    "شیر خانه ما چکه می‌کند.",
    "شیر تشنه است و آب نیاز دارد.",
    "شیر خانه ما نشتی دارد.",
    "شیر حیوان درنده‌ای است.",

]
words_to_visualize = ["شیر","آب","حیوان","درنده","شیرالات","چکه"] # تعداد کلمات بیشتر از تعداد جملات


# --- استخراج embeddingها ---
embeddings = []
labels = []

for sent in sentences:
    inputs = tokenizer(sent, return_tensors="pt", truncation=True, max_length=256)
    with torch.no_grad():
        outputs = model(**inputs)
        last_hidden_states = outputs.last_hidden_state  # [1, seq_len, hidden_size]

    tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])
    for word in words_to_visualize:
        word_tokens = tokenizer.tokenize(word)
        if word_tokens and word_tokens[0] in tokens:
            start_idx = tokens.index(word_tokens[0])
            emb = last_hidden_states[0, start_idx].numpy()
            embeddings.append(emb)
            labels.append(f"{word} (in: {sent[:20]}...)")

# --- بررسی وجود داده ---
if len(embeddings) == 0:
    print("No embeddings found!")
else:
    print(f"Found {len(embeddings)} embeddings.")
    embeddings = np.array(embeddings)

    # --- t-SNE ---
    n_samples = len(embeddings)
    if n_samples < 2:
        print("Need at least 2 samples for t-SNE.")
    else:
        perplexity = min(30, n_samples - 1) if n_samples > 1 else 1
        tsne = TSNE(n_components=2, random_state=42, perplexity=perplexity)
        embeddings_2d = tsne.fit_transform(embeddings)

        # --- ساخت نمودار با Plotly ---
        fig = go.Figure()

        # اضافه کردن نقاط
        fig.add_trace(go.Scatter(
            x=embeddings_2d[:, 0],
            y=embeddings_2d[:, 1],
            mode='markers+text',
            text=labels,
            textposition="top center",
            marker=dict(size=10, color='lightblue', line=dict(width=1, color='black')),
            hovertemplate='%{text}<extra></extra>'
        ))

        fig.update_layout(
            title="t-SNE Visualization of BERT Embeddings for Selected Words",
            xaxis_title="t-SNE Component 1",
            yaxis_title="t-SNE Component 2",
            width=900,
            height=700,
            showlegend=False,
            font=dict(size=12),
            plot_bgcolor='white',
            xaxis=dict(showgrid=True, gridcolor='lightgray'),
            yaxis=dict(showgrid=True, gridcolor='lightgray')
        )

        # --- ذخیره به عنوان HTML استاتیک ---
        output_file = "embeddings_tsne.html"
        pio.write_html(fig, file=output_file, full_html=True, include_plotlyjs='cdn')
        print(f"Interactive plot saved to: {os.path.abspath(output_file)}")
شیر (in: شیر در بیابان گرسنه ...)شیر (in: شیر حیوان وحشی است....)حیوان (in: شیر حیوان وحشی است....)شیر (in: شیر خانه ما چکه می‌ک...)چکه (in: شیر خانه ما چکه می‌ک...)شیر (in: شیر تشنه است و آب نی...)آب (in: شیر تشنه است و آب نی...)شیر (in: شیر خانه ما نشتی دار...)شیر (in: شیر حیوان درنده‌ای ا...)حیوان (in: شیر حیوان درنده‌ای ا...)−100−50050100150−150−100−50050100150
t-SNE Visualization of BERT Embeddings for Selected Wordst-SNE Component 1t-SNE Component 2

همان طور که در بالا مشاهده می‌کنید کلمات بالا و چپ مربوط به آب و کلمات پایین و چپ مربوط به جنگل و حیوان است. و کلمه شیر که بین هر دو مشترک است با توجه به جمله در این فضا حرکت کرده و موقعیت‌های متفاوت گرفته.

حافظه و توجه به کدام کلمات؟

همان طور که اشاره شد در مدل‌های زبانی کلمات به کمک معماری که مثل حافظه امکان توجه به توکن‌های گذشته را به مدل می‌داد مدل زبانی می‌توانست با توجه به کلمات گفته شده در گذشته تک کلمه جدید را کشف کند ولی اگر کلمات ابتدایی یک جمله وابسطه به کلمات بعدی همان جمله یا جملات بعد باشد محاسبه آینده دور قبل از شروع این جمله برای مدل‌های زبانی چالش بود. در مدل BERT با توجه کردن به کلمات گذشته (اصطلاحا سمت چپ) و کلمات آینده (اصطلاحا سمت راست) جملات را راحت تر و معنی دار تر می‌نوشت. 

BERT مخفف چیست؟

کلمه BERT مخفف عبارت Bidirectional Encoder Representations from Transformers‌

است. همبن طور که در عنوان مشخص است در این مقاله رمز گذاری که قرار هست اتفاق بیوفتد و توکن ما را به فضای embeding خاص خودش ببرد، دو جهته است. قبل از مدل BERT تمام مدل‌های زبان این مشکل را داشتند. یا تک جهته بودند یا نهایتا از دو سمت جداگانه متن رو بررسی می‌کردند و بعد تحلیل‌های دو جهت را به هم وصل می‌کردند ولی به طور هم زمان هیچ مدلی به کلمات سمت راست و چپ کلمه‌ای که می‌خواست پیش بینی شود توجه نمی‌کرد. در مدل BERT دو مرحله ایجاد کردن. مرحله اول به عنوان پیش آموزش (pre treaning) به شکل عمومی برای تمام وظیفه‌های مختلف NLP مدل به صورت «بدون نظارت» (unsupervised learning) آموزش می‌بینیه بعد برای وظایف تخصصی مثل پرسش و پاسخ، انتخاب این که چه گزینه‌ای از ۴ گزینه جمله ادامه مطلب هست، دسته بندی مطالب و … «تنظیم دقیق» (fine tune) می‌شه. از مزایای این عمل fine tune می‌شه گفت که هم خیلی سریع می‌تونه انجام بشه و هم به منابع سخت افزاری کم تر نیاز داره و هم به نسبت تنظیم یک مدل از پایه به داده‌های کم تری نیاز داره. این طور می‌شه بیان کرد که آموزش از ابتدا مثل اینه که یک انسان رو از نوزادی تا اون وظیفه خاص تربیت کنیم ولی fine tune مثل اینه که یک کسی که یک سری دانش‌های عمومی داره رو استخدام کنیم و با مقدار کمی آموزش تخصصی اون نیرویی که نیاز داریم رو تربیت کنیم.

پیش آموزش pre treaning

این عملیات شامل دو وظیفه، مدل زبانی ماسک شده (masked language model) و پیش بینی عبارت بعدی (Next Sentence Prediction) بود. برای این کار نیاز است از منابع مختلف مثل wikipedia و … کمک گرفت و هر سند به شکل به هم پیوسته در یک فایل txt قرار بگیرد و بین اسناد یک خط فاصله باشد.

مدل زبانی ماسک شده (Masked Language Model - MLM)

در این روش هدف این است که مدل بتواند مفهوم و ارتباط بین کلمات جمله را درک کند، نه این‌که صرفاً ترتیب آن‌ها را حفظ کند. برای این کار، درصدی از کلمات جمله به طور تصادفی با نماد خاصی به نام [MASK] جایگزین می‌شوند.
برای مثال جمله «من امروز به مدرسه رفتم» را در نظر بگیر. اگر کلمه «مدرسه» را پنهان کنیم، مدل باید با توجه به بقیه جمله حدس بزند که در جای خالی چه کلمه‌ای باید باشد. یعنی جمله به شکل «من امروز به [MASK] رفتم» در ورودی مدل قرار می‌گیرد و مدل با استفاده از فهمش از ساختار و معنای زبان، کلمه‌ی گم‌شده را پیش‌بینی می‌کند.

این تمرین باعث می‌شود مدل نه‌تنها معنی هر کلمه را به تنهایی درک کند، بلکه بفهمد هر کلمه چگونه با کلمات قبل و بعد از خودش ارتباط دارد. نکته جذاب‌تر این است که BERT جمله را از هر دو جهت می‌بیند — از راست و از چپ — بنابراین در پیش‌بینی‌اش از تمام اطلاعات جمله بهره می‌گیرد.
این بخش شبیه تمرین پر کردن جای خالی در زبان‌آموزی است؛ با این تفاوت که برای مقیاس میلیاردها جمله انجام می‌شود. حاصل این مرحله، مدلی است که می‌تواند درک عمیقی از معنای زبان داشته باشد و پایه اصلی قدرت BERT نیز همین یادگیری دوطرفه از طریق MLM است.


پیش‌بینی عبارت بعدی (Next Sentence Prediction - NSP)

در کنار یادگیری معنی در سطح کلمه، مدل باید بتواند درک کند دو جمله پشت سر هم با هم ارتباط معنایی دارند یا نه.
برای این آموزش، به مدل جفت‌جملاتی داده می‌شود. در نیمی از موارد جمله دوم واقعاً ادامه جمله اول است، و در نیمی دیگر جمله‌ای تصادفی از متن دیگر جای آن گذاشته می‌شود. مدل باید تشخیص دهد که آیا جمله دوم در ادامه جمله اول آمده یا خیر.

برای مثال:

  • جمله ۱: «امروز هوا بارانی بود.»
  • جمله ۲: «من چترم را با خودم برداشتم.» → این دو جمله به هم مربوط‌اند.
    اما اگر جمله دوم را جایگزین کنیم با:
  • جمله ۲: «کتابخانه تا ساعت ۸ باز است.» → این دو جمله به هم نامرتبط هستند.

با تمرین روی میلیون‌ها جفت جمله، مدل یاد می‌گیرد که پیوند منطقی بین جملات را بشناسد. همین توانایی است که بعداً در وظایفی مثل پاسخ به سؤال، خلاصه‌سازی متن یا تشخیص تداوم گفتگو به کار می‌آید.

به زبان ساده، در حالی که بخش MLM به مدل یاد می‌دهد «کلمه‌ی مناسب جمله چیست»، بخش NSP به آن می‌آموزد «جمله‌ی بعدی مرتبط کدام است».

یک نمونه از ورودی‌های مدل هنگام تمرین دیدن برای عملیات پیش پردازش به شکل زیر است:

[CLS] در | سال | ۱۳۹۹ | پژوهشگران | دانشگاه | تهران | مدل | جدیدی | از | پردازش | زبان | طبیعی | معرفی | کردند | . این | مدل | بر | پایه | معماری | [MASK] | طراحی | شده | و | توانست | در | وظایف | مختلف | مانند | طبقه‌بندی | متن | و | تحلیل | احساسات | عملکرد | چشمگیری | نشان | دهد | . هدف | اصلی | آن | بهبود | [MASK] | مدل‌های | زبانی | در | متون | فارسی | بود | . [SEP] در | مرحله | دوم | پژوهش | ، | تیم | توسعه | تصمیم | گرفت | مدل | را | بر | روی | پیکره‌ای | بزرگ‌تر | شامل | داده‌های | خبری | و | گفت‌وگویی | [MASK] | دهد | . نتایج | اولیه | نشان | داد | که | دقت | مدل | در | تشخیص | نیت | کاربران | حدود | [MASK] | درصد | افزایش | یافته | است | . با | این | حال | برخی | خطاها | هنوز | در | واژه‌های | [MASK] | و | ترکیبات | [MASK] | باقی | مانده | بود | . برای | رفع | این | مشکل | ، | پژوهشگران | از | روش | یادگیری | انتقالی | و | بهینه‌سازی | [MASK] | استفاده | کردند | تا | عملکرد | مدل | در | داده‌های | واقعی | بهتر | شود | . همچنین | در | فاز | نهایی | ، | از | الگوریتم | [MASK] | برای | کاهش | [MASK] | حافظه | و | افزایش | سرعت | آموزش | بهره | گرفته | شد | . این | رویکرد | سبب | شد | تا | کتاب | نسبت | به | داده | خود | سریع‌تر | و | نرم‌افزار | عمل | کند | . [SEP]

سه توکن قرمز (کتاب, داده, نرم‌افزار) همان‌هایی هستند که اشتباه جایگزین شده‌اند.

سه توکن سبز (تهران, مدل, زبان) همان‌هایی‌اند که بدون تغییر باقی مانده‌اند.

همین طور هم که می‌بینین دنباله‌هایی که با توکن [SEP] از هم جدا شدند دو دنباله پشت سر هم بودند و مدل در ازای این پشت سر هم بودن باید بعد از تحلیل توکن [CLS] باید IsNext را پیش بینی کند.

اتمام مرحله پیش‌آموزش و ورود به تنظیم دقیق (Fine-tuning)

پس از اینکه مدل در مرحله پیش‌آموزش (Pre-training) یاد گرفت چگونه کلمات را درک کند و چطور ارتباط بین جمله‌ها را تشخیص دهد، نوبت به مرحله تنظیم دقیق یا همان Fine-tuning می‌رسد. در این مرحله مدل دیگر از صفر شروع نمی‌کند، بلکه دانشی کلی از ساختار زبان به‌دست آورده و آماده است تا با داده‌های خاص‌تر برای یک وظیفه مشخص آموزش ببیند.

برای نمونه، اگر بخواهیم از BERT برای پاسخ به سؤالات (Question Answering) استفاده کنیم، تنها کافی است آن را با مجموعه‌ای از نمونه سؤال و پاسخ‌ها دوباره آموزش دهیم تا توانایی‌اش در این نوع کار تقویت شود. یا اگر هدف ما دسته‌بندی احساسی جملات باشد (مثلاً تشخیص مثبت یا منفی بودن نظر کاربران)، کافی است داده‌هایی شامل جملات و برچسب احساساتشان را در اختیار مدل بگذاریم تا یاد بگیرد از معنای جمله، حالت عاطفی آن را تشخیص دهد.

BERT به دلیل همین ساختار دوه‌مرحله‌ای خود — یعنی یادگیری عمومی در مرحله Pre-training و یادگیری خاص در مرحله Fine-tuning — می‌تواند در وظایف مختلف زبانی با داده‌های اندک عملکردی بسیار قوی داشته باشد. همین ویژگی باعث شد که BERT نقطه عطفی در تاریخ مدل‌های زبانی و مبنایی برای ده‌ها مدل جدید مانند RoBERTa، ALBERT، DistilBERT و غیره شود.

در واقع می‌توان گفت مدل‌های زبانی قبل از BERT مثل شاگردانی بودند که فقط از روی مثال یاد می‌گرفتند، اما BERT شاگردی است که زبان را «می‌فهمد» و بعد از آن می‌تواند در هر زمینه‌ای تخصص پیدا کند — از ترجمه گرفته تا تحلیل احساسات یا درک سؤالات.

📦 نصب و اجرا

کدهای اجرا و تمرین دادن مدل BERT‌ در GitHub قرار دارد ولی دیگه به حالت بایگانی در اومدن و پشتیبانی نمی‌شن اما با همین معماری توسط کتابخانه‌های pytorch و HuggingFace دوباره پیاده سازی شدن. در این بخش طبق این راهنما می‌توانید پیاده سازی مدل پیش پردازش و مصور سازی embeding را انجام دهید.

⚙️ پیش‌نیازها

✅ نسخه‌ی پیشنهادی پایتون

این پروژه در محیط Python 3.12.3 تست و توسعه داده شده است.
نسخه‌های بالاتر (به‌ویژه 3.13 و 3.14) ممکن است با برخی پکیج‌ها مانند torch یا transformers ناسازگار باشند (به‌خصوص در هنگام نصب با pip).

⚠️ توصیه:
اگر از نسخه‌های جدیدتر استفاده می‌کنید و با خطای نصب مواجه شدید، یکی از دو روش زیر را انجام دهید:

روش ۱️⃣: استفاده از نسخه‌ی پیشنهادی پایتون (پیشنهادی‌ترین گزینه)
در لینوکس یا مک:

pyenv install 3.12.3
pyenv local 3.12.3

در ویندوز می‌توانید از python.org نسخه‌ی 3.12.3 را دانلود کنید.

روش ۲️⃣: رفع ناسازگاری در نسخه‌های بالاتر اگر پایتون شما 3.13 یا 3.14 است، قبل از نصب بسته‌ها دستور زیر را اجرا کنید تا نسخه‌ی سازگار PyTorch نصب شود:

pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cpu
pip install transformers==4.46.1

در صورت وجود GPU از آدرس پکیج‌های PyTorch نسخه‌ی مناسب CUDA را انتخاب کنید.


1️⃣ دریافت ریپازیتوری

git clone https://github.com/mohammadsaleh40/bert_hf.git
cd bert_hf

2️⃣ ایجاد محیط مجازی و نصب وابستگی‌ها

python3 -m venv venv
source venv/bin/activate       # در ویندوز: venv\Scripts\activate
pip install --upgrade pip
pip install -r requirements.txt

⚙️ آماده‌سازی داده‌ها الف) دریافت داده‌ی نمونه MirasText

wget https://raw.githubusercontent.com/miras-tech/MirasText/refs/heads/master/MirasText/MirasText_sample.txt -O MirasText_sample.txt

ب) پیش‌پردازش داده‌ها

python prepare_mirastext.py

📄 خروجی: mirastext_preprocessed.txt


ج) افزودن Wikipedia فارسی

  1. دانلود فایل فشرده ویکی‌پدیا فارسی:
    wget https://dumps.wikimedia.org/fawiki/latest/fawiki-latest-pages-articles.xml.bz2
    
  2. استخراج محتوای متنی با WikiExtractor:
    python -m wikiextractor.WikiExtractor fawiki-latest-pages-articles.xml.bz2 -o fawiki-latest-pages-articles
    
  3. اضافه کردن مقالات ویکی‌پدیا به انتهای داده‌ی MirasText:
    python add_wiki_to_preprocessed.py
    

    📄 خروجی نهایی: mirastext_preprocessed.txt شامل MirasText + Wikipedia فارسی — 🧰 ساخت واژگان (اختیاری)

در صورت تمایل می‌توانید واژگان جدید بسازید:

python create_vocab.py

فایل تولیدی نامش باید به vocab.txt تغییر پیدا کند. با دستور زیر آن را تغییر می‌دهیم.

mv persian_bert_tokenizer/wp-vocab.txt persian_bert_tokenizer/vocab.txt

🚀 آموزش مدل BERT فارسی

فایل run_pretraining_hf_v2.py مسئول اجرای آموزش مدل بر پایه‌ی HuggingFace Trainer است. پارامترهای اصلی درون فایل تعریف شده‌اند (مثل اندازه‌ی مدل، توکنایزر، مسیر داده‌ها و غیره).

python run_pretraining_hf_v2.py

📂 خروجی مدل ذخیره می‌شود در مسیر:

persian_bert_tiny_output_large_2/

🔍 بررسی و تست مدل

برای آزمایش مدل آموزش‌دیده، دو روش در دسترس است:

🔹 روش ۱: اجرای مستقیم اسکریپت

python check_model.py

این فایل چند جمله‌ی فارسی را پردازش کرده و با استفاده از t-SNE توزیع بردارهای کلمات را نمایش می‌دهد. —

🔹 روش ۲: استفاده از نوت‌بوک

فایل chek_model.ipynb را با Jupyter باز کنید:

jupyter notebook chek_model.ipynb

در این نوت‌بوک:

مدل از مسیر persian_bert_tiny_final_model_large_2 بارگذاری می‌شود.

چند جمله‌ی فارسی نمونه به مدل داده می‌شود.

و خروجی‌ها (embedding و شباهت‌ها) بررسی می‌شوند.

نسخه‌های از پیش تمرین داده شده

در این لینک می‌تونین با پروژه parsBERT آشنا بشین. نسخه‌های مختلفی از bert روی دیتاست‌های بزرگی از زبان فارسی تمرین داده شده که می‌تونین از اون‌ها استفاده کنین.

کامل کردن کلمه گم شده

مثلا در این لینک می‌تونین جملاتی دارای توکن [MASK] به مدل بدین و خروجی به شما می‌گه چه کلماتی احتمال دارد به جای کلمه گم شده قرار گیرند.

مقاله ترجمه شده

در صورت علاقه به خواندن اصل مقاله BERT در این لینک نسخه ترجمه فارسی اون قرار داره که به کمک ChatGPT ترجمه شده.

منابع

  1. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
  2. ParsBERT
  3. Cortana
  4. WordPiece Tokenization: A BPE Variant
  5. Attention Is All You Need