تخفیف تابستانی تا 35 درصد روی تمام دوره ها
روز
ساعت
دقیقه
ثانیه

شبکه‌های عصبی گراف (GNN) چیست؟

GNN
آنچه می خوانید:

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

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

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

شبکه‌های عصبی گراف (GNN)

 

معماری‌های GNN

شبکه‌های عصبی گراف را می‌توان به روش‌های مختلفی ساخت که تفاوت آن‌ها در نحوه تجمیع اطلاعات و به‌روزرسانی بازنمایی گره‌ها است. یکی از رایج‌ترین معماری‌های مورد استفاده، شبکه عصبی کانولوشن گراف (GCN) است که ایده کانولوشن CNN را از تصاویر به داده‌هایی با ساختار گراف تعمیم می‌دهد.

شبکه عصبی کانولوشن گراف (GCN)

یک GCN پایه برای دسته‌بندی گراف معمولاً شامل سه لایه اصلی است:

  • لایه کانولوشن (Convolutional Layer): ویژگی‌ها را از همسایگان هر گره تجمیع می‌کند.
  • لایه فعال‌ساز (Activation Layer): یک تابع غیرخطی مانند ReLU را اعمال می‌کند.
  • لایه خروجی (Output Layer): پیش‌بینی نهایی را برای گراف تولید می‌کند.

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

شبکه‌های عصبی انتقال پیام (MPNNs)

مدل‌های MPNN با پشتیبانی هم‌زمان از ویژگی‌های گره و یال، این محدودیت‌ها را برطرف می‌کنند. در هر تکرار:

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

مدل‌های MPNN بازنمایی‌های غنی‌تری ارائه می‌دهند و از دسته‌بندی گره، دسته‌بندی یال و پیش‌بینی لینک پشتیبانی می‌کنند که باعث می‌شود نسبت به GCNهای پایه، انعطاف‌پذیرتر و گویا‌تر باشند.

مدل‌های GCN و MPNN نشان‌دهنده دو روش اصلی برای پردازش داده‌های گرافیکی هستند و در کنار هم معماری‌های شبکه عصبی GNN را تشکیل می‌دهند.

 

شبکه عصبی GNN چگونه کار می‌کند؟

شبکه‌های عصبی گراف با اجازه دادن به گره‌ها برای به اشتراک‌گذاری اطلاعات با همسایگان خود از طریق فرآیندی به نام «انتقال پیام» (message passing) عمل می‌کنند. از آنجایی که گراف‌ها ساختاری نامنظم و غیرساختاریافته دارند، شبکه‌های عصبی GNN این داده‌ها را به گونه‌ای سازماندهی می‌کنند که مدل‌های یادگیری عمیق بتوانند الگوهای معنادار را از آن‌ها استخراج کنند.

  1. مقداردهی اولیه (Initialization): هر گره با یک بردار ویژگی شروع می‌شود که ویژگی‌های آن را توصیف می‌کند؛ مانند مشخصات کاربر یا ویژگی‌های یک اتم.
  2. انتقال پیام (Message Passing): گره‌ها اطلاعات خود را در طول لایه‌ها با همسایگانشان به اشتراک می‌گذارند، که این کار به هر گره اجازه می‌دهد بافت و زمینه را از ساختار گراف اطراف خود یاد بگیرد.
  3. به‌روزرسانی (Update): پس از تجمیع اطلاعات، گره‌ها بردار ویژگی خود را با استفاده از یک لایه شبکه عصبی به‌روزرسانی می‌کنند.

شبکه‌های عصبی GNN از عملیات اسپارس (تراکم کم) استفاده می‌کنند و معمولاً تنها به چند لایه نیاز دارند، که این امر آن‌ها را برای داده‌های رابطه‌ای و متصل‌به‌هم بسیار کارآمد می‌کند.

 

انواع شبکه‌های عصبی گراف

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

۱. شبکه‌های عصبی کانولوشن گراف (GCN)

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

شبکه‌های عصبی کانولوشن گراف (GCN)

