ارزیابی مدل یادگیری عمیق — به زبان ساده

۱۹۵۸ بازدید
آخرین به‌روزرسانی: ۱۱ اردیبهشت ۱۴۰۲
زمان مطالعه: ۱۰ دقیقه
ارزیابی مدل یادگیری عمیق — به زبان ساده

هنگامی که یک مدل «شبکه عصبی یادگیری عمیق» (Deep Learning Neural Network) برازش می‌شود، باید کارایی آن روی مجموعه داده‌های تست ارزیابی شود. این کار از آن رو ضروری است که کارایی گزارش شده به کاربر امکان انتخاب بین مدل‌های کاندید و همچنین، مذاکره با ذینفعان پیرامون خوب بودن مدل در حل مسائل را می‌دهد. مدل «رابط برنامه‌نویسی کاربردی» (Application Programming Interface) یادگیری عمیق کتابخانه «کرس» (Keras)، بسیار محدود به سنجه‌هایی است که می‌توان از آن‌ها برای گزارش کردن کارایی مدل استفاده کرد. افراد زیادی که مدل‌های یادگیری عمیق استفاده می‌کنند، معمولا این پرسش را مطرح می‌کنند که «چگونه می‌توان دقت و صحت مدل را اندازه‌گیری کرد؟» و «چطور می‌توان امتیاز «اف ۱» (F1 Score) یا ماتریس درهم ریختگی را برای مدل محاسبه کرد». در این مطلب، ضمن تشریح روش‌های ارزیابی مدل یادگیری عمیق، موارد زیر مورد بررسی قرار خواهند گرفت.

  • چگونه می‌توان از API سنجه‌های کتابخانه «سایکیت‌لرن» (Scikit-Learn) برای ارزیابی مدل یادگیری عمیق استفاده کرد.
  • چگونه می‌توان پیش‌بینی دسته‌ها و احتمال را با یک مدل خوب مورد نیاز با API سایکیت‌لرن انجام داد.
  • چگونه می‌توان «دقت» (Precision)، «صحت» (Recall)، «امتیاز اف ۱» (F1-Score)، «منحنی مشخصه عملکرد سیستم» (Receiver Operating Characteristic | ROC) و دیگر موارد را با استفاده از API سایکیت‌لِرن، برای مدل محاسبه کرد.

در این مطلب در سه بخش کلی، به مساله دسته‌بندی دودویی، مدل «پرسپترون چند لایه» (Multilayer Perceptron) و چگونگی محاسبه سنجه‌های مدل پرداخته خواهد شد.

مساله دسته‌بندی دودویی

در اینجا، از یک مساله استاندارد دسته‌بندی دودویی استفاده می‌شود که مساله «Two Circles» نام دارد. به این مساله، بدین دلیل مساله دو دایره گفته می‌شود که در بردارنده نقاطی است که پس از ترسیم، دو دایره هم‌مرکز را نشان می‌دهند؛ هر یک از این دایره‌ها برای یک دسته (از مجموع دو دسته) هستند. بدین شکل، این مثالی از یک مساله دسته‌بندی دودویی است. مساله دارای دو ورودی است که در نمودار به عنوان محورهای x و y قابل تفسیر هستند. هر نقطه داده به دایره داخلی یا خارجی تعلق دارد.

تابع ()make_circles در کتابخانه سایکیت‌لرن به کاربر امکان تولید نمونه‌هایی از مساله دو دایره را می‌دهد. آرگومان «n_samples» به کاربر امکان تعیین تعداد نمونه‌ها را برای تولید می‌دهد که به طور مساوی بین دو کلاس تقسیم شده‌اند. آرگومان «noise» به کاربر این امکان را می‌دهد که مشخص کند چه میزان نویز آماری تصادفی به ورودی‌ها یا مختصات هر نقطه داده می‌شود؛ این کار، دسته‌بندی را چالش برانگیزتر می‌کند. آرگومان «random_state» «بذر» (seed) برای مولد اعداد تصادفی را تعیین می‌کند تا اطمینان حاصل کند که نمونه‌های مشابهی هر بار که کد اجرا می‌شود تولید می‌شوند. مثال زیر، ۱۰۰۰ نمونه با نویز آماری ۰.۱ و بذر ۱ تولید می‌کند.

1# generate 2d classification dataset
2X, y = make_circles(n_samples=1000, noise=0.1, random_state=1)

