شعار زيفيرنت

الشبكات العصبية القابلة للتفسير باستخدام PyTorch

التاريخ:

By دكتور روبرت كوبلر، عالم البيانات


الشبكات العصبية القابلة للتفسير مع PyTorch
تصوير يان شولز # Webdesigner شتوتغارت on Unsplash

 

هناك عدة طرق لتقييم نماذج التعلم الآلي ، اثنان منها دقة و تفسير. النموذج ذو الدقة العالية هو ما نسميه عادةً بـ خير النموذج ، تعلمت العلاقة بين المدخلات X والنواتج y حسن.

إذا كان للنموذج قابلية عالية للتفسير أو قابلية التفسير ، فإننا نفهم كيف يقوم النموذج بالتنبؤ وكيف يمكننا ذلك تأثير هذا التوقع عن طريق تغيير ميزات الإدخال. في حين أنه من الصعب تحديد كيف يتصرف ناتج شبكة عصبية عميقة عندما نقوم بزيادة أو تقليل ميزة معينة من المدخلات ، فإنه من السهل للغاية بالنسبة للنموذج الخطي: إذا قمت بزيادة الميزة بمقدار واحد ، فإن الناتج يزيد بالمعامل من تلك الميزة. سهل.

الآن ، غالبًا ما سمعت شيئًا كهذا:

"هناك نماذج قابلة للتفسير وهناك نماذج جيدة الأداء." - شخص لا يعرفه أفضل

ومع ذلك ، إذا كنت قد قرأت مقالتي حول آلة التعزيز القابلة للتفسير (EBM) ، فأنت تعلم بالفعل أن هذا ليس صحيحًا. يعتبر EBM مثالاً على نموذج يتمتع بأداء رائع بينما يكون قابلاً للتفسير.

 
آلة التعزيز القابلة للتفسير
 

بالنسبة لمقالتي القديمة ، قمت بإنشاء الشكل التالي الذي يوضح كيف يمكننا وضع بعض النماذج في ملف مساحة دقة التفسير.


الشبكات العصبية القابلة للتفسير مع PyTorch
الصورة من قبل المؤلف.

 

على وجه الخصوص ، لقد وضعت الشبكات العصبية العميقة (مع حذف الامتداد عميق) المزيد في دقيقة للغاية ، ولكن يصعب شرحها منطقة. بالتأكيد ، يمكنك التخفيف من مشكلة القابلية للتفسير إلى حد ما باستخدام مكتبات مثل حالات العسر الشديد or ليمون، ولكن هذه الأساليب تأتي مع مجموعة من الافتراضات والمشاكل الخاصة بهم. لذلك ، دعونا نأخذ مسارًا آخر وننشئ بنية شبكة عصبية يمكن تفسيرها حسب التصميم في هذه المقالة.

تنصل: لقد خطرت في بالي للتو الهندسة المعمارية التي أنا على وشك تقديمها. لا أعرف ما إذا كان هناك أدبيات حول هذا الموضوع بالفعل ، على الأقل لم أجد شيئًا. ولكن إذا كنت تعرف أي ورقة تقوم بما أقوم به هنا ، فيرجى إبلاغي بذلك! سأضعها في المراجع بعد ذلك.

فكرة معمارية قابلة للتفسير

 
يرجى ملاحظة أنني أتوقع أنك تعرف كيف تعمل الشبكات العصبية المغذية. لن أعطي مقدمة كاملة هنا لأن هناك العديد من الموارد الرائعة حول هذا الموضوع بالفعل.

ضع في اعتبارك الشبكة العصبية للألعاب التالية ، التي تحتوي على ثلاث عقد إدخال x₁ ، x₂ ، x₃ ، عقدة إخراج واحدة ŷ، وثلاث طبقات مخفية كل منها ست عقد. لقد حذفت شروط التحيز هنا.


الشبكات العصبية القابلة للتفسير مع PyTorch
الصورة من قبل المؤلف.

 

تكمن مشكلة هذه البنية الخاصة بالقابلية للتفسير في أن جميع المدخلات تختلط تمامًا معًا بسبب الطبقات المتصلة بالكامل. تؤثر كل عقدة إدخال مفردة على جميع عُقد الطبقة المخفية ، ويزداد هذا التأثير تعقيدًا كلما تعمقنا في الشبكة.

إلهام من الأشجار

 
عادة ما يكون هو نفسه بالنسبة للنماذج المستندة إلى الأشجار لأنه من المحتمل أن تستخدم شجرة القرار كل ميزة لإنشاء تقسيم إذا لم نقم بتقييده. على سبيل المثال ، تعزيز التدرج القياسي ومشتقاته مثل XGBoostLightGBMو كاتبووست لا يمكن تفسيرها حقًا من تلقاء نفسها.

ومع ذلك ، يمكنك جعل التدرج اللوني قابلاً للتفسير باستخدام أشجار القرار التي تعتمد فقط على ميزة واحدة، كما حدث مع EBM (اقرأ مقالتي عنها! 😎).

لا يؤدي تقييد الأشجار مثل هذا إلى الإضرار بالأداء كثيرًا في كثير من الحالات ، ولكنه يمكننا من تصور تأثيرات الميزة مثل هذا:


الشبكات العصبية القابلة للتفسير مع PyTorch
إخراج ترجمةوظيفة العرض. الصورة من قبل المؤلف.

 

ما عليك سوى إلقاء نظرة على الجزء العلوي من الرسم ذي الخط الأزرق. يوضح تأثير feature_4 على المخرجات في بعض مشاكل الانحدار. على ال x-المحور ، يمكنك رؤية نطاق feature_4. ال y- يظهر المحور العلامة، وهي القيمة بمقدار تغير الناتج. يوضح لك الرسم البياني أدناه توزيع feature_4.

يمكننا أن نرى ما يلي من الرسم البياني:

  • إذا كانت feature_4 حوالي 0.62 ، فإن الناتج يزيد بحوالي 10 مقارنةً بالميزة feature_4 التي تكون 0.6 أو 0.65.
  • إذا كانت feature_4 أكبر من 0.66 ، فإن التأثير على الناتج يكون سالبًا.
  • يؤدي تغيير feature_4 في النطاق من 0.4 إلى 0.56 قليلاً إلى تغيير الناتج كثيرًا.

عندئذٍ يكون التنبؤ النهائي للنموذج هو مجرد مجموع درجات الميزات المختلفة. هذا السلوك مشابه لقيم Shapley ولكن دون الحاجة إلى حسابها. عظيم ، أليس كذلك؟ الآن ، اسمحوا لي أن أريكم كيف يمكننا أن نفعل الشيء نفسه للشبكات العصبية.

إزالة الحواف

 
لذا ، إذا كانت المشكلة هي أن مدخلات الشبكة العصبية تتناثر في جميع أنحاء الطبقات المخفية بسبب الحواف الكثيرة ، فلنقم بإزالة بعضها. على وجه الخصوص ، يتعين علينا إزالة الحواف التي تسمح بتدفق معلومات أحد المعالم إلى ميزة أخرى. حذف هذه فقط حواف الانسكاب، تصبح الشبكة العصبية للعبة من الأعلى:


الشبكات العصبية القابلة للتفسير مع PyTorch
الصورة من قبل المؤلف.

 

أنشأنا ثلاثة منفصلة كتل بالنسبة لمتغيرات الإدخال الثلاثة ، كل كتلة عبارة عن شبكة متصلة بالكامل بمخرج جزئي واحد ŷᵢ. كخطوة أخيرة ، هذه ŷᵢ يتم جمعها ، ويتم إضافة التحيز (تم حذفه في الرسم) لإنتاج الناتج النهائي ŷ.

قدمنا ​​النواتج الجزئية لنكون قادرين على إنشاء نفس النوع من المؤامرات التي يسمح بها EBM. كتلة واحدة في الصورة أعلاه تسمح بقطعة أرض واحدة: xᵢ يذهب في، ŷᵢ يخرج. سنرى كيف نفعل هذا لاحقا.

هنا لدينا بالفعل الهندسة المعمارية الكاملة! أعتقد أنه من السهل جدًا فهمها من الناحية النظرية ، ولكن دعونا أيضًا ننفذها. بهذه الطريقة ، أنت سعيد لأنه يمكنك استخدام الشبكات العصبية ، والعمل سعيد لأن الشبكات العصبية قابلة للتفسير.

التنفيذ في PyTorch

 
لا أتوقع أنك مألوف تمامًا PyTorch، لذلك سأشرح بعض الأساسيات حول الطريقة التي ستساعدك على فهم تطبيقنا المخصص. إذا كنت تعرف أساسيات PyTorch ، فيمكنك تخطي ملف طبقات متصلة بالكامل الجزء. إذا لم تقم بتثبيت PyTorch ، اختر نسختك هنا.

طبقات متصلة بالكامل

 
تُعرف هذه الطبقات أيضًا باسم خطي في PyTorch أو كثيف in Keras. يتواصلون n عقد الإدخال إلى m باستخدام عقد الإخراج nm حواف بأوزان الضرب. هذا في الأساس عبارة عن ضرب مصفوفة بالإضافة إلى إضافة مصطلح التحيز ، كما ترى في مقتطفات الشفرة التالية:

import torchtorch.manual_seed(0) # keep things reproduciblex = torch.tensor([1., 2.]) # create an input array
linear_layer = torch.nn.Linear(2, 3) # define a linear layer
print(linear_layer(x)) # putting the input array into the layer# Output:
# tensor([ 0.7393, -1.0621, 0.0441], grad_fn=<AddBackward0>)

هذه هي الطريقة التي يمكنك بها إنشاء طبقات متصلة بالكامل وتطبيقها على موترات PyTorch. يمكنك الحصول على المصفوفة المستخدمة في الضرب من خلال linear_layer.weight والتحيز عبر linear_layer.bias . ثم يمكنك أن تفعل

print(linear_layer.weight @ x + linear_layer.bias) # @ = matrix mult# Output:
# tensor([ 0.7393, -1.0621, 0.0441], grad_fn=<AddBackward0>)

جميل ، إنه نفس الشيء! الآن ، الجزء الأكبر حول PyTorch و Keras وشركائهم. هو أنه يمكنك تكديس العديد من هذه الطبقات معًا لإنشاء شبكة عصبية. في PyTorch ، يمكنك تحقيق هذا التكديس عبر ملفات torch.nn.Sequential . لإعادة إنشاء الشبكة الكثيفة من الأعلى ، يمكنك عمل ملف

model = torch.nn.Sequential( torch.nn.Linear(3, 6), torch.nn.ReLU(), torch.nn.Linear(6, 6), torch.nn.ReLU(), torch.nn.Linear(6, 6), torch.nn.ReLU(), torch.nn.Linear(6, 1),
)print(model(torch.randn(4, 3))) # feed it 4 random 3-dim. vectors

ملحوظة: لم أوضح لك كيفية تدريب هذه الشبكة حتى الآن ، إنها مجرد تعريف للهندسة المعمارية ، بما في ذلك تهيئة المعلمات. ولكن يمكنك تغذية الشبكة بمدخلات ثلاثية الأبعاد وتلقي مخرجات ذات بعد واحد.

نظرًا لأننا نريد إنشاء طبقتنا الخاصة ، فلنتدرب على شيء سهل أولاً: إعادة إنشاء طبقة PyTorch Linear طبقة. هكذا كيف تقوم بها:

import torch
import mathclass MyLinearLayer(torch.nn.Module): def __init__(self, in_features, out_features): super().__init__() self.in_features = in_features self.out_features = out_features # multiplicative weights weights = torch.Tensor(out_features, in_features) self.weights = torch.nn.Parameter(weights) torch.nn.init.kaiming_uniform_(self.weights)  # bias bias = torch.Tensor(out_features) self.bias = torch.nn.Parameter(bias) bound = 1 / math.sqrt(in_features) torch.nn.init.uniform_(self.bias, -bound, bound)  def forward(self, x): return x @ self.weights.t() + self.bias

هذا الرمز يستحق بعض الشرح. في أول قالب عريض ، نقدم أوزان الطبقة الخطية بواسطة

  1. إنشاء موتر PyTorch (يحتوي على جميع الأصفار ، لكن هذا لا يهم)
  2. تسجيله كمعامل قابل للتعلم للطبقة مما يعني أن نزول التدرج يمكن تحديثه أثناء التدريب ، وبعد ذلك
  3. تهيئة المعلمات.

إن تهيئة معلمات الشبكة العصبية هو موضوع كامل من تلقاء نفسه ، لذلك لن ننزل في حفرة الأرانب. إذا كان يزعجك كثيرًا ، يمكنك أيضًا تهيئته بشكل مختلف ، على سبيل المثال عن طريق استخدام التوزيع العادي القياسي torch.randn(out_features, in_features) ، ولكن من المحتمل أن يكون التدريب أبطأ بعد ذلك. على أي حال ، نحن نفعل الشيء نفسه مع التحيز.

بعد ذلك ، تحتاج الطبقة إلى معرفة العمليات الحسابية التي يجب أن تؤديها في ملف forward طريقة. هذه مجرد عملية خطية ، أي ضرب مصفوفة وإضافة الانحياز.

حسنًا ، نحن الآن جاهزون لتنفيذ الطبقة لشبكتنا العصبية القابلة للتفسير!

طبقات كتلة خطية

 
نقوم الآن بتصميم ملف BlockLinear الطبقة التي سنستخدمها بالطريقة التالية: أولاً نبدأ بها n الميزات. ال BlockLinear يجب أن تخلق الطبقة بعد ذلك n كتل تتكون من h الخلايا العصبية المخفية. لتبسيط الأمور ، h هو نفسه في كل كتلة ، ولكن يمكنك تعميم هذا بالطبع. في المجموع ، ستتكون الطبقة المخفية الأولى من nh الخلايا العصبية ، ولكن أيضًا فقط nh الحواف متصلة بهم (بدلاً من n²لطبقة متصلة بالكامل)لفهمها بشكل أفضل ، انظر إلى الصورة أعلاه مرة أخرى. هنا، = 3، = 2.


الشبكات العصبية القابلة للتفسير مع PyTorch
الصورة من قبل المؤلف.

 

ثم - بعد استخدام بعض اللاخطية مثل ReLU - سنضع أخرى BlockLinear طبقة خلف هذا لأنه لا ينبغي دمج الكتل المختلفة مرة أخرى. نكرر هذا كثيرًا حتى نستخدم a Linear طبقة في النهاية لربط كل شيء مرة أخرى.

تنفيذ طبقة البلوك الخطية

 
دعنا نصل إلى الكود. إنه مشابه تمامًا للطبقة الخطية المخصصة لدينا ، لذلك لا ينبغي أن يكون الكود مخيفًا للغاية.

class BlockLinear(torch.nn.Module): def __init__(self, n_blocks, in_features, out_features): super().__init__() self.n_blocks = n_blocks self.in_features = in_features self.out_features = out_features self.block_weights = [] self.block_biases = [] for i in range(n_blocks): block_weight = torch.Tensor(out_features, in_features) block_weight = torch.nn.Parameter(block_weight) torch.nn.init.kaiming_uniform_(block_weight) self.register_parameter( f'block_weight_{i}', block_weight ) self.block_weights.append(block_weight) block_bias = torch.Tensor(out_features) block_bias = torch.nn.Parameter(block_bias) bound = 1 / math.sqrt(in_features) torch.nn.init.uniform_(block_bias, -bound, bound) self.register_parameter( f'block_bias_{i}', block_bias ) self.block_biases.append(block_bias) def forward(self, x): block_size = x.size(1) // self.n_blocks x_blocks = torch.split( x, split_size_or_sections=block_size, dim=1 ) block_outputs = [] for block_id in range(self.n_blocks): block_outputs.append( x_blocks[block_id] @ self.block_weights[block_id].t() + self.block_biases[block_id] ) return torch.cat(block_outputs, dim=1)

لقد أبرزت بضعة أسطر مرة أخرى. الخطوط الأولى الجريئة تشبه ما رأيناه في الطبقة الخطية محلية الصنع ، مكررة للتو n_blocks مرات. هذا يخلق طبقة خطية مستقلة لكل كتلة.

في الطريقة إلى الأمام ، نحصل على x كموتر واحد علينا تقسيمه إلى كتل مرة أخرى باستخدامه أولاً torch.split. كمثال ، حجم الكتلة 2 يقوم بما يلي: [1, 2, 3, 4, 5, 6] -> [1, 2], [3, 4], [5, 6]. ثم نطبق التحويلات الخطية المستقلة على الكتل المختلفة ، ونلصق النتائج معًا باستخدام torch.cat. منجز!

تدريب الشبكة العصبية القابلة للتفسير

 
الآن ، لدينا جميع المكونات لتحديد شبكتنا العصبية القابلة للتفسير. علينا فقط إنشاء مجموعة بيانات أولاً:

X = torch.randn(1000, 3)
y = 3*X[:, 0] + 2*X[:, 1]**2 + X[:, 2]**3 + torch.randn(1000)
y = y.reshape(-1, 1)

يمكننا أن نرى أننا نتعامل مع مجموعة بيانات ثلاثية الأبعاد تتكون من ألف عينة هنا. تكون العلاقة الحقيقية خطية إذا قمت بتربيع الميزة 1 وميزة المكعب 2 - وهذا ما نريد استرداده باستخدام نموذجنا! لذا ، دعونا نحدد نموذجًا صغيرًا يجب أن يكون قادرًا على تصوير هذه العلاقة.

class Model(torch.nn.Module): def __init__(self): super().__init__() self.features = torch.nn.Sequential( BlockLinear(3, 1, 20), torch.nn.ReLU(), BlockLinear(3, 20, 20), torch.nn.ReLU(), BlockLinear(3, 20, 20), torch.nn.ReLU(), BlockLinear(3, 20, 1), ) self.lr = torch.nn.Linear(3, 1) def forward(self, x): x_pre = self.features(x) return self.lr(x_pre) model = Model()

قسمت النموذج إلى خطوتين:

  1. حساب المخرجات الجزئية ŷᵢ مع self.features وثم
  2. احسب التنبؤ النهائي ŷ كمجموع مرجح لـ ŷᵢ مع self.lr .

هذا يجعل من السهل استخراج تفسيرات الميزة. في تعريف self.features يمكنك أن ترى أننا أنشأنا شبكة عصبية من ثلاث كتل لأن لدينا ثلاث ميزات في مجموعة البيانات. لكل كتلة ، نقوم بإنشاء العديد من الطبقات المخفية مع 20 خلية عصبية لكل كتلة.

الآن ، يمكننا إنشاء حلقة تدريب بسيطة:

optimizer = torch.optim.Adam(model.parameters())
criterion = torch.nn.MSELoss()for i in range(2000): optimizer.zero_grad() y_pred = model(X) loss = criterion(y, y_pred) loss.backward() optimizer.step() if i % 100 == 0: print(loss)

بشكل أساسي ، نختار آدم كمحسِّن ، و MSE كخسارة ، ثم نختار نزول التدرج القياسي ، أي محو التدرج القديم باستخدام optimzer.zero_grad() ، حساب التنبؤات ، حساب الخسارة ، التفريق عن طريق الخسارة loss.backward() وتحديث معلمات النموذج عبر optimizer.step() . يمكنك أن ترى تراجع خسارة التدريب بمرور الوقت. نحن لا نهتم بالتحقق من الصحة أو مجموعات الاختبار هنا. ال السلامه اولا rيجب أن يكون ² أكبر من 0.95 في النهاية.

يمكننا الآن طباعة تفسيرات النموذج عبر

import matplotlib.pyplot as pltx = torch.linspace(-5, 5, 100).reshape(-1, 1)
x = torch.hstack(3*[x])for i in range(3): plt.plot( x[:, 0].detach().numpy(), model.get_submodule('lr').weight[0][i].item() * model.get_submodule('features')(x)[:, i].detach().numpy()) plt.title(f'Feature {i+1}') plt.show()

والحصول على


الشبكات العصبية القابلة للتفسير مع PyTorch


الشبكات العصبية القابلة للتفسير مع PyTorch


الشبكات العصبية القابلة للتفسير مع PyTorch
الصور من قبل المؤلف.

 

هذا يبدو جميل جدا! يوضح النموذج أن تأثير الميزة 1 خطي ، وتأثير الميزة 2 تربيعي وتأثير الميزة 3 هو تأثير تكعيبي. وليس هذا فقط ، النموذج قادر على إظهاره لنا، وهو الشيء العظيم في البناء كله!

يمكنك حتى التخلص من الشبكة وإجراء تنبؤات بناءً على هذه المخططات فقط!

كمثال ، دعونا نقدر ناتج الشبكة لـ x = (2، -2، 0).

  • x₁ = 2 يترجم إلى أ +5 للتنبؤ ، بناءً على الشكل الأول.
  • x₂ = -2 يترجم إلى أ +9 للتنبؤ ، بناءً على الشكل الثاني.
  • x₃ = 0 يترجم إلى أ +0 للتنبؤ ، بناءً على الرقم الثالث.
  • لا يزال هناك انحياز من آخر طبقة خطية يمكنك الوصول إليها عبر model.get_submodule('lr').bias يجب إضافة هذا أيضًا ، لكن يجب أن يكون صغيرًا.

في المجموع ، يجب أن يكون توقعك قريبًا ŷ ≈ 5 + 9 + 0 + تحيز ≈ 14 ، وهي دقيقة إلى حد ما.