۲. شبکه‌های توجه گراف (GAT)

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

۳. شبکه‌های بازگشتی گراف (GRN)

  • ساختارهای گراف را با مفاهیم شبکه عصبی بازگشتی ترکیب می‌کنند.
  • برای مدیریت داده‌های گرافی زمانی یا در حال تکامل طراحی شده‌اند.
  • حالات پنهان (Hidden States) را برای ردیابی تغییرات در طول زمان حفظ کرده و به‌روزرسانی می‌کنند.
  • برای گراف‌های پویا مانند جریان ترافیک، الگوهای ارتباطی یا تعاملات اجتماعی مناسب هستند.

۴. شبکه‌های GNN مبتنی بر فضا (Spatial-based)

  • مستقیماً روی توپولوژی گراف در حوزه فضایی عمل می‌کنند.
  • پیام‌ها را بر اساس همسایگی فیزیکی یا ساختاری هر گره منتقل می‌کنند.
  • برای گراف‌های بزرگ و دنیای واقعی، بصری و کارآمد هستند.

۵. شبکه‌های GNN مبتنی بر طیف (Spectral-based)

  • از تئوری گراف طیفی و تبدیل فوریه گراف برای کانولوشن استفاده می‌کنند.
  • ویژگی‌های سراسری و مبتنی بر فرکانس گراف را استخراج می‌کنند.
  • اغلب در وظایف یادگیری گراف ریاضیاتی یا بسیار ساختاریافته استفاده می‌شوند.

 

پیاده‌سازی گام‌به‌گام

گام ۱: وارد کردن کتابخانه‌ها

ما کتابخانه‌های pytorch، scikit learn، matplotlib و numpy را وارد خواهیم کرد.

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

from torch_geometric.datasets import TUDataset
from torch_geometric.data import DataLoader
import torch_geometric.nn as pyg_nn
import torch_geometric.transforms as T
import torch_geometric.utils as pyg_utils

from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
import networkx as nx
import numpy as np

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print("Using device:", device)

خروجی:

Device: cuda

گام ۲: بارگذاری مجموعه داده MUTAG

  • استفاده از TUDataset که شامل تعداد زیادی گراف کوچک است.
  • بر زدن (Shuffle) و تقسیم داده‌ها به ۸۰٪ برای آموزش و ۲۰٪ برای تست.
  • استفاده از NormalizeFeatures برای مقیاس‌بندی ویژگی‌های گره‌ها.
  • loader_train و loader_test دسته‌هایی (batches) از گراف‌ها را تولید می‌کنند.
dataset = TUDataset(root='data/TUDataset', name='MUTAG', use_node_attr=False, transform=T.NormalizeFeatures())

dataset = dataset.shuffle()
n = len(dataset)
n_train = int(0.8 * n)
train_dataset = dataset[:n_train]
test_dataset = dataset[n_train:]

print(f"Loaded MUTAG. Total graphs: {len(dataset)} | Train: {len(train_dataset)} | Test: {len(test_dataset)}")

loader_train = DataLoader(train_dataset, batch_size=64, shuffle=True)
loader_test = DataLoader(test_dataset, batch_size=64, shuffle=False)

گام ۳: تعریف مدل GNN

  • GINConv یک تجمیع‌کننده گراف کاربردی برای وظایف دسته‌بندی گراف است.
  • num_layers عمق فرآیند انتقال پیام را کنترل می‌کند.
  • global_mean_pool ویژگی‌های گره‌ها را برای رسیدن به بازنمایی کل گراف تجمیع (pool) می‌کند.
  • post_mp یک شبکه MLP است که بازنمایی تجمیع‌شده را به لاجیت‌های کلاس تبدیل می‌کند.
  • تابع loss() خطای NLL را باز می‌گرداند که انتظار ورودی‌های F.log_softmax را دارد.
