الذكاء الاصطناعي مقابل الكذب والخداع

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

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

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

لذلك دعونا نبدأ!

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

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

أمثلة عشوائية 10



أمثلة عشوائية 10 ، ولكن من العلامات الخاطئة. القناع العلوي صحيح ، القناع السفلي خاطئ ، والأرقام في تسلسل التدريب موضحة في الصور.



بالنسبة للتجزئة ، نأخذ نفس برامج حساب الخسارة المترية ونفس شبكة U البسيطة ، لكننا لن نستخدم Dropout.

المكتبات
import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import NoNorm %matplotlib inline import math from tqdm import tqdm #from joblib import Parallel, delayed from skimage.draw import ellipse, polygon from keras import Model from keras.optimizers import Adam from keras.layers import Input,Conv2D,Conv2DTranspose,MaxPooling2D,concatenate from keras.layers import BatchNormalization,Activation,Add,Dropout from keras.losses import binary_crossentropy from keras import backend as K from keras.models import load_model import tensorflow as tf import keras as keras w_size = 128 train_num = 10000 radius_min = 10 radius_max = 30 


وظائف المتري والخسارة
 def dice_coef(y_true, y_pred): y_true_f = K.flatten(y_true) y_pred = K.cast(y_pred, 'float32') y_pred_f = K.cast(K.greater(K.flatten(y_pred), 0.5), 'float32') intersection = y_true_f * y_pred_f score = 2. * K.sum(intersection) / (K.sum(y_true_f) + K.sum(y_pred_f)) return score def dice_loss(y_true, y_pred): smooth = 1. y_true_f = K.flatten(y_true) y_pred_f = K.flatten(y_pred) intersection = y_true_f * y_pred_f score = (2. * K.sum(intersection) + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth) return 1. - score def bce_dice_loss(y_true, y_pred): return binary_crossentropy(y_true, y_pred) + dice_loss(y_true, y_pred) def get_iou_vector(A, B): # Numpy version batch_size = A.shape[0] metric = 0.0 for batch in range(batch_size): t, p = A[batch], B[batch] true = np.sum(t) pred = np.sum(p) # deal with empty mask first if true == 0: metric += (pred == 0) continue # non empty mask case. Union is never empty # hence it is safe to divide by its number of pixels intersection = np.sum(t * p) union = true + pred - intersection iou = intersection / union # iou metrric is a stepwise approximation of the real iou over 0.5 iou = np.floor(max(0, (iou - 0.45)*20)) / 10 metric += iou # teake the average over all images in batch metric /= batch_size return metric def my_iou_metric(label, pred): # Tensorflow version return tf.py_func(get_iou_vector, [label, pred > 0.5], tf.float64) from keras.utils.generic_utils import get_custom_objects get_custom_objects().update({'bce_dice_loss': bce_dice_loss }) get_custom_objects().update({'dice_loss': dice_loss }) get_custom_objects().update({'dice_coef': dice_coef }) get_custom_objects().update({'my_iou_metric': my_iou_metric }) 


عادي U- صافي
 def build_model(input_layer, start_neurons): # 128 -> 64 conv1 = Conv2D(start_neurons * 1, (3, 3), activation="relu", padding="same")(input_layer) conv1 = Conv2D(start_neurons * 1, (3, 3), activation="relu", padding="same")(conv1) pool1 = Conv2D(start_neurons * 1, (2, 2), strides=(2, 2), activation="relu", padding="same")(conv1) # pool1 = Dropout(0.25)(pool1) # 64 -> 32 conv2 = Conv2D(start_neurons * 2, (3, 3), activation="relu", padding="same")(pool1) conv2 = Conv2D(start_neurons * 2, (3, 3), activation="relu", padding="same")(conv2) pool2 = Conv2D(start_neurons * 1, (2, 2), strides=(2, 2), activation="relu", padding="same")(conv2) # pool2 = Dropout(0.5)(pool2) # 32 -> 16 conv3 = Conv2D(start_neurons * 4, (3, 3), activation="relu", padding="same")(pool2) conv3 = Conv2D(start_neurons * 4, (3, 3), activation="relu", padding="same")(conv3) pool3 = Conv2D(start_neurons * 1, (2, 2), strides=(2, 2), activation="relu", padding="same")(conv3) # pool3 = Dropout(0.5)(pool3) # 16 -> 8 conv4 = Conv2D(start_neurons * 8, (3, 3), activation="relu", padding="same")(pool3) conv4 = Conv2D(start_neurons * 8, (3, 3), activation="relu", padding="same")(conv4) pool4 = Conv2D(start_neurons * 1, (2, 2), strides=(2, 2), activation="relu", padding="same")(conv4) # pool4 = Dropout(0.5)(pool4) # Middle convm = Conv2D(start_neurons * 16, (3, 3), activation="relu", padding="same")(pool4) convm = Conv2D(start_neurons * 16, (3, 3) , activation="relu", padding="same")(convm) # 8 -> 16 deconv4 = Conv2DTranspose(start_neurons * 8, (3, 3), strides=(2, 2), padding="same")(convm) uconv4 = concatenate([deconv4, conv4]) # uconv4 = Dropout(0.5)(uconv4) uconv4 = Conv2D(start_neurons * 8, (3, 3) , activation="relu", padding="same")(uconv4) uconv4 = Conv2D(start_neurons * 8, (3, 3) , activation="relu", padding="same")(uconv4) # 16 -> 32 deconv3 = Conv2DTranspose(start_neurons * 4, (3, 3), strides=(2, 2), padding="same")(uconv4) uconv3 = concatenate([deconv3, conv3]) # uconv3 = Dropout(0.5)(uconv3) uconv3 = Conv2D(start_neurons * 4, (3, 3) , activation="relu", padding="same")(uconv3) uconv3 = Conv2D(start_neurons * 4, (3, 3) , activation="relu", padding="same")(uconv3) # 32 -> 64 deconv2 = Conv2DTranspose(start_neurons * 2, (3, 3), strides=(2, 2), padding="same")(uconv3) uconv2 = concatenate([deconv2, conv2]) # uconv2 = Dropout(0.5)(uconv2) uconv2 = Conv2D(start_neurons * 2, (3, 3) , activation="relu", padding="same")(uconv2) uconv2 = Conv2D(start_neurons * 2, (3, 3) , activation="relu", padding="same")(uconv2) # 64 -> 128 deconv1 = Conv2DTranspose(start_neurons * 1, (3, 3), strides=(2, 2), padding="same")(uconv2) uconv1 = concatenate([deconv1, conv1]) # uconv1 = Dropout(0.5)(uconv1) uconv1 = Conv2D(start_neurons * 1, (3, 3) , activation="relu", padding="same")(uconv1) uconv1 = Conv2D(start_neurons * 1, (3, 3) , activation="relu", padding="same")(uconv1) # uncov1 = Dropout(0.5)(uconv1) output_layer = Conv2D(1, (1,1), padding="same", activation="sigmoid")(uconv1) return output_layer input_layer = Input((w_size, w_size, 1)) output_layer = build_model(input_layer, 27) model = Model(input_layer, output_layer) model.compile(loss=bce_dice_loss, optimizer=Adam(lr=1e-4), metrics=[my_iou_metric]) model.summary() 


برنامج لتوليد الصور والأقنعة - صحيح وكاذب. يتم وضع الطبقة الأولى من الصورة في الصفيف ، والثاني هو القناع الحقيقي ، بينما الطبقة الثالثة هي القناع الكاذب.

 def next_pair_f(idx): img_l = np.ones((w_size, w_size, 1), dtype='float')*0.45 img_h = np.ones((w_size, w_size, 1), dtype='float')*0.55 img = np.zeros((w_size, w_size, 3), dtype='float') i0_qua = math.trunc(np.random.sample()*4.) i1_qua = math.trunc(np.random.sample()*4.) while i0_qua == i1_qua: i1_qua = math.trunc(np.random.sample()*4.) _qua = np.int(w_size/4) qua = np.array([[_qua,_qua],[_qua,_qua*3],[_qua*3,_qua*3],[_qua*3,_qua]]) p = np.random.sample() - 0.5 r = qua[i0_qua,0] c = qua[i0_qua,1] r_radius = np.random.sample()*(radius_max-radius_min) + radius_min c_radius = np.random.sample()*(radius_max-radius_min) + radius_min rot = np.random.sample()*360 rr, cc = ellipse( r, c, r_radius, c_radius, rotation=np.deg2rad(rot), shape=img_l.shape ) p0 = np.rint(np.random.sample()*(radius_max-radius_min) + radius_min) p1 = qua[i1_qua,0] - (radius_max-radius_min) p2 = qua[i1_qua,1] - (radius_max-radius_min) p3 = np.rint(np.random.sample()*radius_min) p4 = np.rint(np.random.sample()*radius_min) p5 = np.rint(np.random.sample()*radius_min) p6 = np.rint(np.random.sample()*radius_min) p7 = np.rint(np.random.sample()*radius_min) p8 = np.rint(np.random.sample()*radius_min) poly = np.array(( (p1, p2), (p1+p3, p2+p4+p0), (p1+p5+p0, p2+p6+p0), (p1+p7+p0, p2+p8), (p1, p2), )) rr_p, cc_p = polygon(poly[:, 0], poly[:, 1], img_l.shape) if p > 0: img[:,:,:1] = img_l.copy() img[rr, cc,:1] = img_h[rr, cc] img[rr_p, cc_p,:1] = img_h[rr_p, cc_p] else: img[:,:,:1] = img_h.copy() img[rr, cc,:1] = img_l[rr, cc] img[rr_p, cc_p,:1] = img_l[rr_p, cc_p] img[:,:,1] = 0. img[:,:,1] = 0. img[rr_p, cc_p,1] = 1. img[:,:,2] = 0. p_f = np.random.sample()*1000. if p_f > 10: img[rr_p, cc_p,2] = 1. else: img[rr, cc,2] = 1. i_false[idx] = 1 return img 