هنگامی که نمونه‌ها تولید می‌شوند، می‌توان یک نمودار از مجموعه داده را برای به دست آوردن ایده‌ای از اینکه کار دسته‌بندی چقدر چالش برانگیزتر است را ترسیم کرد. مثال زیر، نمونه‌هایی را تولید و آن‌ها را ترسیم می‌کند، هر نقطه مطابق با دسته‌ای که به آن تعلق دارد رنگ می‌شود؛ نقاط متعلق به دسته ۰ (دایره بیرونی) به رنگ آبی و نقاط متعلق به دسته ۱ (دایره درونی) نارنجی رنگ می‌شوند.

1# Example of generating samples from the two circle problem
2from sklearn.datasets import make_circles
3from matplotlib import pyplot
4from numpy import where
5# generate 2d classification dataset
6X, y = make_circles(n_samples=1000, noise=0.1, random_state=1)
7# scatter plot, dots colored by class value
8for i in range(2):
9	samples_ix = where(y == i)
10	pyplot.scatter(X[samples_ix, 0], X[samples_ix, 1])
11pyplot.show()

اجرای مثال بالا، منجر به تولید مجموعه داده می‌شود و نقاط را روی نمودار ترسیم می‌کند؛ این نقاط به طور واضح نشانگر دو دایره هم‌مرکز از نقاط متعلق به دسته‌های ۰ و ۱ هستند.

ارزیابی مدل
نمودار نقطه‌ای نمونه‌ها برای مساله دو دایره

ارزیابی مدل پرسپترون چند لایه

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

پس از آنکه نمونه‌ها برای مجموعه داده تولید شدند، آن‌ها به دو بخش مساوی تقسیم می‌شوند؛ یک بخش برای آموزش مدل و بخش دیگر برای ارزیابی مدل آموزش دیده.

1# split into train and test
2n_test = 500
3trainX, testX = X[:n_test, :], X[n_test:, :]
4trainy, testy = y[:n_test], y[n_test:]

سپس، می‌توان مدل MLP را تعریف کرد. مدل ساده است؛ نیاز به دو متغیر ورودی از مجموعه داده، یک لایه پنهان با ۱۰۰ گره و یک تابع فعال‌سازی ReLU و در نهایت، یک گره مجرد و «تابع فعال‌سازی سیگموئید» (Sigmoid Activation Function) دارد. مدل یک مقدار بین ۰ و ۱ را پیش‌بینی می‌کند که تفسیر آن مشخص می‌کند نمونه ورودی متعلق به دسته ۰ یا ۱ است.

1# define model
2model = Sequential()
3model.add(Dense(100, input_dim=2, activation='relu'))
4model.add(Dense(1, activation='sigmoid'))

مدل با استفاده از «تابع زیان آنتروپی متقاطع دودویی» (Binary Cross Entropy Loss Function) برازش می‌شود و در اینجا، از نسخه «آدام» (Adam) روش «گرادیان کاهشی تصادفی» (Stochastic Gradient Descent) استفاده خواهد شد. همچنین، مدل سنجه صحت دسته‌بندی را مورد نظارت قرار می‌دهد.

1# compile model
2model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

مدل برای ۳۰۰ «دوره» (epoch) با اندازه دسته ۳۲ نمونه برازش می‌شود و کارایی مدل در پایان هر دوره روی مجموعه داده تست ارزیابی می‌شود.

1# fit model
2history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=300, verbose=0)

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

1# evaluate the model
2_, train_acc = model.evaluate(trainX, trainy, verbose=0)
3_, test_acc = model.evaluate(testX, testy, verbose=0)

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

1# plot loss during training
2pyplot.subplot(211)
3pyplot.title('Loss')
4pyplot.plot(history.history['loss'], label='train')
5pyplot.plot(history.history['val_loss'], label='test')
6pyplot.legend()
7# plot accuracy during training
8pyplot.subplot(212)
9pyplot.title('Accuracy')
10pyplot.plot(history.history['acc'], label='train')
11pyplot.plot(history.history['val_acc'], label='test')
12pyplot.legend()
13pyplot.show()

با آزمودن همه این عناصر به صورت هم‌زمان، کد مربوط به لیست کردن آموزش و ارزیابی یک MLP روی مساله دو دایره، در زیر نمایش داده شده است.

1# multilayer perceptron model for the two circles problem
2from sklearn.datasets import make_circles
3from keras.models import Sequential
4from keras.layers import Dense
5from matplotlib import pyplot
6# generate dataset
7X, y = make_circles(n_samples=1000, noise=0.1, random_state=1)
8# split into train and test
9n_test = 500
10trainX, testX = X[:n_test, :], X[n_test:, :]
11trainy, testy = y[:n_test], y[n_test:]
12# define model
13model = Sequential()
14model.add(Dense(100, input_dim=2, activation='relu'))
15model.add(Dense(1, activation='sigmoid'))
16# compile model
17model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
18# fit model
19history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=300, verbose=0)
20# evaluate the model
21_, train_acc = model.evaluate(trainX, trainy, verbose=0)
22_, test_acc = model.evaluate(testX, testy, verbose=0)
23print('Train: %.3f, Test: %.3f' % (train_acc, test_acc))
24# plot loss during training
25pyplot.subplot(211)
26pyplot.title('Loss')
27pyplot.plot(history.history['loss'], label='train')
28pyplot.plot(history.history['val_loss'], label='test')
29pyplot.legend()
30# plot accuracy during training
31pyplot.subplot(212)
32pyplot.title('Accuracy')
33pyplot.plot(history.history['acc'], label='train')
34pyplot.plot(history.history['val_acc'], label='test')
35pyplot.legend()
36pyplot.show()

با اجرای کد بالا، برازش مدل به سرعت روی CPU انجام می‌شود (نیاز به GPU نیست). ارزیابی مدل انجام و صحت دسته‌بندی روی مجموعه‌های آموزش و تست به ترتیب برابر با ٪۸۳ و ٪۸۵ گزارش می‌شود.

شایان توجه است که نتایج ممکن است در اجراهای مختلف به دلیل ماهیت تصادفی الگوریتم آموزش، تغییر کنند.

Train: 0.838, Test: 0.850

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

ارزیابی مدل
نمودار خطی که منحنی یادگیری زیان و صحت MLP را در طول آموزش، روی مساله دو دایره نشان می‌دهد.

روش محاسبه سنجه‌های مدل

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

این کار ممکن است به لحاظ فنی، چالش برانگیز باشد. یک راهکار جایگزین ساده‌تر استفاده از مدل نهایی برای انجام پیش‌بینی برای مجموعه داده تست و سپس محاسبه هر سنجه‌ای که کاربر تمایل دارد با استفاده از API سنجه‌های سایکیت‌لرن است. دقت، صحت، امتیاز اف‌۱ سه سنجه متداولی هستند که علاوه بر صحت دسته‌بندی برای مسائل دسته‌بندی دودویی یک مدل شبکه عصبی مورد استفاده قرار می‌گیرند.

در این بخش، این سه سنجه همراه با صحت دسته‌بندی با استفاده از API سنجه‌های سایکیت‌لرن و همچنین، سه سنجه اضافه دیگری که کمتر متداول اما محبوب هستند نیز محاسبه می‌شوند. این سه سنجه عبارتند از: ضریب «کاپای کوهن» (Cohen’s Kappa)، «منحنی مشخصه عملکرد سیستم» (ROC AUC)، «ماتریس درهم ریختگی» (Confusion Matrix).

لیست ارائه شده، یک لیست کامل از ماتریس‌های موجود برای مدل‌های دسته‌بندی پشتیبانی شده توسط سایکیت‌لرن نیست. این سنجه‌ها صرفا به کاربر نشان می‌دهند که چگونه هر سنجه‌ای را که ممکن است به آن نیاز پیدا کند، با استفاده از API سایکیت‌لرن مورد محاسبه قرار دهد. مثال ارائه شده در این بخش، سنجه‌هایی برای یک مدل MLP را محاسبه می‌کند، اما کد مشابهی برای محاسبه سنجه‌ها برای دیگر مدل‌ها مانند «شبکه‌های عصبی بازگشتی» (Recurrent Neural Network) و «شبکه‌های عصبی پیچشی» (Convolutional Neural Network) نیز قابل استفاده است. می‌توان از کد مشابهی از بخش پیشین برای آماده‌سازی مجموعه داده، تعریف و برازش مدل استفاده کرد. برای ساده‌تر کردن مثال، کدهای لازم برای این گام‌ها در یک تابع ساده‌تر قرار داده می‌شوند.