class GNNStack(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim, num_layers=3, dropout=0.25):
        super(GNNStack, self).__init__()
        self.num_layers = num_layers
        self.dropout = dropou
        self.convs = nn.ModuleList()
        self.convs.append(pyg_nn.GINConv(nn.Sequential(
            nn.Linear(input_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim)
        )))
        for _ in range(1, num_layers):
            self.convs.append(pyg_nn.GINConv(nn.Sequential(
                nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim)
            )))
        self.lns = nn.ModuleList([nn.LayerNorm(hidden_dim) for _ in range(num_layers - 1)])

        self.post_mp = nn.Sequential(
            nn.Linear(hidden_dim, hidden_dim),
            nn.ReLU(),
            nn.Dropout(dropout),
            nn.Linear(hidden_dim, output_dim)
        )

    def forward(self, data):
        x, edge_index, batch = data.x, data.edge_index, data.batch
        if x is None:
            x = torch.ones((data.num_nodes, 1), device=edge_index.device)

        for i, conv in enumerate(self.convs):
            x = conv(x, edge_index)
            if i != self.num_layers - 1:
                x = F.relu(x)
                x = F.dropout(x, p=self.dropout, training=self.training)
                x = self.lns[i](x)

        emb = x  
        g_emb = pyg_nn.global_mean_pool(emb, batch)
        out = self.post_mp(g_emb)
        return emb, F.log_softmax(out, dim=1)

    def loss(self, pred_logprob, label):
        return F.nll_loss(pred_logprob, label)

گام ۴: نمونه‌سازی از مدل و بهینه‌ساز

  • input_dim از ویژگی‌های گره‌های مجموعه داده استفاده می‌کند.
  • انتقال مدل به دستگاه محاسباتی (Device).
  • استفاده از بهینه‌ساز Adam همراه با weight decay کوچک برای منظم‌سازی (Regularization).
input_dim = max(1, dataset.num_node_features)
num_classes = dataset.num_classes

model = GNNStack(input_dim=input_dim, hidden_dim=64, output_dim=num_classes, num_layers=3, dropout=0.25).to(device)
optimizer = optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

print(model)

خروجی:

معماری مدل GNN

گام ۵: توابع کمکی آموزش و ارزیابی

  • train_graph_epoch مدل را برای یک دوره (epoch) روی تمامی دسته‌ها آموزش می‌دهد.
  • ضرب مقدار loss در batch.num_graphs برای تجمع صحیح خطا.
  • eval_graph دقت مدل را روی دسته‌های تست محاسبه می‌کند.
  • توابع انتظار دارند که دسته‌ها به دستگاه محاسباتی منتقل شده باشند.
def train_graph_epoch(loader):
    model.train()
    total_loss = 0.0
    total_graphs = 0
    for batch in loader:
        batch = batch.to(device)
        optimizer.zero_grad()
        emb, pred = model(batch) 
        loss = model.loss(pred, batch.y)
        loss.backward()
        optimizer.step()
        total_loss += loss.item() * batch.num_graphs
        total_graphs += batch.num_graphs
    return total_loss / total_graphs

@torch.no_grad()
def eval_graph(loader):
    model.eval()
    correct = 0
    total = 0
    for batch in loader:
        batch = batch.to(device)
        emb, pred = model(batch)
        pred_label = pred.argmax(dim=1)
        correct += (pred_label == batch.y).sum().item()
        total += batch.num_graphs
    return correct / total

گام ۶: اجرای حلقه آموزش و ثبت معیارها

آموزش برای تعداد مشخصی دوره (num_epochs) و ذخیره لیست‌های خطا و دقت تست.

num_epochs = 100
train_losses = []
test_scores = []

for epoch in range(1, num_epochs + 1):
    loss = train_graph_epoch(loader_train)
    acc = eval_graph(loader_test)
    train_losses.append(loss)
    test_scores.append(acc)
    if epoch % 10 == 0 or epoch == 1:
        print(f"[Graph] Epoch {epoch:03d} | Loss: {loss:.4f} | Test Acc: {acc:.4f}")

گام ۷: ترسیم نمودار خطای آموزش و دقت تست

استفاده از این نمودارها برای بررسی همگرایی و بیش‌برازش (Overfitting).

