التعلم العميق. التعليم الموحد

صورة مرحبا ، habrozhiteli! سلمنا مؤخرًا إلى Andrew W. Trask ، كتاب يضع الأساس لمزيد من التمكن من تكنولوجيا التعلم العميق. ويبدأ مع وصف لأساسيات الشبكات العصبية ، ثم يبحث بالتفصيل في طبقات ومعماريات إضافية.

نحن نقدم مراجعة لمقطع "التعليم الموحد"

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

التعلم الموحد هو تقنية لإحاطة نموذج في بيئة آمنة وتعليمه دون نقل البيانات في أي مكان. النظر في مثال.

import numpy as np from collections import Counter import random import sys import codecsnp.random.seed(12345) with codecs.open('spam.txt',"r",encoding='utf-8',errors='ignore') as f: ←     http://www2.aueb.gr/users/ion/data/enron-spam/ raw = f.readlines() vocab, spam, ham = (set(["<unk>"]), list(), list()) for row in raw: spam.append(set(row[:-2].split(" "))) for word in spam[-1]: vocab.add(word) with codecs.open('ham.txt',"r",encoding='utf-8',errors='ignore') as f: raw = f.readlines() for row in raw: ham.append(set(row[:-2].split(" "))) for word in ham[-1]: vocab.add(word) vocab, w2i = (list(vocab), {}) for i,w in enumerate(vocab): w2i[w] = i def to_indices(input, l=500): indices = list() for line in input: if(len(line) < l): line = list(line) + ["<unk>"] * (l - len(line)) idxs = list() for word in line: idxs.append(w2i[word]) indices.append(idxs) return indices 

تعلم للكشف عن البريد المزعج.


دعنا نقول أننا بحاجة إلى تدريب نموذج لاكتشاف البريد العشوائي من رسائل البريد الإلكتروني للأشخاص

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

تنفذ الشفرة في السابق وفي هذا القسم العمليات التحضيرية فقط. تتوفر ملفات الإدخال (ham.txt و spam.txt) على صفحة الويب الخاصة بالكتاب : www.manning.com/books/grokking-deep-learning وفي مستودع GitHub: github.com/iamtrask/Grokking-Deep-Learning . نحتاج إلى معالجتها مسبقًا من أجل إعدادها للنقل إلى فصل التضمين من الفصل 13 ، حيث أنشأنا إطار التعلم العميق. كما كان من قبل ، يتم تحويل جميع الكلمات الموجودة في هذه المجموعة إلى قوائم الفهرس. بالإضافة إلى ذلك ، نأتي جميع الحروف بطول 500 كلمة ، إما بتشذيبها أو إضافة رموز. بفضل هذا ، حصلنا على مجموعة بيانات مستطيلة.

 spam_idx = to_indices(spam) ham_idx = to_indices(ham) train_spam_idx = spam_idx[0:-1000] train_ham_idx = ham_idx[0:-1000] test_spam_idx = spam_idx[-1000:] test_ham_idx = ham_idx[-1000:] train_data = list() train_target = list() test_data = list() test_target = list() for i in range(max(len(train_spam_idx),len(train_ham_idx))): train_data.append(train_spam_idx[i%len(train_spam_idx)]) train_target.append([1]) train_data.append(train_ham_idx[i%len(train_ham_idx)]) train_target.append([0]) for i in range(max(len(test_spam_idx),len(test_ham_idx))): test_data.append(test_spam_idx[i%len(test_spam_idx)]) test_target.append([1]) test_data.append(test_ham_idx[i%len(test_ham_idx)]) test_target.append([0]) def train(model, input_data, target_data, batch_size=500, iterations=5): n_batches = int(len(input_data) / batch_size) for iter in range(iterations): iter_loss = 0 for b_i in range(n_batches): #         model.weight.data[w2i['<unk>']] *= 0 input = Tensor(input_data[b_i*bs:(b_i+1)*bs], autograd=True) target = Tensor(target_data[b_i*bs:(b_i+1)*bs], autograd=True) pred = model.forward(input).sum(1).sigmoid() loss = criterion.forward(pred,target) loss.backward() optim.step() iter_loss += loss.data[0] / bs sys.stdout.write("\r\tLoss:" + str(iter_loss / (b_i+1))) print() return model def test(model, test_input, test_output): model.weight.data[w2i['<unk>']] *= 0 input = Tensor(test_input, autograd=True) target = Tensor(test_output, autograd=True) pred = model.forward(input).sum(1).sigmoid() return ((pred.data > 0.5) == target.data).mean() 