ابتدا، می‌توان یک تابع با عنوان ()get_data اضافه کرد که مجموعه داده را تولید و آن را به بخش‌های آموزش و آزمون تقسیم می‌کند.

1# generate and prepare the dataset
2def get_data():
3	# generate dataset
4	X, y = make_circles(n_samples=1000, noise=0.1, random_state=1)
5	# split into train and test
6	n_test = 500
7	trainX, testX = X[:n_test, :], X[n_test:, :]
8	trainy, testy = y[:n_test], y[n_test:]
9	return trainX, trainy, testX, testy

سپس، تابعی با عنوان ()get_model تعریف می‌شود که مدل MLP را تعریف کرده و آن را روی مجموعه داده آموزش برازش می‌کند.

1# define and fit the model
2def get_model(trainX, trainy):
3	# define model
4	model = Sequential()
5	model.add(Dense(100, input_dim=2, activation='relu'))
6	model.add(Dense(1, activation='sigmoid'))
7	# compile model
8	model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
9	# fit model
10	model.fit(trainX, trainy, epochs=300, verbose=0)
11	return model

می‌توان تابع ()get_data را برای آماده‌سازی مجموعه داده و تابع ()get_model را برای برازش و بازگرداندن مدل استفاده کرد.

1# generate data
2trainX, trainy, testX, testy = get_data()
3# fit model
4model = get_model(trainX, trainy)

اکنون که مدل روی مجموعه داده آموزش برازش داده شد، می‌توان آن را با استفاده از سنجه‌هایی از API سنجه‌های سایکیت‌لرن ارزیابی کرد. در حال حاضر، ابتدا باید از مدل برای انجام پیش‌بینی استفاده کرد. بیشتر توابع سنجه‌ها نیاز به مقایسه بین مقادیر صحیح کلاس (برای مثال testy) و مقادیر کلاس پیش‌بینی شده (yhat_classes) دارند. می‌توان مقادیر کلاس را به طور مستقیم با استفاده از تابع ()predict_classes روی مدل، پیش‌بینی کرد. برخی از سنجه‌ها، مانند ROC AUC، نیاز به پیش‌بینی احتمال‌های کلاس دارند (yhat_probs). این موارد را می‌توان با فراخوانی تابع ()predict روی مدل پیش‌بینی کرد. می‌توان کلاس و پیش‌بینی‌های احتمالات را با مدل انجام داد.

1# predict probabilities for test set
2yhat_probs = model.predict(testX, verbose=0)
3# predict crisp classes for test set
4yhat_classes = model.predict_classes(testX, verbose=0)

پیش‌بینی‌ها در یک آرایه دوبعدی بازگردانده می‌شوند، با یک سطر برای هر مثال در مجموعه داده تست و یک ستون برای هر پیش‌بینی. API سنجه‌های سایکیت‌لرن نیاز به یک آرایه یک‌بُعدی از مقادیر واقعی و پیش‌بینی شده برای مقایسه دارد؛ بنابراین، باید آرایه دوبعدی را به یک بعدی کاهش داد.

1# reduce to 1d array
2yhat_probs = yhat_probs[:, 0]
3yhat_classes = yhat_classes[:, 0]

اکنون، آمادگی لازم برای محاسبه سنجه‌ها برای مدل شبکه عصبی یادگیری عمیق وجود دارد. می‌توان کار را با محاسبه «درستی» (Accuracy)، «صحت» (Precision)، «دقت» (recall) و «امتیاز اف ۱» (F1 scores) آغاز کرد.

1# accuracy: (tp + tn) / (p + n)
2accuracy = accuracy_score(testy, yhat_classes)
3print('Accuracy: %f' % accuracy)
4# precision tp / (tp + fp)
5precision = precision_score(testy, yhat_classes)
6print('Precision: %f' % precision)
7# recall: tp / (tp + fn)
8recall = recall_score(testy, yhat_classes)
9print('Recall: %f' % recall)
10# f1: 2 tp / (2 tp + fp + fn)
11f1 = f1_score(testy, yhat_classes)
12print('F1 score: %f' % f1)

