هناك العديد من المنشورات على الشبكة حول تفسير شبكة عصبية معينة وأهمية ومساهمة بعض النقاط في التعلم. هناك الكثير من العمل حول البحث عن شعيرات وذيول وأجزاء أخرى وأهميتها وأهميتها. الآن لن أستبدل أمناء المكتبات وأعد قائمة. سأتحدث فقط عن تجربتي.
بدأ كل شيء بتقرير فيديو ممتاز "كيف تفكر الروبوتات. تفسير نماذج ML " ، الذي تمت مراجعته بناءً على نصيحة شخص ذكي ومثل أي عمل حكيم ، أثار العديد من الأسئلة. على سبيل المثال: - ما مدى تميز النقاط الرئيسية لمجموعة البيانات؟
أو سؤال آخر: - هناك العديد من المقالات على الشبكة حول كيف أن تغيير نقطة واحدة في الصورة يمكن أن يشوه بشكل كبير تنبؤات الشبكة. اسمحوا لي أن أذكركم أننا في هذه المقالة ننظر فقط في مشاكل التصنيف. ما مدى تميز هذه النقطة الخبيثة؟ هل توجد مثل هذه النقاط في التسلسل الطبيعي لـ MNIST وإذا تم العثور عليها وطردها ، فهل ستكون دقة تدريب الشبكة العصبية أعلى؟
قرر المؤلف ، باتباع طريقته التقليدية للتخلص من كل ما هو غير ضروري ، عدم التدخل في المجموعة واختار طريقة بسيطة وموثوقة وفعالة لدراسة الأسئلة المطروحة:
كمشكلة تجريبية ، كمثال للتحضير ، اختر MNIST المألوف ( yann.lecun.com/exdb/mnist ) وتصنيفها.
كشبكة تجريبية ، اخترت الشبكة الكلاسيكية ، الموصى بها للمبتدئين ، وهي شبكة نموذجية لفريق KERAS
github.com/keras-team/keras/blob/master/examples/mnist_cnn.py
وقررت إجراء البحث بنفسه بكل بساطة.
دعونا ندرب الشبكة من KERAS بمعيار التوقف مثل عدم وجود زيادة في الدقة في تسلسل الاختبار ، أي تعليم الشبكة حتى تصبح دقة الاختبار أكبر بكثير من دقة التحقق ولا تتحسن دقة التحقق لمدة 15 حقبة. بعبارة أخرى ، توقفت الشبكة عن التعلم وبدأت إعادة التدريب.
من مجموعة بيانات MNIST ، سننشئ 324 مجموعة بيانات جديدة عن طريق تجاهل مجموعات النقاط وسنقوم بتعليم نفس الشبكة على نفس الظروف تمامًا بنفس الأوزان الأولية.
لنبدأ ، أعتقد أنه من الصواب والصحيح وضع كل الكود ، من أول سطر إلى آخر سطر. حتى لو شاهده القراء ، من الواضح ، مرات عديدة.
نقوم بتحميل المكتبات وتحميل مجموعة البيانات mnist ، إذا لم يتم تحميلها بعد.
ثم نقوم بتحويله إلى تنسيق "float32" وتطبيعه إلى النطاق 0. - 1.
التحضير انتهى.
'''Trains a simple convnet on the MNIST dataset.
Gets to 99.25% test accuracy after 12 epochs
(there is still a lot of margin for parameter tuning).
16 seconds per epoch on a GRID K520 GPU.
'''
from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential, load_model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
from keras.optimizers import *
from keras.callbacks import EarlyStopping
import numpy as np
import os
num_classes = 10
# input image dimensions
img_rows, img_cols = 28, 28
# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()
if K.image_data_format() == 'channels_first':
x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
input_shape = (1, img_rows, img_cols)
else:
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= np.max(x_train)
x_test /= np.max(x_test)
XX_test = np.copy(x_test)
XX_train = np.copy(x_train)
YY_test = np.copy(y_test)
YY_train = np.copy(y_train)
print('x_train shape:', XX_train.shape)
print('x_test shape:', XX_test.shape)
دعونا نتذكر في المتغيرات اسم ملفات النموذج والأوزان ، وكذلك دقة وفقدان شبكتنا. هذا ليس في الكود المصدري ، لكنه ضروري للتجربة.
f_model = "./data/mnist_cnn_model.h5"
f_weights = "./data/mnist_cnn_weights.h5"
accu_f = 'accuracy'
loss_f = 'binary_crossentropy'
الشبكة نفسها هي نفسها تمامًا كما في
github.com/keras-team/keras/blob/master/examples/mnist_cnn.py .
احفظ الشبكة والمقاييس على القرص. سنجري جميع محاولات التدريب لدينا بنفس الأوزان الأولية:
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
activation='relu',
input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss=[loss_f], optimizer=Adam(lr=1e-4), metrics=[accu_f])
model.summary()
model.save_weights(f_weights)
model.save(f_model)
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 26, 26, 32) 320
_________________________________________________________________
conv2d_1 (Conv2D) (None, 24, 24, 64) 18496
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 12, 12, 64) 0
_________________________________________________________________
dropout (Dropout) (None, 12, 12, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 9216) 0
_________________________________________________________________
dense (Dense) (None, 128) 1179776
_________________________________________________________________
dropout_1 (Dropout) (None, 128) 0
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0
_________________________________________________________________
لنبدأ التدريب على mnist الأولي للحصول على معيار الكفاءة الأساسية.
x_test = np.copy(XX_test)
x_train = np.copy(XX_train)
s0 = 0
if os.path.isfile(f_model):
model = load_model(f_model)
model.load_weights(f_weights, by_name=False)
step = 0
while True:
fit = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=1,
verbose=0,
validation_data=(x_test, y_test)
)
current_accu = fit.history[accu_f][0]
current_loss = fit.history['loss'][0]
val_accu = fit.history['val_'+accu_f][0]
val_loss = fit.history['val_loss'][0]
print("\x1b[2K","accuracy {0:12.10f} loss {1:12.10f} step {2:5d} val_accu {3:12.10f} val_loss {4:12.10f} ".\
format(current_accu, current_loss, step, val_accu, val_loss), end="\r")
step += 1
if val_accu > max_accu:
s0 = 0
max_accu = val_accu
else:
s0 += 1
if current_accu * 0.995 > val_accu and s0 > 15:
break
else:
print("model not found ")
accuracy 0.9967333078 loss 0.0019656278 step 405 val_accu 0.9916999936 val_loss 0.0054226643
الآن لنبدأ التجربة الرئيسية. نأخذ للتدريب من التسلسل الأصلي جميع الصور المرمزة البالغ عددها 60000 ، وفيها نخرج كل شيء باستثناء المربع 9 × 9. دعنا نحصل على 324 سلسلة تجريبية ونقارن نتيجة تدريب الشبكة عليها بالتدريب على التسلسل الأصلي. نقوم بتدريب نفس الشبكة بنفس الأوزان الأولية.
batch_size = 5000
s0 = 0
max_accu = 0.
for i in range(28 - 9):
for j in range(28 - 9):
print("\ni= ", i, " j= ",j)
x_test = np.copy(XX_test)
x_train = np.copy(XX_train)
x_train[:,:i,:j,:] = 0.
x_test [:,:i,:j,:] = 0.
x_train[:,i+9:,j+9:,:] = 0.
x_test [:,i+9:,j+9:,:] = 0.
if os.path.isfile(f_model):
model = load_model(f_model)
model.load_weights(f_weights, by_name=False)
else:
print("model not found ")
break
step = 0
while True:
fit = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=1,
verbose=0,
validation_data=(x_test, y_test)
)
current_accu = fit.history[accu_f][0]
current_loss = fit.history['loss'][0]
val_accu = fit.history['val_'+accu_f][0]
val_loss = fit.history['val_loss'][0]
print("\x1b[2K","accuracy {0:12.10f} loss {1:12.10f} step {2:5d} val_accu {3:12.10f} val_loss {4:12.10f} ".\
format(current_accu, current_loss, step, val_accu, val_loss), end="\r")
step += 1
if val_accu > max_accu:
s0 = 0
max_accu = val_accu
else:
s0 += 1
if current_accu * 0.995 > val_accu and s0 > 15:
break
ليس من المنطقي نشر جميع النتائج البالغ عددها 324 هنا ، إذا كان أي شخص مهتمًا ، يمكنني إرسالها شخصيًا. يستغرق الحساب عدة أيام ، إذا أراد شخص ما تكراره.
كما اتضح فيما بعد ، يمكن أن تتعلم الشبكة على قصاصة 9x9 على أنها أسوأ ، وهو أمر واضح ، ولكنه أفضل أيضًا ، وهو ليس واضحًا على الإطلاق.
على سبيل المثال:
i = 0 j = 14
دقة 0.9972333312 خسارة 0.0017946947 خطوة 450 val_accu 0.9922000170 val_loss 0.0054322388
i = 18، j = 1
دقة 0.9973166585 خسارة 0.0019487827 خطوة 415 val_accu 0.9922000170 val_loss9 0.0053000450
نتخلص من جميع الصور المكتوبة بخط اليد وأرقام الجودة 9x الاعتراف يتحسن معنا!
من الواضح أيضًا أن هناك أكثر من مجال خاص لتحسين جودة الشبكة. وليس اثنان ، فهذان هما مثالان.
نتيجة هذه التجربة والاستنتاجات الأولية.
- أي مجموعة بيانات طبيعية ، لا أعتقد أن LeCune شوه شيئًا عن عمد ، لا يحتوي فقط على نقاط ضرورية للتعلم ، ولكن أيضًا نقاط تتداخل مع التعلم. تصبح مهمة البحث عن النقاط "الضارة" ملحة ، فهي موجودة ، حتى لو لم تكن مرئية.
- يمكنك التكديس والمزج ليس فقط على طول مجموعة البيانات ، واختيار الصور في مجموعات ، ولكن أيضًا عبر ، وتحديد مناطق الصور للتقسيم ثم كالمعتاد. في هذه الحالة ، يعمل هذا النهج على تحسين جودة التدريب ، وهناك أمل في أن يؤدي استخدام مثل هذا التكديس عبر مهمة مماثلة إلى إضافة الجودة. وعلى نفس kaggle.com ، تسمح لك بضعة أجزاء من عشرة آلاف أحيانًا (دائمًا تقريبًا) بزيادة سلطتك وتصنيفك بشكل كبير.
شكرآ لك على أهتمامك.