plt.figure(figsize=(10,4))
plt.subplot(1,2,1)
plt.plot(train_losses, label='Train Loss')
plt.xlabel('Epoch'); plt.ylabel('Loss'); plt.title('Training Loss'); plt.grid(True); plt.legend()

plt.subplot(1,2,2)
plt.plot(test_scores, label='Test Accuracy')
plt.xlabel('Epoch'); plt.ylabel('Accuracy'); plt.title('Test Accuracy'); plt.grid(True); plt.legend()

plt.tight_layout()
plt.show()

خروجی:

خطای آموزش و دقت تست

گام ۸: استخراج ویژگی‌های گراف و بصری‌سازی t-SNE

  • اجرای مدل روی تمامی گراف‌ها و تجمیع ویژگی‌های گره‌ها برای به دست آوردن بازنمایی در سطح گراف.
  • اعمال t-SNE برای کاهش ابعاد به دو بعدی و رسم نمودار پراکندگی رنگی بر اساس کلاس‌ها.
  • خوشه‌ها نشان‌دهنده میزان جدایی‌پذیری بازنمایی‌های یادگرفته شده از گراف هستند.
@torch.no_grad()
def get_graph_embeddings_and_labels():
    model.eval()
    all_embs = []
    all_labels = []
    loader = DataLoader(dataset, batch_size=64, shuffle=False)
    for batch in loader:
        batch = batch.to(device)
        emb, pred = model(batch)   
        g_emb = pyg_nn.global_mean_pool(emb, batch.batch)
        all_embs.append(g_emb.cpu())
        all_labels.append(batch.y.cpu())
    embs = torch.cat(all_embs, dim=0).numpy()
    labels = torch.cat(all_labels, dim=0).numpy()
    return embs, labels

embs, labels = get_graph_embeddings_and_labels()
print("Embeddings shape:", embs.shape, "Labels shape:", labels.shape)

tsne = TSNE(n_components=2, random_state=42, perplexity=20)
emb2 = tsne.fit_transform(embs)

plt.figure(figsize=(7,6))
scatter = plt.scatter(emb2[:,0], emb2[:,1], c=labels, cmap='tab10', s=40)
plt.legend(*scatter.legend_elements(), title="Classes")
plt.title('t-SNE of learned graph embeddings')
plt.show()

خروجی:

t-SNE

 

کاربردهای GNN

  • تحلیل شبکه‌های اجتماعی: برای پیش‌بینی رفتار کاربران، شناسایی جوامع (جامعه‌یابی)، پیشنهاد دوستان و مدل‌سازی تأثیرگذاری استفاده می‌شود.
  • شیمی مولکولی و کشف دارو: با در نظر گرفتن مولکول‌ها به عنوان گراف، به پیش‌بینی ویژگی‌های مولکولی، تعاملات هدف-دارو و ساختار پروتئین کمک می‌کند.
  • تکمیل گراف دانش: برای استنتاج روابط مفقود (یافت‌نشده) میان موجودیت‌ها در پایگاه‌های دانش بزرگ به کار می‌رود.
  • سیستم‌های توصیه‌گر: تعاملات میان کاربر و آیتم را به صورت گراف مدل‌سازی می‌کند تا توصیه‌های دقیق‌تری ارائه دهد.
  • شبکه‌های ترافیکی و حمل‌ونقل: با استفاده از داده‌های گراف پویا، جریان ترافیک، الگوهای تراکم و بهینه‌سازی مسیرها را پیش‌بینی می‌کند.

 

مزایای GNN

  • سازگاری با داده‌های نامنظم: به‌طور طبیعی با ساختارهای غیر‌اقلیدسی مانند شبکه‌های اجتماعی و مولکول‌ها کار می‌کند.
  • یادگیری روابط میان گره‌ها: اطلاعات همسایگان را برای ساختن جاسازی‌های (embeddings) معنادار گره تجمیع می‌کند.
  • مقیاس‌پذیری در ابعاد مختلف گراف: بدون نیاز به تغییر در مدل، روی گراف‌های کوچک و بزرگ کار می‌کند.
  • انعطاف‌پذیری در پیش‌بینی: از وظایف پیش‌بینی در سطح گره، سطح یال و کل گراف پشتیبانی می‌کند.
  • کارایی بالا در یادگیری نیمه‌نظارتی: حتی زمانی که تنها تعداد کمی از گره‌ها دارای برچسب هستند، عملکرد خوبی ارائه می‌دهد.

 