بعد تحديد الوظائف المساعدة train () و test () ، يمكننا تهيئة الشبكة العصبية وتدريبها عن طريق كتابة بضعة أسطر من التعليمات البرمجية. بعد ثلاث مرات ، أصبحت الشبكة قادرة على تصنيف مجموعة بيانات التحكم بدقة 99.45٪ (مجموعة بيانات التحكم متوازنة بشكل جيد ، وبالتالي يمكن اعتبار هذه النتيجة ممتازة):

 model = Embedding(vocab_size=len(vocab), dim=1) model.weight.data *= 0 criterion = MSELoss() optim = SGD(parameters=model.get_parameters(), alpha=0.01) for i in range(3): model = train(model, train_data, train_target, iterations=1) print("% Correct on Test Set: " + \ str(test(model, test_data, test_target)*100)) ______________________________________________________________________________ Loss:0.037140416860871446 % Correct on Test Set: 98.65 Loss:0.011258669226059114 % Correct on Test Set: 99.15 Loss:0.008068268387986223 % Correct on Test Set: 99.45 

لنجعل النموذج الفيدرالي


أعلاه ، تم التعلم العميق الأكثر شيوعا. الآن إضافة الخصوصية

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

 bob = (train_data[0:1000], train_target[0:1000]) alice = (train_data[1000:2000], train_target[1000:2000]) sue = (train_data[2000:], train_target[2000:]) 

لا شيء معقد حتى الآن. الآن يمكننا إجراء نفس الإجراء التدريبي كما كان من قبل ، ولكن في ثلاث مجموعات منفصلة من البيانات. بعد كل تكرار ، سنقوم بتقييم القيم في نماذج Bob و Alice و Sue وتقييم النتائج. يرجى ملاحظة أن بعض أساليب التعلم الموحدة تتضمن الجمع بعد كل حزمة (أو مجموعة مجموعة) ؛ قررت أن أبقي الكود بسيطًا قدر الإمكان:

 for i in range(3): print("Starting Training Round...") print("\tStep 1: send the model to Bob") bob_model = train(copy.deepcopy(model), bob[0], bob[1], iterations=1) print("\n\tStep 2: send the model to Alice") alice_model = train(copy.deepcopy(model), alice[0], alice[1], iterations=1) print("\n\tStep 3: Send the model to Sue") sue_model = train(copy.deepcopy(model), sue[0], sue[1], iterations=1) print("\n\tAverage Everyone's New Models") model.weight.data = (bob_model.weight.data + \ alice_model.weight.data + \ sue_model.weight.data)/3 print("\t% Correct on Test Set: " + \ str(test(model, test_data, test_target)*100)) print("\nRepeat!!\n") 


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

 Starting Training Round... Step 1: send the model to Bob Loss:0.21908166249699718 ...... Step 3: Send the model to Sue Loss:0.015368461608470256 Average Everyone's New Models % Correct on Test Set: 98.8 

هاك نموذج اتحادي


دعونا نلقي نظرة على مثال بسيط عن كيفية استخراج المعلومات من مجموعة بيانات التدريب.

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

لكن دعونا لا نتقدم على أنفسنا. دعونا نرى ما يمكنك اكتشافه بعد قيام المستخدم بتحديث الأوزان على حزمة واحدة:

 import copy bobs_email = ["my", "computer", "password", "is", "pizza"] bob_input = np.array([[w2i[x] for x in bobs_email]]) bob_target = np.array([[0]]) model = Embedding(vocab_size=len(vocab), dim=1) model.weight.data *= 0 bobs_model = train(copy.deepcopy(model), bob_input, bob_target, iterations=1, batch_size=1) 

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

 for i, v in enumerate(bobs_model.weight.data - model.weight.data): if(v != 0): print(vocab[i]) 

بهذه الطريقة البسيطة ، اكتشفنا كلمة مرور بوب السرية للغاية (وربما تفضيلاته الطهي). وماذا تفعل؟ كيف تثق في التعلم الموحد إذا كان من السهل للغاية معرفة أي بيانات التدريب تسببت في التغيير في الأوزان؟

 is pizza computer password my 

»يمكن الاطلاع على مزيد من المعلومات حول الكتاب على موقع الناشر
» المحتويات
» مقتطفات

خصم 30٪ على كتب هابروجيتيلي المسبقة الدفع على كوبون - Grokking Deep Learning

Source: https://habr.com/ru/post/ar458800/


All Articles