ہڈ کے نیچے گراف توجہ کے نیٹ ورکس

ماخذ نوڈ: 769288

گراف توجہ کے نیٹ ورکس

گراف نیورل نیٹ ورکس (GNNs) گراف ڈیٹا سے سیکھنے کے لیے معیاری ٹول باکس کے طور پر ابھرے ہیں۔ GNNs مختلف شعبوں میں اعلیٰ اثرات کے مسائل جیسے کہ مواد کی سفارش یا منشیات کی دریافت کے لیے بہتری لانے کے قابل ہیں۔ ڈیٹا کی دیگر اقسام جیسے کہ تصاویر کے برعکس، گراف ڈیٹا سے سیکھنے کے لیے مخصوص طریقوں کی ضرورت ہوتی ہے۔ جیسا کہ بیان کیا گیا ہے۔ مائیکل برونسٹائن:

[..] یہ طریقے گراف پر گزرنے والے پیغام کی کسی شکل پر مبنی ہیں جو مختلف نوڈس کو معلومات کا تبادلہ کرنے کی اجازت دیتا ہے۔

گرافس (نوڈ کی درجہ بندی، لنک کی پیشن گوئی، وغیرہ) پر مخصوص کاموں کو پورا کرنے کے لیے، ایک GNN پرت نام نہاد کے ذریعے نوڈ اور کنارے کی نمائندگی کی گنتی کرتی ہے۔ بار بار چلنے والا پڑوس پھیلاؤ (یا پیغام گزر رہا ہے)۔ اس اصول کے مطابق، ہر گراف نوڈ مقامی گراف کی ساخت کی نمائندگی کرنے کے لیے اپنے پڑوسیوں سے خصوصیات حاصل کرتا ہے اور ان کو جمع کرتا ہے: مختلف قسم کی GNN پرتیں متنوع جمع حکمت عملی انجام دیتی ہیں۔

GNN پرت کی سب سے آسان فارمولیشنز، جیسے کہ Graph Convolutional Networks (GCNs) یا GraphSage، ایک isotropic مجموعے پر عمل درآمد کرتے ہیں، جہاں ہر پڑوسی مرکزی نوڈ کی نمائندگی کو اپ ڈیٹ کرنے کے لیے یکساں طور پر تعاون کرتا ہے۔ اس بلاگ پوسٹ میں گراف اٹینشن نیٹ ورکس (GATs) کے تجزیے کے لیے وقف ایک منی سیریز (2 مضامین) متعارف کرائی گئی ہے، جو بار بار پڑنے والے پڑوس کے پھیلاؤ میں انیسوٹروپی آپریشن کی وضاحت کرتی ہے۔ انیسوٹروپی پیراڈیم سے فائدہ اٹھاتے ہوئے، توجہ کے طریقہ کار سے سیکھنے کی صلاحیت بہتر ہوتی ہے، جو ہر پڑوسی کے تعاون کو مختلف اہمیت دیتا ہے۔

اگر آپ GNNs اور متعلقہ تصورات میں بالکل نئے ہیں، تو میں آپ کو درج ذیل تعارفی مضمون کو پڑھنے کی دعوت دیتا ہوں: گراف نیورل نیٹ ورکس کے بلڈنگ بلاکس کو سمجھنا (انٹرو).

اگر یہ گہرائی میں تعلیمی مواد آپ کے لیے مفید ہے، ہماری AI ریسرچ میلنگ لسٹ کو سبسکرائب کریں۔ جب ہم نیا مواد جاری کرتے ہیں تو متنبہ کیا جائے۔ 

GCN بمقابلہ GAT — ریاضی وارم اپ

یہ وارم اپ ڈیپ گراف لائبریری کے ذریعہ رپورٹ کردہ GAT تفصیلات پر مبنی ہے۔ ویب سائٹ.

GAT پرت کے رویے کو سمجھنے سے پہلے، آئیے GCN پرت کے ذریعے کی گئی جمع کے پیچھے ریاضی کو دوبارہ دیکھیں۔

GCN پرت — جمع کرنے کا فنکشن
  • نوڈ کے ون ہاپ پڑوسیوں کا سیٹ ہے۔ i. اس نوڈ کو ایک سیلف لوپ جوڑ کر پڑوسیوں میں بھی شامل کیا جا سکتا ہے۔
  • گراف کی ساخت کی بنیاد پر ایک نارملائزیشن مستقل ہے، جو ایک آئیسوٹروپک اوسط حساب کی وضاحت کرتا ہے۔
  • σ ایک ایکٹیویشن فنکشن ہے، جو ٹرانسفارمیشن میں غیر لکیری کو متعارف کرواتا ہے۔
  • فیچر ٹرانسفارمیشن کے لیے اختیار کیے گئے سیکھنے کے قابل پیرامیٹرز کا وزن میٹرکس ہے۔

GAT پرت GCN پرت کے بنیادی مجموعے کے فنکشن کو بڑھاتی ہے، توجہ کے گتانک کے ذریعے ہر کنارے کو مختلف اہمیت دیتی ہے۔

GAT پرت کی مساوات
  • مساوات (1) نچلی پرت کے سرایت کی لکیری تبدیلی ہے۔ h_i، اور W اس کا سیکھنے کے قابل وزن میٹرکس ہے۔ یہ تبدیلی ان پٹ خصوصیات کو اعلیٰ سطحی اور گھنے خصوصیات میں تبدیل کرنے کے لیے کافی اظہاری قوت حاصل کرنے میں مدد کرتی ہے۔
  • مساوات (2) دو پڑوسیوں کے درمیان جوڑے کے حساب سے غیر معمولی توجہ کے اسکور کی گنتی کرتا ہے۔ یہاں، یہ سب سے پہلے جوڑتا ہے۔ z دو نوڈس کی سرایت، جہاں || جوڑ کی نشاندہی کرتا ہے۔ پھر، یہ اس طرح کے کنکٹنیشن کا ڈاٹ پروڈکٹ اور سیکھنے کے قابل وزن ویکٹر لیتا ہے۔ a. آخر میں، ڈاٹ پروڈکٹ کے نتیجے پر ایک LeakyReLU لاگو کیا جاتا ہے۔ توجہ کا اسکور پیغام پاس کرنے والے فریم ورک میں پڑوسی نوڈ کی اہمیت کی نشاندہی کرتا ہے۔
  • مساوات (3) ہر نوڈ کے آنے والے کناروں پر توجہ کے اسکور کو معمول پر لانے کے لیے سافٹ میکس کا اطلاق کرتا ہے۔ softmax امکانی تقسیم میں پچھلے مرحلے کے آؤٹ پٹ کو انکوڈ کرتا ہے۔ نتیجے کے طور پر، توجہ کے اسکور مختلف نوڈس میں بہت زیادہ موازنہ ہیں۔
  • مساوات (4) GCN جمع کی طرح ہے (سیکشن کے شروع میں مساوات دیکھیں)۔ پڑوسیوں کی طرف سے سرایت کو ایک ساتھ جمع کیا جاتا ہے، توجہ کے اسکور کے حساب سے اسکیل کیا جاتا ہے۔ اس اسکیلنگ کے عمل کا بنیادی نتیجہ ہر پڑوس کے نوڈ سے مختلف شراکت سیکھنا ہے۔

NumPy نفاذ

پہلا قدم ایک سادہ گراف کی نمائندگی کرنے اور لکیری تبدیلی کو انجام دینے کے لیے اجزاء (میٹریس) کو تیار کرنا ہے۔

NumPy کوڈ