محدودیت‌های شبکه‌های عصبی گراف

  • هزینه محاسباتی بالا: گراف‌های بزرگ به حافظه و قدرت پردازش قابل‌توجهی نیاز دارند.
  • مشکل بیش‌هموارسازی (Over-Smoothing): هنگامی که تعداد لایه‌های GNN انباشته‌شده خیلی زیاد شود، ویژگی‌های گره‌ها غیرقابل‌تشخیص می‌شوند.
  • چالش‌های مقیاس‌پذیری: آموزش روی گراف‌های بسیار بزرگ یا پویا بدون استفاده از تکنیک‌های تخصصی دشوار است.
  • وابستگی به کیفیت گراف: ساختار ضعیف یا نویزدار گراف می‌تواند منجر به یادگیری نادرست شود.
  • مدل‌سازی وابستگی‌های طولانی‌مدت: GNNهای استاندارد بدون استفاده از معماری‌های عمیق‌تر، برای ثبت روابط میان گره‌های بسیار دور با مشکل مواجه می‌شوند.

 

سوالات متداول

۱. شبکه عصبی گراف (GNN) چیست؟

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

۲. تفاوت اصلی بین معماری‌های GCN و GAT چیست؟

مدل GCN ویژگی‌های همسایگان یک گره را به طور یکنواخت یا بر اساس فرمول‌های ثابت ریاضی تجمیع می‌کند، در حالی که مدل GAT با استفاده از مکانیسم توجه (Attention)، وزن‌های پویایی را بر اساس میزان اهمیت به گره‌های همسایه اختصاص می‌دهد.

۳. مشکل بیش‌هموارسازی (Over-Smoothing) در شبکه‌های عصبی گراف چیست؟

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

۴. چرا GNNها در حوزه کشف دارو و شیمی مولکولی محبوب هستند؟

زیرا مولکول‌ها به طور طبیعی ساختاری غیر‌اقلیدسی و گرافی دارند که در آن اتم‌ها نقش گره‌ها و پیوندهای شیمیایی نقش یال‌ها را ایفا می‌کنند؛ GNNها به بهترین شکل می‌توانند این ویژگی‌های ساختاری را برای پیش‌بینی خواص مولکولی مدل‌سازی کنند.

 

مسیر تخصص شما از اینجا آغاز می‌شود

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

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

  • تسلط کامل بر پایتون و کتابخانه‌های تخصصی برای پیاده‌سازی پیشرفته‌ترین معماری‌های Deep Learning.
  • آموزش پروژه‌محور پردازش تصویر و مدل‌های زبانی بزرگ (LLMs) جهت ورود مقتدرانه به بازار کار بین‌المللی.
  • درک عمیق ریاضیات و منطق پشت الگوریتم‌ها برای حل چالش‌های پیچیده‌ای همچون بهینه‌سازی مدل‌های گرافی.
  • ساخت یک پورتفولیوی حرفه‌ای از پروژه‌های واقعی هوش مصنوعی که تفاوت شما را با دیگران رقم می‌زند.
مقالات هوش مصنوعی
دوره جامع

هوش مصنوعی

دوره جامع نخبگان پایتون
دوره جامع متخصص علم داده
دوره جامع بینایی کامپیوتر و پردازش تصویر
دوره جامع مدل زبانی بزرگ و پردازش زبان طبیعی
قیمت اصلی: ۵۸,۰۰۰,۰۰۰ تومان بود.قیمت فعلی: ۳۷,۷۰۰,۰۰۰ تومان.
مقالات مشابه
نظرات

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *