මෙයGATV2 ක්රියාකරුගේ PyTorch ක්රියාත්මක කිරීමකි ප්රස්ථාර අවධානය යොමු කරන ජාලයන් කෙතරම් අවධානයෙන් සිටිනවාද? .
GATV2s GATහා සමාන ප්රස්තාර දත්ත මත ක්රියා කරයි. ප්රස්ථාරයක් නෝඩ් සහ දාර සම්බන්ධ කරන නෝඩ් වලින් සමන්විත වේ. උදාහරණයක් ලෙස, කෝරා දත්ත කට්ටලයේ නෝඩ් පර්යේෂණ පත්රිකා වන අතර දාර යනු පත්රිකා සම්බන්ධ කරන උපුටා දැක්වීම් වේ.
GATV2ක්රියාකරු සම්මත GAT හිස්ථිතික අවධානය යොමු කිරීමේ ගැටළුව විසඳයි. ස්ථිතික අවධානය යනු යතුරු නෝඩ් වෙත අවධානය යොමු කිරීම ඕනෑම විමසුම් නෝඩයක් සඳහා එකම ශ්රේණියක් (ඇණවුමක්) ඇති විටය. ගැට් විමසුම node එකක් මතම ඊට අදාල සිට ප්රධාන node එකක් මතම ඊට අදාල අවධානය ගණනය
ඕනෑමවිමසුම් නෝඩයක් සඳහා , යතුරු වල අවධානය ශ්රේණිය () මත පමණක් රඳා පවතින බව සලකන්න . එබැවින් සියලු විමසුම් සඳහා යතුරු වල අවධානය යොමු කිරීම එකම (ස්ථිතික) පවතී.
GATV2අවධානය යොමු කිරීමේ යාන්ත්රණය වෙනස් කිරීමෙන් ගතික අවධානයට ඉඩ දෙයි,
කෘතිමශබ්ද කෝෂ බැලීමේ දත්ත කට්ටලයක් සමඟ සමහර ප්රස්ථාර ගැටළු වලට GATs ස්ථිතික අවධානය යොමු කිරීමේ යාන්ත්රණය අසමත් වන බව පත්රිකාව පෙන්වයි. එය සම්පූර්ණ සම්බන්ධිත ද්විපාර්ශවීය ප්රස්ථාරයක් වන අතර එහිදී එක් නෝඩ් කට්ටලයක් (විමසුම් නෝඩ්) එයට සම්බන්ධ යතුරක් ඇති අතර අනෙක් නෝඩ් කට්ටලයට යතුරක් සහ ඒ හා සම්බන්ධ වටිනාකමක් ඇත. ඉලක්කය වන්නේ විමසුම් නෝඩ් වල අගයන් පුරෝකථනය කිරීමයි. GAT නිසා එහි සීමිත ස්ථිතික අවධානය මෙම කාර්යය සඳහා අසමත්.
කෝරා දත්ත කට්ටලයේ ස්ථර දෙකක GATV2 පුහුණු කිරීම සඳහා පුහුණු කේතය මෙන්න.
59import torch
60from torch import nn
61
62from labml_helpers.module import Module
මෙයතනි ප්රස්ථාර අවධානය v2 ස්ථරයකි. GATV2 එවැනි ස්ථර කිහිපයකින් සෑදී ඇත. ආදාන සහ ප්රතිදානයන් ලෙස කොතැනද , එය අවශ්ය වේ .
65class GraphAttentionV2Layer(Module):
in_features
, , node එකක් මතම ඊට අදාල ආදාන ලක්ෂණ සංඛ්යාව out_features
, , node එකක් මතම ඊට අදාල ප්රතිදානය විශේෂාංග සංඛ්යාව වේ n_heads
, , අවධානය යොමු ප්රධානීන් සංඛ්යාව වේ is_concat
බහු-හිස ප්රති results ල සංයුක්ත කළ යුතුද නැතහොත් සාමාන්යය විය යුතුද යන්න dropout
අතහැර දැමීමේ සම්භාවිතාව leaky_relu_negative_slope
යනු කාන්දු වන රිලූ සක්රිය කිරීම සඳහා negative ණ බෑවුමයි share_weights
සකසා ඇත්නම් True
, සෑම දාරයකම ප්රභවයට සහ ඉලක්කගත නෝඩයට එකම අනුකෘතිය යොදනු ලැබේ78 def __init__(self, in_features: int, out_features: int, n_heads: int,
79 is_concat: bool = True,
80 dropout: float = 0.6,
81 leaky_relu_negative_slope: float = 0.2,
82 share_weights: bool = False):
92 super().__init__()
93
94 self.is_concat = is_concat
95 self.n_heads = n_heads
96 self.share_weights = share_weights
හිසකටමානයන් ගණන ගණනය කරන්න
99 if is_concat:
100 assert out_features % n_heads == 0
අපිබහු හිස් සංකෝචනය කරන්නේ නම්
102 self.n_hidden = out_features // n_heads
103 else:
අපිබහු හිස් සාමාන්යය කරන්නේ නම්
105 self.n_hidden = out_features
ආරම්භකප්රභව පරිවර්තනය සඳහා රේඛීය ස්ථරය; එනම් ස්වයං අවධානයට පෙර ප්රභව නෝඩ් කාවැද්දීම් පරිවර්තනය කිරීම
109 self.linear_l = nn.Linear(in_features, self.n_hidden * n_heads, bias=False)
share_weights
නම් True
ඉලක්කගත නෝඩ් සඳහා එකම රේඛීය ස්ථරය භාවිතා වේ
111 if share_weights:
112 self.linear_r = self.linear_l
113 else:
114 self.linear_r = nn.Linear(in_features, self.n_hidden * n_heads, bias=False)
අවධානයලකුණු ගණනය කිරීම සඳහා රේඛීය ස්ථරය
116 self.attn = nn.Linear(self.n_hidden, 1, bias=False)
අවධානයලකුණු සඳහා සක්රිය
118 self.activation = nn.LeakyReLU(negative_slope=leaky_relu_negative_slope)
අවධානයගණනය කිරීමට සොෆ්ට්මැක්ස්
120 self.softmax = nn.Softmax(dim=1)
අවධානයසඳහා යෙදිය යුතු ස්තරය
122 self.dropout = nn.Dropout(dropout)
h
, හැඩයේ ආදාන නෝඩ් කාවැද්දීම් [n_nodes, in_features]
වේ. adj_mat
යනු හැඩයේ විඝටන අනුකෘතියකි [n_nodes, n_nodes, n_heads]
. එක් එක් හිස සඳහා adjacency එක සමාන [n_nodes, n_nodes, 1]
බැවින් අපි හැඩය භාවිතා කරමු. සමපාත අනුකෘතිය නෝඩ් අතර දාර (හෝ සම්බන්ධතා) නියෝජනය කරයි. adj_mat[i][j]
නෝඩ් සිට නෝඩ් සිට නෝඩ් i
දක්වා දාරයක් තිබේ True
නම් j
. 124 def forward(self, h: torch.Tensor, adj_mat: torch.Tensor):
නෝඩ්ගණන
134 n_nodes = h.shape[0]
එක්එක් හිස සඳහා ආරම්භක පරිවර්තනයන්. අපි රේඛීය පරිවර්තනයන් දෙකක් කර එක් එක් හිස සඳහා එය බෙදන්න.
140 g_l = self.linear_l(h).view(n_nodes, self.n_heads, self.n_hidden)
141 g_r = self.linear_r(h).view(n_nodes, self.n_heads, self.n_hidden)
එක්එක් හිස සඳහා අපි මේවා ගණනය කරමු . සරලබව සඳහා අපි මඟ හරවා ඇත්තෙමු.
අවධානය ලකුණු (වැදගත්කම) node එකක් මතම ඊට අදාල සිට node එකක් මතම ඊට අදාල අපි එක් එක් හිස සඳහා මෙය ගණනය කරමු.
අවධානය යොමු කිරීමේ යාන්ත්රණය, එය අවධානය ලකුණු ගණනය කරයි. කඩදාසි සාරාංශ , a විසින් අනුගමනය කරන අතර බර දෛශිකයක් සමඟ රේඛීය පරිවර්තනයක් සිදු කරයි
සටහන: අප මෙහි භාවිතා කරන අර්ථ දැක්වීමට සමාන වන කඩදාසි අවලංගු කරයි .
පළමුවඅපි සියලු යුගල සඳහා ගණනය කරමු .
g_l_repeat
එක් එක් node එකක් මතම ඊට අදාල කාවැද්දීම නැවත නැවත n_nodes
වතාවක් කොහෙද ලැබෙන.
179 g_l_repeat = g_l.repeat(n_nodes, 1, 1)
g_r_repeat_interleave
එක් එක් node එකක් මතම ඊට අදාල කාවැද්දීම නැවත නැවත n_nodes
වතාවක් කොහෙද ලැබෙන.
184 g_r_repeat_interleave = g_r.repeat_interleave(n_nodes, dim=0)
දැන්අපි ලබා ගැනීම සඳහා ටෙන්සර දෙක එකතු කරමු
192 g_sum = g_l_repeat + g_r_repeat_interleave
ඒනිසා නැවත g_sum[i, j]
හැඩගස්වා
194 g_sum = g_sum.view(n_nodes, n_nodes, self.n_heads, self.n_hidden)
ගණනයහැඩයෙන් e
යුක්ත වේ [n_nodes, n_nodes, n_heads, 1]
202 e = self.attn(self.activation(g_sum))
ප්රමාණයේඅවසාන මානය ඉවත් කරන්න 1
204 e = e.squeeze(-1)
මෙමadjacency න්යාසය හැඩය [n_nodes, n_nodes, n_heads]
හෝ තිබිය යුතුය[n_nodes, n_nodes, 1]
208 assert adj_mat.shape[0] == 1 or adj_mat.shape[0] == n_nodes
209 assert adj_mat.shape[1] == 1 or adj_mat.shape[1] == n_nodes
210 assert adj_mat.shape[2] == 1 or adj_mat.shape[2] == self.n_heads
මැස්සිඅනුකෘතිය මත පදනම් වූ මාස්ක්. සිට දාරයක් නොමැති නම් දක්වා සකසා ඇත.
213 e = e.masked_fill(adj_mat == 0, float('-inf'))
ඉන්පසුඅපි අවධානය යොමු කිරීමේ ලකුණු සාමාන්යකරණය කරමු (හෝ සංගුණක)
සම්බන්ධවූ නෝඩ් කට්ටලය කොහේද?
අපිමෙය කරන්නේ අසම්බන්ධිත යුගල සඳහා සම්බන්ධ නොවූ සැකසීමෙනි.
223 a = self.softmax(e)
අතහැරදැමීමේ විධිමත් කිරීම යොදන්න
226 a = self.dropout(a)
එක්එක් හිස සඳහා අවසාන ප්රතිදානය ගණනය කරන්න
230 attn_res = torch.einsum('ijh,jhf->ihf', a, g_r)
ප්රධානීන්සංයුක්ත කරන්න
233 if self.is_concat:
235 return attn_res.reshape(n_nodes, self.n_heads * self.n_hidden)
ප්රධානීන්ගේමධ්යන්යය ගන්න
237 else:
239 return attn_res.mean(dim=1)