يمكنك أيضًا معرفة ما عليك القيام به لتقليل الإخراج: اختر قيمًا صغيرة للميزة 1 ، وقيم قريبة من الصفر للميزة 2 ، وقيم صغيرة للميزة 3. هذا شيء لا يمكنك رؤيته عادةً بمجرد النظر إلى الشبكة العصبية ، ولكن مع وظائف النتيجة ، يمكننا ذلك. هذه فائدة كبيرة لقابلية التفسير.

لاحظ أن وظائف النتيجة المكتسبة من الأعلى يمكن أن تكون واثقة فقط للمناطق التي نحن فيها في الواقع كان لديه بيانات تدريب. في مجموعة البيانات الخاصة بنا ، لاحظنا فقط القيم بين -3 و 3 لكل ميزة. لذلك ، يمكننا أن نرى أننا لم نصل إلى الكمال x² و x³ كثيرات الحدود على الحواف. لكنني أعتقد أنه لا يزال من المثير للإعجاب أن اتجاهات الرسوم البيانية صحيحة. لتقدير ذلك تمامًا ، قارنه بنتائج EBM:


الشبكات العصبية القابلة للتفسير مع PyTorch


الشبكات العصبية القابلة للتفسير مع PyTorch
الصور من قبل المؤلف.

 

المنحنيات ممتلئة ، والاستقراء هو مجرد خط مستقيم على كلا الجانبين ، وهو أحد العيوب الرئيسية للطرق القائمة على الأشجار.

وفي الختام

 
في هذه المقالة ، تحدثنا عن قابلية تفسير النماذج ، وكيف تفشل الشبكات العصبية وتعزيز التدرج في تقديمها. بينما أنشأ مؤلفو حزمة التفسير EBM ، خوارزمية تعزيز التدرج القابل للتفسير ، فقد قدمت لك طريقة لإنشاء شبكات عصبية قابلة للتفسير.

قمنا بعد ذلك بتطبيقه في PyTorch ، والذي كان ثقيلًا بعض الشيء في التعليمات البرمجية ، لكن لا شيء مجنون للغاية. بالنسبة إلى EBM ، يمكننا استخراج وظائف النتيجة المكتسبة لكل ميزة يمكننا حتى استخدامها لعمل تنبؤات.

لم يعد النموذج الفعلي المدرب ضروريًا بعد الآن ، مما يجعل من الممكن نشره واستخدامه على أجهزة ضعيفة. هذا لأنه يتعين علينا فقط تخزين جدول بحث واحد لكل ميزة ، وهو خفيف على الذاكرة. باستخدام حجم شبكة من g لكل جدول بحث ينتج عنه التخزين فقط O(n_الميزات * g) عناصر بدلاً من الملايين أو المليارات من معلمات النموذج المحتملة. إجراء التنبؤات رخيص أيضًا: فقط أضف بعض الأرقام من جداول البحث. نظرًا لأن هذا يحتوي على ملف تعقيد الوقت فقط O(n_الميزات) عمليات البحث والإضافات ، فهي أسرع بكثير من المرور الأمامي عبر الشبكة.

إخلاء المسؤولية مرة أخرى: لست متأكدًا مما إذا كانت هذه فكرة جديدة ، لكن ها هي على أي حال! إذا كنت تعرف أي ورقة تشرح نفس الفكرة ، فالرجاء ترك رسالة لي وسأشير إليها.

أتمنى أن تكون قد تعلمت شيئًا جديدًا وشيقًا ومفيدًا اليوم. شكرا للقراءة!

كنقطة أخيرة ، إذا كنت

  1. تريد دعمي في كتابة المزيد عن التعلم الآلي و
  2. تخطط للحصول على اشتراك متوسط ​​على أي حال ،

لماذا لا تفعل ذلك عبر هذا الرابط؟ هذا سيساعدني كثيرا 😊

لكي نكون شفافين ، لا يتغير السعر بالنسبة لك ، لكن حوالي نصف رسوم الاشتراك تذهب إلي مباشرة.

شكرا جزيلا ، إذا كنت تفكر في دعمي!

إذا كان لديك أي أسئلة ، فاكتب لي لينكدين:!

 
 
دكتور روبرت كوبلر هو عالم بيانات في Publicis Media ومؤلف في Towards Data Science.

أصلي. تم إعادة النشر بإذن.

المصدر: https://www.kdnuggets.com/2022/01/interpretable-neural-networks-pytorch.html

بقعة_صورة

أحدث المعلومات الاستخباراتية

بقعة_صورة