print('nn----- One-hot vector representation of nodes. Shape(n,n)n')
X = np.eye(5, 5)
n = X.shape[0]
np.random.shuffle(X)
print(X) print('nn----- Embedding dimensionn')
emb = 3
print(emb) print('nn----- Weight Matrix. Shape(emb, n)n')
W = np.random.uniform(-np.sqrt(1. / emb), np.sqrt(1. / emb), (emb, n))
print(W) print('nn----- Adjacency Matrix (undirected graph). Shape(n,n)n')
A = np.random.randint(2, size=(n, n))
np.fill_diagonal(A, 1) A = (A + A.T)
A[A > 1] = 1
print(A)

آؤٹ پٹ

----- One-hot vector representation of nodes. Shape(n,n)
[[0 0 1 0 0] # node 1 [0 1 0 0 0] # node 2 [0 0 0 0 1] [1 0 0 0 0] [0 0 0 1 0]]
----- Embedding dimension
3
----- Weight Matrix. Shape(emb, n)
[[-0.4294049 0.57624235 -0.3047382 -0.11941829 -0.12942953] [ 0.19600584 0.5029172 0.3998854 -0.21561317 0.02834577] [-0.06529497 -0.31225734 0.03973776 0.47800217 -0.04941563]]
----- Adjacency Matrix (undirected graph). Shape(n,n)
[[1 1 1 0 1] [1 1 1 1 1] [1 1 1 1 0] [0 1 1 1 1] [1 1 0 1 1]]

پہلا میٹرکس نوڈس کی ایک گرم انکوڈ شدہ نمائندگی کی وضاحت کرتا ہے (نوڈ 1 کو بولڈ میں دکھایا گیا ہے)۔ پھر، ہم ایک ویٹ میٹرکس کی وضاحت کرتے ہیں، متعین ایمبیڈنگ طول و عرض کا استحصال کرتے ہیں۔ میں نے کے تیسرے کالم ویکٹر پر روشنی ڈالی ہے۔ W کیونکہ، جیسا کہ آپ جلد ہی دیکھیں گے، یہ ویکٹر نوڈ 1 کی تازہ ترین نمائندگی کی وضاحت کرتا ہے (ایک 1-قدر تیسری پوزیشن میں شروع کی جاتی ہے)۔ ہم ان اجزاء سے شروع ہونے والی نوڈ خصوصیات کے لیے کافی اظہاری طاقت حاصل کرنے کے لیے لکیری تبدیلی انجام دے سکتے ہیں۔ اس قدم کا مقصد (ایک گرم انکوڈ شدہ) ان پٹ خصوصیات کو کم اور گھنے نمائندگی میں تبدیل کرنا ہے۔

GAT پرت (مساوات 1)

NumPy کوڈ

# equation (1)
print('nn----- Linear Transformation. Shape(n, emb)n')
z1 = X.dot(W.T)
print(z1)

آؤٹ پٹ

----- Linear Transformation. Shape(n, emb) [[-0.3047382 0.3998854 0.03973776] [ 0.57624235 0.5029172 -0.31225734] [-0.12942953 0.02834577 -0.04941563] [-0.4294049 0.19600584 -0.06529497] [-0.11941829 -0.21561317 0.47800217]]

اگلا آپریشن ہر کنارے کے لیے خود توجہ کے گتانک کو متعارف کرانا ہے۔ ہم منبع نوڈ کی نمائندگی اور کناروں کی نمائندگی کرنے کے لئے منزل نوڈ کی نمائندگی کو جوڑتے ہیں۔ یہ کنکٹنیشن عمل ملحقہ میٹرکس کے ذریعے فعال کیا گیا ہے۔ A، جو گراف میں تمام نوڈس کے درمیان تعلقات کی وضاحت کرتا ہے۔

GAT پرت (مساوات 2)

NumPy کوڈ

# equation (2) - First part
print('nn----- Concat hidden features to represent edges. Shape(len(emb.concat(emb)), number of edges)n')
edge_coords = np.where(A==1)
h_src_nodes = z1[edge_coords[0]]
h_dst_nodes = z1[edge_coords[1]]
z2 = np.concatenate((h_src_nodes, h_dst_nodes), axis=1)

آؤٹ پٹ

----- Concat hidden features to represent edges. Shape(len(emb.concat(emb)), number of edges) [[-0.3047382 0.3998854 0.03973776 -0.3047382 0.3998854 0.03973776] [-0.3047382 0.3998854 0.03973776 0.57624235 0.5029172 -0.31225734] [-0.3047382 0.3998854 0.03973776 -0.12942953 0.02834577 -0.04941563] [-0.3047382 0.3998854 0.03973776 -0.11941829 -0.21561317 0.47800217] [ 0.57624235 0.5029172 -0.31225734 -0.3047382 0.3998854 0.03973776] [ 0.57624235 0.5029172 -0.31225734 0.57624235 0.5029172 -0.31225734] [ 0.57624235 0.5029172 -0.31225734 -0.12942953 0.02834577 -0.04941563] [ 0.57624235 0.5029172 -0.31225734 -0.4294049 0.19600584 -0.06529497] [ 0.57624235 0.5029172 -0.31225734 -0.11941829 -0.21561317 0.47800217] [-0.12942953 0.02834577 -0.04941563 -0.3047382 0.3998854 0.03973776] [-0.12942953 0.02834577 -0.04941563 0.57624235 0.5029172 -0.31225734] [-0.12942953 0.02834577 -0.04941563 -0.12942953 0.02834577 -0.04941563] [-0.12942953 0.02834577 -0.04941563 -0.4294049 0.19600584 -0.06529497] [-0.4294049 0.19600584 -0.06529497 0.57624235 0.5029172 -0.31225734] [-0.4294049 0.19600584 -0.06529497 -0.12942953 0.02834577 -0.04941563] [-0.4294049 0.19600584 -0.06529497 -0.4294049 0.19600584 -0.06529497] [-0.4294049 0.19600584 -0.06529497 -0.11941829 -0.21561317 0.47800217] [-0.11941829 -0.21561317 0.47800217 -0.3047382 0.3998854 0.03973776] [-0.11941829 -0.21561317 0.47800217 0.57624235 0.5029172 -0.31225734] [-0.11941829 -0.21561317 0.47800217 -0.4294049 0.19600584 -0.06529497] [-0.11941829 -0.21561317 0.47800217 -0.11941829 -0.21561317 0.47800217]]

پچھلے بلاک میں، میں نے نوڈ 4 سے منسلک 4 ان کناروں کی نمائندگی کرنے والی 1 قطاروں کو نمایاں کیا ہے۔ ہر قطار کے پہلے 3 عناصر نوڈ 1 کے پڑوسیوں کی سرایت کی نمائندگی کی وضاحت کرتے ہیں، جبکہ ہر قطار کے دیگر 3 عناصر کی سرایت کی وضاحت کرتے ہیں۔ نوڈ 1 خود (جیسا کہ آپ دیکھ سکتے ہیں، پہلی قطار سیلف لوپ کو انکوڈ کرتی ہے)۔

اس آپریشن کے بعد، ہم توجہ کے گتانک کو متعارف کروا سکتے ہیں اور کنٹینیشن کے عمل کے نتیجے میں، کنارے کی نمائندگی کے ساتھ ان کو ضرب دے سکتے ہیں۔ آخر میں، Leaky Relu فنکشن اس پروڈکٹ کے آؤٹ پٹ پر لاگو ہوتا ہے۔

NumPy کوڈ

# equation (2) - Second part
print('nn----- Attention coefficients. Shape(1, len(emb.concat(emb)))n')
att = np.random.rand(1, z2.shape[1])
print(att) print('nn----- Edge representations combined with the attention coefficients. Shape(1, number of edges)n')
z2_att = z2.dot(att.T)
print(z2_att) print('nn----- Leaky Relu. Shape(1, number of edges)')
e = leaky_relu(z2_att)
print(e)

آؤٹ پٹ

----- Attention coefficients. Shape(1, len(emb.concat(emb))) [[0.09834683 0.42110763 0.95788953 0.53316528 0.69187711 0.31551563]] ----- Edge representations combined with the attention coefficients. Shape(1, number of edges) [[ 0.30322275] [ 0.73315639] [ 0.11150219] [ 0.11445879] [ 0.09607946] [ 0.52601309] [-0.0956411 ] [-0.14458757] [-0.0926845 ] [ 0.07860653] [ 0.50854017] [-0.11311402] [-0.16206049] [ 0.53443082] [-0.08722337] [-0.13616985] [-0.08426678] [ 0.48206613] [ 0.91199976] [ 0.2413991 ] [ 0.29330217]] ----- Leaky Relu. Shape(1, number of edges)
[[ 3.03222751e-01] [ 7.33156386e-01] [ 1.11502195e-01] [ 1.14458791e-01] [ 9.60794571e-02] [ 5.26013092e-01] [-9.56410988e-04] [-1.44587571e-03] [-9.26845030e-04] [ 7.86065337e-02] [ 5.08540169e-01] [-1.13114022e-03] [-1.62060495e-03] [ 5.34430817e-01] [-8.72233739e-04] [-1.36169846e-03] [-8.42667781e-04] [ 4.82066128e-01] [ 9.11999763e-01] [ 2.41399100e-01] [ 2.93302168e-01]]

اس عمل کے اختتام پر، ہم نے گراف کے ہر کنارے کے لیے ایک مختلف سکور حاصل کیا۔ اوپری بلاک میں، میں نے پہلے کنارے سے وابستہ عدد کے ارتقاء پر روشنی ڈالی ہے۔ پھر، گتانک کو مختلف نوڈس میں آسانی سے موازنہ کرنے کے لیے، ہر منزل کے نوڈ کے لیے تمام پڑوسیوں کے تعاون پر ایک softmax فنکشن لاگو کیا جاتا ہے۔

GAT پرت (مساوات 3)

NumPy کوڈ

# equation (3)
print('nn----- Edge scores as matrix. Shape(n,n)n')
e_matr = np.zeros(A.shape)
e_matr[edge_coords[0], edge_coords[1]] = e.reshape(-1,)
print(e_matr) print('nn----- For each node, normalize the edge (or neighbor) contributions using softmaxn')
alpha0 = softmax(e_matr[:,0][e_matr[:,0] != 0]) alpha1 = softmax(e_matr[:,1][e_matr[:,1] != 0])
alpha2 = softmax(e_matr[:,2][e_matr[:,2] != 0])
alpha3 = softmax(e_matr[:,3][e_matr[:,3] != 0])
alpha4 = softmax(e_matr[:,4][e_matr[:,4] != 0])
alpha = np.concatenate((alpha0, alpha1, alpha2, alpha3, alpha4))
print(alpha) print('nn----- Normalized edge score matrix. Shape(n,n)n')
A_scaled = np.zeros(A.shape)
A_scaled[edge_coords[0], edge_coords[1]] = alpha.reshape(-1,)
print(A_scaled)

آؤٹ پٹ

----- Edge scores as matrix. Shape(n,n) [[ 3.03222751e-01 7.33156386e-01 1.11502195e-01 0.00000000e+00 1.14458791e-01] [ 9.60794571e-02 5.26013092e-01 -9.56410988e-04 -1.44587571e-03 -9.26845030e-04] [ 7.86065337e-02 5.08540169e-01 -1.13114022e-03 -1.62060495e-03 0.00000000e+00] [ 0.00000000e+00 5.34430817e-01 -8.72233739e-04 -1.36169846e-03 -8.42667781e-04] [ 4.82066128e-01 9.11999763e-01 0.00000000e+00 2.41399100e-01 2.93302168e-01]] ----- For each node, normalize the edge (or neighbor) contributions using softmax [0.26263543 0.21349717 0.20979916 0.31406823 0.21610715 0.17567419 0.1726313 0.1771592 0.25842816 0.27167844 0.24278118 0.24273876 0.24280162 0.23393014 0.23388927 0.23394984 0.29823075 0.25138555 0.22399017 0.22400903 0.30061525] ----- Normalized edge score matrix. Shape(n,n) [[0.26263543 0.21349717 0.20979916 0. 0.31406823] [0.21610715 0.17567419 0.1726313 0.1771592 0.25842816] [0.27167844 0.24278118 0.24273876 0.24280162 0. ] [0. 0.23393014 0.23388927 0.23394984 0.29823075] [0.25138555 0.22399017 0. 0.22400903 0.30061525]]

نارملائزڈ ایج اسکورز کی وضاحت کرنے والے آخری میٹرکس کے معنی کی تشریح کرنے کے لیے، آئیے ملحقہ میٹرکس کے مواد کو دوبارہ دیکھیں۔

----- Adjacency Matrix (undirected graph). Shape(n,n) [[1 1 1 0 1] [1 1 1 1 1] [1 1 1 1 0] [0 1 1 1 1] [1 1 0 1 1]]

جیسا کہ آپ دیکھ سکتے ہیں، کناروں کی وضاحت کرنے کے لیے 1 اقدار رکھنے کے بجائے، ہم نے ہر پڑوسی کے تعاون کو دوبارہ بڑھایا۔ آخری مرحلہ پڑوس کے مجموعے کی گنتی کرنا ہے: پڑوسیوں کی طرف سے سرایت کو منزل کے نوڈ میں شامل کیا جاتا ہے، توجہ کے اسکور سے اسکیل کیا جاتا ہے۔

GAT پرت (مساوات 4)

NumPy کوڈ

# equation (4)
print('nnNeighborhood aggregation (GCN) scaled with attention scores (GAT). Shape(n, emb)n')
ND_GAT = A_scaled.dot(z1)
print(ND_GAT)

آؤٹ پٹ

Neighborhood aggregation (GCN) scaled with attention scores (GAT). Shape(n, emb) [[-0.02166863 0.15062515 0.08352843] [-0.09390287 0.15866476 0.05716299] [-0.07856777 0.28521023 -0.09286313] [-0.03154513 0.10583032 0.04267501] [-0.07962369 0.19226439 0.069115 ]]

اگلے مراحل

مستقبل کے مضمون میں، میں ملٹی ہیڈ GAT لیئر کے پیچھے میکانزم کی وضاحت کروں گا، اور ہم لنک پیشین گوئی کے کام کے لیے کچھ ایپلی کیشنز دیکھیں گے۔

حوالہ جات

  • کوڈ کا چل رہا ورژن درج ذیل میں دستیاب ہے۔ نوٹ بک. آپ کو ایک DGL نفاذ بھی ملے گا، جو عمل درآمد کی درستگی کو جانچنے کے لیے مفید ہے۔
  • Petar Veličković، Guillem Cucurull، Arantxa Casanova، Adriana Romero، Pietro Liò، Yoshua Bengiois سے گراف اٹینشن نیٹ ورکس پر اصل کاغذ دستیاب ہے۔ arxiv.
  • موضوع کی گہرائی سے وضاحت کے لیے، میں اس سے ویڈیو بھی تجویز کرتا ہوں۔ الیکسا گورڈیچ.

یہ مضمون اصل میں شائع کیا گیا تھا ڈیٹا سائنس کی طرف اور مصنف کی اجازت سے TOPBOTS پر دوبارہ شائع کیا گیا۔

اس مضمون کا لطف اٹھائیں؟ مزید AI اپ ڈیٹس کے لیے سائن اپ کریں۔

جب ہم مزید تکنیکی تعلیم جاری کریں گے تو ہم آپ کو بتائیں گے۔

ماخذ: https://www.topbots.com/graph-attention-networks-under-the-hood/

ٹائم اسٹیمپ:

سے زیادہ ٹاپ بوٹس