محاسبه یک سنجه خاص، بسیار آسان و تنها کافی است کاربر سنجه مورد نظر خود را انتخاب کند. سپس، تابع مربوط به آن سنجه را فراخوانی کرده و آرگومان‌های لازم را به آن پاس دهد. اکنون، می‌توان برخی از سنجه‌های اضافی مانند «کوهن کاپا» (Cohen’s kappa)، «منحنی مشخصه عملکرد سیستم» (ROC AUC) و «ماتریس درهم ریختگی» (Confusion Matrix) را محاسبه کرد.

توجه به این نکته لازم است که ROC AUC نیاز به احتمالات دسته پیش‌بینی شده (yhat_probs) به عنوان آرگومان دارد؛ به جای آنکه دسته پیش‌بینی شده (yhat_classes) را به عنوان آرگومان دریافت کند.

1# kappa
2kappa = cohen_kappa_score(testy, yhat_classes)
3print('Cohens kappa: %f' % kappa)
4# ROC AUC
5auc = roc_auc_score(testy, yhat_probs)
6print('ROC AUC: %f' % auc)
7# confusion matrix
8matrix = confusion_matrix(testy, yhat_classes)
9print(matrix)

اکنون که چگونگی محاسبه سنجه‌ها برای شبکه‌های عصبی یادگیری عمیق با استفاده از API سایکیت‌لرن مشخص شد، می‌توان همه این عناصر را در کنار هم در یک مثال کامل قرار داد که کد آن در زیر ارائه شده است.

1# demonstration of calculating metrics for a neural network model using sklearn
2from sklearn.datasets import make_circles
3from sklearn.metrics import accuracy_score
4from sklearn.metrics import precision_score
5from sklearn.metrics import recall_score
6from sklearn.metrics import f1_score
7from sklearn.metrics import cohen_kappa_score
8from sklearn.metrics import roc_auc_score
9from sklearn.metrics import confusion_matrix
10from keras.models import Sequential
11from keras.layers import Dense
12 
13# generate and prepare the dataset
14def get_data():
15	# generate dataset
16	X, y = make_circles(n_samples=1000, noise=0.1, random_state=1)
17	# split into train and test
18	n_test = 500
19	trainX, testX = X[:n_test, :], X[n_test:, :]
20	trainy, testy = y[:n_test], y[n_test:]
21	return trainX, trainy, testX, testy
22 
23# define and fit the model
24def get_model(trainX, trainy):
25	# define model
26	model = Sequential()
27	model.add(Dense(100, input_dim=2, activation='relu'))
28	model.add(Dense(1, activation='sigmoid'))
29	# compile model
30	model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
31	# fit model
32	model.fit(trainX, trainy, epochs=300, verbose=0)
33	return model
34 
35# generate data
36trainX, trainy, testX, testy = get_data()
37# fit model
38model = get_model(trainX, trainy)
39 
40 
41# predict probabilities for test set
42yhat_probs = model.predict(testX, verbose=0)
43# predict crisp classes for test set
44yhat_classes = model.predict_classes(testX, verbose=0)
45# reduce to 1d array
46yhat_probs = yhat_probs[:, 0]
47yhat_classes = yhat_classes[:, 0]
48 
49# accuracy: (tp + tn) / (p + n)
50accuracy = accuracy_score(testy, yhat_classes)
51print('Accuracy: %f' % accuracy)
52# precision tp / (tp + fp)
53precision = precision_score(testy, yhat_classes)
54print('Precision: %f' % precision)
55# recall: tp / (tp + fn)
56recall = recall_score(testy, yhat_classes)
57print('Recall: %f' % recall)
58# f1: 2 tp / (2 tp + fp + fn)
59f1 = f1_score(testy, yhat_classes)
60print('F1 score: %f' % f1)
61 
62# kappa
63kappa = cohen_kappa_score(testy, yhat_classes)
64print('Cohens kappa: %f' % kappa)
65# ROC AUC
66auc = roc_auc_score(testy, yhat_probs)
67print('ROC AUC: %f' % auc)
68# confusion matrix
69matrix = confusion_matrix(testy, yhat_classes)
70print(matrix)

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

1Accuracy: 0.842000
2Precision: 0.836576
3Recall: 0.853175
4F1 score: 0.844794
5Cohens kappa: 0.683929
6ROC AUC: 0.923739
7[[206  42]
8 [ 37 215]]

جمع‌بندی

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

اگر مطلب بالا برای شما مفید بوده، آموزش‌های زیر نیز به شما پیشنهاد می‌شود:

بر اساس رای ۱۱ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
Machine Learning Mastery
نظر شما چیست؟

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