الغش برنامج حساب ورقة
 def make_sh(f_imgs, f_msks, val_len): precision = 0.85 batch_size = 50 t = tqdm() t_batch_size = 50 raw_len = val_len id_train = 1 #id_select = 1 v_false = np.zeros((train_num), dtype='float') while True: if id_train == 1: fit = model.fit(f_imgs[m2_select>0], f_msks[m2_select>0], batch_size=batch_size, epochs=1, verbose=0 ) current_accu = fit.history['my_iou_metric'][0] current_loss = fit.history['loss'][0] if current_accu > precision: id_train = 0 else: t_pred = model.predict( f_imgs[raw_len: min(raw_len+t_batch_size,f_imgs.shape[0])], batch_size=batch_size ) for kk in range(t_pred.shape[0]): val_iou = get_iou_vector( f_msks[raw_len+kk].reshape(1,w_size,w_size,1), t_pred[kk].reshape(1,w_size,w_size,1) > 0.5) v_false[raw_len+kk] = val_iou if val_iou < precision*0.95: new_img_test = 1 m2_select[raw_len+kk] = 1 val_len += 1 break raw_len += (kk+1) id_train = 1 t.set_description("Accuracy {0:6.4f} loss {1:6.4f} selected img {2:5d} tested img {3:5d} ". format(current_accu, current_loss, val_len, raw_len)) t.update(1) if raw_len >= train_num: break t.close() return v_false 


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

 i_false = np.zeros((train_num), dtype='int') 

هناك قناع مؤشر خاطئ. إذا كان 1 ، فإن القناع من F_msks لا يطابق القناع من f_msks. هذا مؤشر على ما نبحث عنه بالفعل - أقنعة زائفة.

 m2_select = np.zeros((train_num), dtype='int') 

مؤشر على أن هذه الصورة محددة في ورقة الغش.

 batch_size = 50 val_len = batch_size + 1 # i_false - false mask marked as 1 i_false = np.zeros((train_num), dtype='int') # t_imgs, t_msks -test images and masks _txy = [next_pair_f(idx) for idx in range(train_num)] t_imgs = np.array(_txy)[:,:,:,:1].reshape(-1,w_size ,w_size ,1) t_msks = np.array(_txy)[:,:,:,1].reshape(-1,w_size ,w_size ,1) # m2_select - initial 51 pair m2_select = np.zeros((train_num), dtype='int') for k in range(val_len): m2_select[k] = 1 # i_false - false mask marked as 1 i_false = np.zeros((train_num), dtype='int') _txy = [next_pair_f(idx) for idx in range(train_num)] f_imgs = np.array(_txy)[:,:,:,:1].reshape(-1,w_size ,w_size ,1) f_msks = np.array(_txy)[:,:,:,1].reshape(-1,w_size ,w_size ,1) # F_msks - mask array with ~1% false mask F_msks = np.array(_txy)[:,:,:,2].reshape(-1,w_size ,w_size ,1) fig, axes = plt.subplots(2, 10, figsize=(20, 5)) for k in range(10): kk = np.random.randint(train_num) axes[0,k].set_axis_off() axes[0,k].imshow(f_imgs[kk].squeeze(), cmap="gray", norm=NoNorm()) axes[1,k].set_axis_off() axes[1,k].imshow(f_msks[kk].squeeze(), cmap="gray", norm=NoNorm()) plt.show(block=True) false_num = np.arange(train_num)[i_false>0] fig, axes = plt.subplots(3, 10, figsize=(20, 7)) for k in range(10): kk = np.random.randint(false_num.shape[0]) axes[0,k].set_axis_off() axes[0,k].set_title(false_num[kk]) axes[0,k].imshow(f_imgs[false_num[kk]].squeeze(), cmap="gray", norm=NoNorm()) axes[1,k].set_axis_off() axes[1,k].imshow(f_msks[false_num[kk]].squeeze(), cmap="gray", norm=NoNorm()) axes[2,k].set_axis_off() axes[2,k].imshow(F_msks[false_num[kk]].squeeze(), cmap="gray", norm=NoNorm()) plt.show(block=True) 

نحن نبني تسلسل أزواج صورة / قناع للتدريب وتسلسل آخر للاختبار. أي سوف نتحقق من تسلسل جديد ومستقل يتكون من 10000 زوج. نعرض بصريًا الصور العشوائية ونفحصها بشكل انتقائي باستخدام أقنعة صحيحة وكاذبة. وتظهر الصور أعلاه.

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

نبدأ التدريب على المجموعة الصحيحة ، استخدم f_msks كقناع

 input_layer = Input((w_size, w_size, 1)) output_layer = build_model(input_layer, 25) model = Model(input_layer, output_layer) model.compile(loss=bce_dice_loss, optimizer=Adam(lr=1e-4), metrics=[my_iou_metric]) v_false = make_sh(f_imgs, f_msks, val_len) t_pred = model.predict(t_imgs,batch_size=batch_size) print (get_iou_vector(t_msks,t_pred.reshape(-1,w_size ,w_size ,1))) 

 Accuracy 0.9807 loss 0.0092 selected img 404 tested img 10000 : : 1801it [08:13, 3.65it/s] 0.9895299999999841 

تحولت ورقة الغش في 404 صورة فقط وحصلت على دقة مقبولة على تسلسل اختبار مستقل.

نحن الآن نعيد ترجمة الشبكة ونتدرب على نفس تسلسل التدريب ، لكن كأقنعة نقوم بإطعام F_msks بأقنعة كاذبة بنسبة 1٪ على الإدخال

 input_layer = Input((w_size, w_size, 1)) output_layer = build_model(input_layer, 25) model = Model(input_layer, output_layer) model.compile(loss=bce_dice_loss, optimizer=Adam(lr=1e-4), metrics=[my_iou_metric]) v_false = make_sh(f_imgs, F_msks, val_len) t_pred = model.predict(t_imgs,batch_size=batch_size) print (get_iou_vector(t_msks,t_pred.reshape(-1,w_size ,w_size ,1))) 

 Accuracy 0.9821 loss 0.0324 selected img 727 tested img 10000 : : 1679it [25:44, 1.09it/s] 0.9524099999999959 

حصلنا على ورقة غش مكونة من 727 صورة ، وهي أكبر بكثير وانخفضت دقة تنبؤات الاختبار ، كما في تسلسل الاختبار السابق ، من 0.98953 إلى 0.9525. أضفنا الأكاذيب إلى التسلسل التدريبي بنسبة أقل من 1 ٪ ، 93 فقط من أصل 10،000 أقنعة كانت خاطئة ، ولكن النتيجة تفاقمت بنسبة 3.7 ٪. وهذه ليست مجرد كذبة ، بل هي الماكرة الحقيقية! وزادت ورقة الغش من 404 فقط إلى 727 صورة بالفعل.

مهدئا وإرضاء شيء واحد فقط

 print (len(set(np.arange(train_num)[m2_select>0]).intersection(set(np.arange(train_num)[i_false>0])))) 93 

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

تم تبسيط المهمة بشكل كبير ، حيث لا يتم البحث عن 10000 صورة يدويًا ، فهي فقط 727 وكل الأكاذيب تتركز هنا.

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

 print (len(set(np.arange(train_num)[v_false<0.01]).intersection(set(np.arange(train_num)[i_false>0])))) 89 


كما ترون الجزء الرئيسي من الأقنعة الكاذبة ، 89 من 93 ، سقطت في هذه الأقنعة
 np.arange(train_num)[v_false<0.01].shape (382,) 

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

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

لتلخيص


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

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

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


All Articles