أدى التقدم في مجال الشبكات العصبية بشكل عام والتعرف على الأنماط بشكل خاص إلى حقيقة أنه قد يبدو كما لو أن إنشاء تطبيق شبكة عصبية للعمل مع الصور هو مهمة روتينية. بمعنى أنه - إذا توصلت إلى فكرة متعلقة بالتعرف على الأنماط ، فلا تشك في أن شخصًا ما كتب شيئًا من هذا القبيل بالفعل. كل ما هو مطلوب منك هو العثور على الجزء المقابل من الكود في Google و "تجميعه" من المؤلف.
ومع ذلك ، لا تزال هناك العديد من التفاصيل التي تجعل المهمة غير قابلة للحل بقدر ... مملة ، أود أن أقول. يستغرق الكثير من الوقت ، خاصةً إذا كنت مبتدئًا يحتاج إلى القيادة ، خطوة بخطوة ، وهو مشروع تم تنفيذه أمام عينيك مباشرةً ، وتم الانتهاء منه من البداية إلى النهاية. بدون المعتاد في مثل هذه الحالات ، "تخطي هذا الجزء الواضح" الأعذار.
في هذه المقالة ، سننظر في مهمة إنشاء مُعرّف سلالة الكلاب: سنقوم بإنشاء وتدريب شبكة عصبية ، ثم نقلها إلى Java لنظام Android ونشرها على Google Play.
إذا كنت تريد إلقاء نظرة على النتيجة النهائية ، فإليك:
NeuroDog App على Google Play.
موقع على شبكة الإنترنت مع بلدي الروبوتات (في التقدم):
robotics.snowcron.com .
موقع على شبكة الإنترنت مع البرنامج نفسه ، بما في ذلك دليل:
NeuroDog User Guide .
وهنا لقطة من البرنامج:

بيان المشكلة
سنستخدم Keras: مكتبة Google للعمل مع الشبكات العصبية. هذه مكتبة رفيعة المستوى ، مما يعني أنها أسهل في الاستخدام مقارنة بالبدائل التي أعرفها. إذا كان أي شيء - هناك العديد من الكتب المدرسية على Keras في الشبكة ، وذات جودة عالية.
سوف نستخدم CNN - الشبكات العصبية الملتوية. CNN (والتكوينات الأكثر تقدماً القائمة عليها) هي المعيار الفعلي في التعرف على الصور. في الوقت نفسه ، فإن تدريب مثل هذه الشبكة ليس سهلاً دائمًا: تحتاج إلى اختيار بنية الشبكة الصحيحة ، ومعلمات التدريب (كل هذه معدلات التعلم ، والزخم ، و L1 ، و L2 ، إلخ). تتطلب المهمة موارد حسابية كبيرة ، وبالتالي ، لحلها ببساطة عن طريق تصفح جميع المعلمات سوف تفشل.
هذا أحد الأسباب العديدة التي تجعلهم يستخدمون في معظم الحالات ما يسمى بـ "معرفة النقل" ، بدلاً من ما يسمى بنهج "الفانيليا". يستخدم Transfer Knowlege شبكة عصبية تم تدريبها من قِبل شخص ما أمامنا (على سبيل المثال ، Google) وعادةً لمهمة مماثلة ، ولكن لا تزال مختلفة. نأخذ الطبقات الأولية منه ونستبدل الطبقات النهائية بمصنفنا الخاص - ويعمل بنجاح.
في البداية ، قد تكون هذه النتيجة مفاجئة: كيف استقلنا شبكة Google مدربة على تمييز القطط عن الكراسي ، وتعترف بسلالات الكلاب بالنسبة لنا؟ لفهم كيفية حدوث ذلك ، تحتاج إلى فهم المبادئ الأساسية لعمل الشبكات العصبية العميقة ، بما في ذلك تلك المستخدمة للتعرف على الأنماط.
قمنا "بتغذية" صورة الشبكة (مجموعة من الأرقام ، أي) كمدخلات. تحلل الطبقة الأولى الصورة لأنماط بسيطة ، مثل "الخط الأفقي" ، "القوس" ، إلخ. تتلقى الطبقة التالية هذه الأنماط كمدخلات ، وتنتج أنماطًا من الدرجة الثانية ، مثل "fur" ، و "Corner of the eye" ... في النهاية ، نحصل على لغز يمكننا من خلاله إعادة بناء الكلب: صوف ، وعينان ، ويد بشرية في الأسنان.
تم تنفيذ كل ما سبق بمساعدة الطبقات المدربة مسبقًا التي حصلنا عليها (على سبيل المثال ، من Google). بعد ذلك ، نضيف طبقاتنا ، ونعلمهم استخراج معلومات السلالات من هذه الأنماط. يبدو منطقيا.
للتلخيص ، سننشئ في هذا المقال كلاً من CNN "vanilla" وعدة متغيرات "تعلم النقل" من أنواع مختلفة من الشبكات. بالنسبة إلى "الفانيليا": سوف أقوم بإنشائه ، لكنني لا أخطط لتكوينه من خلال تحديد المعلمات ، لأنه من الأسهل بكثير تدريب وتكوين الشبكات "المدربة مسبقًا".
نظرًا لأننا نخطط لتعليم شبكتنا العصبية للتعرف على سلالات الكلاب ، يجب علينا "إظهار" عينات من السلالات المختلفة. لحسن الحظ ، هناك مجموعة من الصور التي تم إنشاؤها
هنا لمهمة مماثلة (
الأصل هنا ).
ثم أخطط لنقل أفضل الشبكات المستلمة لنظام Android. يعد نقل شبكات Kerasov إلى نظام Android بسيطًا نسبيًا وصحيحًا وسنقوم بكل الخطوات اللازمة ، لذلك لن يكون من الصعب إعادة إنتاج هذا الجزء.
ثم سننشر كل هذا على Google Play. بطبيعة الحال ، ستقاوم Google ، لذلك سيتم استخدام حيل إضافية. على سبيل المثال ، سيكون حجم تطبيقنا (بسبب شبكة عصبية ضخمة) أكبر من الحجم المسموح به لـ Android APK المقبول من Google Play: سيتعين علينا استخدام حزم. بالإضافة إلى ذلك ، لن تعرض Google تطبيقنا في نتائج البحث ، ويمكن إصلاح ذلك عن طريق تسجيل علامات البحث في التطبيق ، أو الانتظار ... أسبوع أو أسبوعين فقط.
نتيجة لذلك ، نحصل على تطبيق "تجاري" يعمل بكامل طاقته (بعلامات اقتباس ، كما هو منصوص عليه مجانًا) لنظام Android واستخدام الشبكات العصبية.
بيئة التطوير
يمكنك برمجة Keras بطرق مختلفة ، اعتمادًا على نظام التشغيل الذي تستخدمه (يوصى باستخدام Ubuntu) ، أو وجود بطاقة فيديو أو عدم وجودها ، وما إلى ذلك. لا يوجد شيء سيء في التطوير على الكمبيوتر المحلي (وبالتالي ، التكوين الخاص به) ، إلا أن هذه ليست الطريقة الأسهل.
أولاً ، يستغرق تثبيت عدد كبير من الأدوات والمكتبات وتكوينها وقتًا ، ثم عند إصدار إصدارات جديدة ، سيتعين عليك قضاء الوقت مرة أخرى. ثانياً ، تتطلب الشبكات العصبية طاقة حوسبية كبيرة للتدريب. يمكنك تسريع هذه العملية (بنسبة 10 مرات أو أكثر) إذا كنت تستخدم وحدة معالجة الرسومات ... في وقت كتابة هذا المقال ، فإن أعلى وحدات معالجة الرسومات المناسبة لهذا العمل تكلف 2000 - 7000 دولار. ونعم ، يحتاجون أيضا إلى تكوين.
لذلك سوف نذهب في الاتجاه الآخر. والحقيقة هي أن Google تسمح لقنافذ القنفذ الفقيرة مثلنا باستخدام وحدات معالجة الرسومات من مجموعتهم - مجانًا ، لإجراء العمليات الحسابية المتعلقة بالشبكات العصبية ، كما أنها توفر بيئة مكتملة التجهيز ، وكلها مجتمعة ، وهذا ما يسمى Google Colab. تتيح لك الخدمة الوصول إلى Jupiter Notebook من خلال python و Keras وعدد كبير من المكتبات الأخرى التي تم تكوينها بالفعل. كل ما عليك فعله هو الحصول على حساب Google (احصل على حساب Gmail وهذا سيمنحك حق الوصول إلى كل شيء آخر).
في الوقت الحالي ، يمكن تعيين Colab
هنا ، لكن مع معرفة Google ، يمكن أن يتغير هذا في أي وقت. مجرد جوجل جوجل كولاب.
المشكلة الواضحة في استخدام Colab هي أنها خدمة WEB. كيف يمكننا الوصول إلى البيانات الخاصة بنا؟ حفظ الشبكة العصبية بعد التدريب ، على سبيل المثال ، قم بتنزيل البيانات الخاصة بمهمتنا وما إلى ذلك؟
هناك عدة طرق (في وقت كتابة هذا المقال - ثلاثة) ، نستخدم الطريقة التي أعتقد أنها الأكثر ملاءمة - نستخدم Google Drive.
Google Drive عبارة عن وحدة تخزين بيانات مستندة إلى مجموعة النظراء تعمل بشكل كبير مثل محرك الأقراص الثابتة العادي ، ويمكن تعيينها على Google Colab (انظر الرمز أدناه). بعد ذلك ، يمكنك العمل به كما تفعل مع الملفات الموجودة على القرص المحلي. هذا ، على سبيل المثال ، من أجل الوصول إلى صور الكلاب لتدريب شبكتنا العصبية ، نحتاج إلى تحميلها على Google Drive ، هذا كل شيء.
إنشاء وتدريب شبكة عصبية
أدناه ، أعطي الشفرة في Python ، كتلة تلو الأخرى (من دفتر جوبيتر). يمكنك نسخ هذا الرمز إلى Jupiter Notebook وتشغيله ، كتلة تلو الأخرى ، حيث يمكن تنفيذ الكتل بشكل مستقل (بالطبع ، قد تكون المتغيرات المحددة في الكتلة المبكرة مطلوبة في وقت متأخر ، ولكن هذا تبعية واضحة).
التهيئة
بادئ ذي بدء ، لنقم بتحميل Google Drive. خطين فقط. يجب تنفيذ هذا الرمز مرة واحدة فقط في جلسة Colab (على سبيل المثال ، مرة واحدة كل 6 ساعات). إذا اتصلت بها مرة ثانية بينما كانت الجلسة "حية" ، فسيتم تخطيها لأن محرك الأقراص مثبت بالفعل.
from google.colab import drive drive.mount('/content/drive/')
في البداية ، سيُطلب منك تأكيد نواياك ، لا يوجد شيء معقد. إليك ما يبدو عليه:
>>> Go to this URL in a browser: ... >>> Enter your authorization code: >>> ·········· >>> Mounted at /content/drive/
وتشمل تماما معيار القسم ؛ من المحتمل أن بعض الملفات المضمّنة ليست ضرورية ، حسنًا ... آسف. أيضًا ، بما أنني سأختبر شبكات عصبية مختلفة ، فسوف يتعين عليك تعليق / إلغاء تثبيت بعض الوحدات النمطية المضمّنة لأنواع محددة من الشبكات العصبية: على سبيل المثال ، لاستخدام InceptionV3 NN ، وإلغاء تثبيت إدراج InceptionV3 ، والتعليق ، على سبيل المثال ، ResNet50. أم لا: كل ما يتغير من هذا هو حجم الذاكرة المستخدمة ، وهذا ليس قويًا جدًا.
import datetime as dt import pandas as pd import seaborn as sns import matplotlib.pyplot as plt from tqdm import tqdm import cv2 import numpy as np import os import sys import random import warnings from sklearn.model_selection import train_test_split import keras from keras import backend as K from keras import regularizers from keras.models import Sequential from keras.models import Model from keras.layers import Dense, Dropout, Activation from keras.layers import Flatten, Conv2D from keras.layers import MaxPooling2D from keras.layers import BatchNormalization, Input from keras.layers import Dropout, GlobalAveragePooling2D from keras.callbacks import Callback, EarlyStopping from keras.callbacks import ReduceLROnPlateau from keras.callbacks import ModelCheckpoint import shutil from keras.applications.vgg16 import preprocess_input from keras.preprocessing import image from keras.preprocessing.image import ImageDataGenerator from keras.models import load_model from keras.applications.resnet50 import ResNet50 from keras.applications.resnet50 import preprocess_input from keras.applications.resnet50 import decode_predictions from keras.applications import inception_v3 from keras.applications.inception_v3 import InceptionV3 from keras.applications.inception_v3 import preprocess_input as inception_v3_preprocessor from keras.applications.mobilenetv2 import MobileNetV2 from keras.applications.nasnet import NASNetMobile
على Google Drive ، نقوم بإنشاء مجلد لملفاتنا. يعرض السطر الثاني محتوياته:
working_path = "/content/drive/My Drive/DeepDogBreed/data/" !ls "/content/drive/My Drive/DeepDogBreed/data" >>> all_images labels.csv models test train valid
كما ترون ، يتم حفظ صور الكلاب (التي تم نسخها من مجموعة بيانات Stanford (انظر أعلاه) على Google Drive) أولاً في مجلد
all_images . في وقت لاحق ، سنقوم بنسخها في
القطار ، وأدلة
صالحة واختبار . سنقوم بحفظ النماذج المدربة في مجلد
النماذج . بالنسبة إلى ملف labels.csv ، هذا جزء من مجموعة البيانات مع الصور ، ويحتوي على جدول مراسلات لأسماء الصور وسلالات الكلاب.
هناك العديد من الاختبارات التي يمكنك إجراؤها لفهم ما حصلنا عليه بالضبط للاستخدام المؤقت من Google. على سبيل المثال:
كما ترى ، فإن GPU متصل بالفعل ، وإذا لم يكن الأمر كذلك ، فأنت بحاجة إلى البحث عن هذا الخيار وتمكينه في إعدادات Jupiter Notebook.
بعد ذلك ، نحتاج إلى إعلان بعض الثوابت ، مثل حجم الصور ، إلخ. سنستخدم الصور بحجم 256 × 256 بكسل ، هذه صورة كبيرة بما يكفي حتى لا تفقد التفاصيل ، وصغيرة بما يكفي بحيث يناسب كل شيء الذاكرة. لاحظ ، مع ذلك ، أن بعض أنواع الشبكات العصبية التي سنستخدمها تتوقع الحصول على صور بحجم 224 × 224 بكسل. في مثل هذه الحالات ، نعلق 256 و uncomment 224.
سيتم تطبيق نفس الطريقة (التعليق الأول - عدم الارتياح) على أسماء النماذج التي نقوم بحفظها ، وذلك ببساطة لأننا لا نريد الكتابة فوق الملفات التي قد لا تزال مفيدة.
warnings.filterwarnings("ignore") os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' np.random.seed(7) start = dt.datetime.now() BATCH_SIZE = 16 EPOCHS = 15 TESTING_SPLIT=0.3
تحميل البيانات
بادئ
ذي بدء ، لنقم
بتحميل ملف
labels.csv ونقسمه إلى أجزاء التدريب والتحقق من الصحة. لاحظ أنه لا يوجد جزء اختبار حتى الآن ، لأنني سأغش للحصول على المزيد من بيانات التدريب.
labels = pd.read_csv(working_path + 'labels.csv') print(labels.head()) train_ids, valid_ids = train_test_split(labels, test_size = TESTING_SPLIT) print(len(train_ids), 'train ids', len(valid_ids), 'validation ids') print('Total', len(labels), 'testing images') >>> id breed >>> 0 000bec180eb18c7604dcecc8fe0dba07 boston_bull >>> 1 001513dfcb2ffafc82cccf4d8bbaba97 dingo >>> 2 001cdf01b096e06d78e9e5112d419397 pekinese >>> 3 00214f311d5d2247d5dfe4fe24b2303d bluetick >>> 4 0021f9ceb3235effd7fcde7f7538ed62 golden_retriever >>> 7155 train ids 3067 validation ids >>> Total 10222 testing images
بعد ذلك ، انسخ ملفات الصور إلى مجلدات التدريب / التحقق / الاختبار ، وفقًا لأسماء الملفات. تقوم الوظيفة التالية بنسخ الملفات التي ننقل أسماؤها إلى المجلد المحدد.
def copyFileSet(strDirFrom, strDirTo, arrFileNames): arrBreeds = np.asarray(arrFileNames['breed']) arrFileNames = np.asarray(arrFileNames['id']) if not os.path.exists(strDirTo): os.makedirs(strDirTo) for i in tqdm(range(len(arrFileNames))): strFileNameFrom = strDirFrom + arrFileNames[i] + ".jpg" strFileNameTo = strDirTo + arrBreeds[i] + "/" + arrFileNames[i] + ".jpg" if not os.path.exists(strDirTo + arrBreeds[i] + "/"): os.makedirs(strDirTo + arrBreeds[i] + "/")
كما ترون ، نقوم بنسخ ملف واحد فقط لكل سلالة كلب
كاختبار . أيضًا ، عند النسخ ، نقوم بإنشاء مجلدات فرعية ، واحدة لكل سلالة. وفقا لذلك ، يتم نسخ الصور الفوتوغرافية إلى المجلدات الفرعية حسب السلالة.
يتم ذلك لأن Keras يمكنها العمل مع دليل لهيكل مشابه ، وتحميل ملفات الصور حسب الحاجة ، وليس كل ذلك مرة واحدة ، مما يحفظ الذاكرة. يعد تحميل جميع الصور التي يبلغ عددها 15000 دفعة واحدة فكرة سيئة.
سيتعين علينا استدعاء هذه الوظيفة مرة واحدة فقط ، لأنها تنسخ الصور - ولم تعد هناك حاجة إليها. وفقًا لذلك ، للاستخدام في المستقبل ، يجب أن نعلق عليه:
الحصول على قائمة سلالات الكلاب:
breeds = np.unique(labels['breed']) map_characters = {}
معالجة الصور
سنستخدم ميزة مكتبة Keras التي تسمى ImageDataGenerators. يمكن ImageDataGenerator معالجة الصورة ، والحجم ، تدوير ، وهلم جرا. يمكنه أيضًا قبول وظيفة
معالجة يمكنها معالجة الصور بشكل إضافي.
def preprocess(img): img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation = cv2.INTER_AREA)
انتبه إلى الكود التالي:
يمكننا التطبيع (البيانات الفرعية ضمن النطاق 0-1 بدلاً من 0-255 الأصلي) في ImageDataGenerator نفسه. لماذا إذن نحتاج إلى معالج مسبق؟ على سبيل المثال ، ضع في الاعتبار المكالمة غير الواضحة (علق عليها ، لا أستخدمها): هذا هو نفس التلاعب بالصورة المخصصة الذي يمكن أن يكون تعسفيًا. أي شيء من النقيض من HDR.
سوف نستخدم اثنين من ImageDataGenerators ، واحد للتدريب والآخر للتحقق من الصحة. الفرق هو أننا في التدريب نحتاج إلى دورات وتحجيم لزيادة "تنوع" البيانات ، لكن من أجل التحقق من الصحة ، لا نحتاج إليها ، على الأقل ليس في هذه المهمة.
train_datagen = ImageDataGenerator( preprocessing_function=preprocess,
إنشاء شبكة عصبية
كما ذكرنا سابقًا ، سنقوم بإنشاء عدة أنواع من الشبكات العصبية. في كل مرة ندعو وظيفة أخرى لإنشاء ، وتشمل الملفات الأخرى وأحيانا تحديد حجم صورة مختلفة. لذلك ، للتبديل بين أنواع مختلفة من الشبكات العصبية ، يجب أن نعلق / نلاحظ أن الكود المناسب.
بادئ ذي بدء ، قم بإنشاء CNN "فانيليا". لا يعمل هذا بشكل جيد ، لأنني قررت عدم تضييع الوقت في تصحيحه ، ولكنه على الأقل يوفر أساسًا يمكن تطويره إذا كانت هناك رغبة (عادة ما تكون هذه فكرة سيئة ، لأن الشبكات المدربة مسبقًا تعطي أفضل النتائج).
def createModelVanilla(): model = Sequential()
عندما ننشئ شبكات باستخدام
تعلم النقل ، يتغير الإجراء:
def createModelMobileNetV2():
إنشاء أنواع أخرى من الشبكات يتبع نفس النمط:
def createModelResNet50(): base_model = ResNet50(weights='imagenet', include_top=False, pooling='avg', input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3)) x = base_model.output x = Dense(512)(x) x = Activation('relu')(x) x = Dropout(0.5)(x) predictions = Dense(NUM_CLASSES, activation='softmax')(x) model = Model(inputs=base_model.input, outputs=predictions)
تحذير: الفائز! أظهر هذا NN أفضل نتيجة:
def createModelInceptionV3():
واحد آخر:
def createModelNASNetMobile():
يمكن استخدام أنواع مختلفة من الشبكات العصبية للقيام بمهام مختلفة. لذلك ، بالإضافة إلى متطلبات دقة التنبؤ ، يمكن أن يكون الحجم مهمًا (يكون NN المحمول أصغر بخمس مرات من التأسيس) والسرعة (إذا احتجنا إلى معالجة دفق الفيديو في الوقت الفعلي ، فسيتعين التضحية بالدقة).
تدريب الشبكة العصبية
بادئ ذي بدء ، نحن نجري
تجارب ، لذلك يجب أن نكون قادرين على إزالة الشبكات العصبية التي قمنا بحفظها ، لكننا لم نعد نستخدمها. الوظيفة التالية تزيل NN إذا كانت موجودة:
طريقة إنشاء الشبكات العصبية وحذفها بسيطة ومباشرة. أولا ، حذف. عند الاتصال
بالحذف (فقط) ، يجب أن يؤخذ في الاعتبار أن Jupiter Notebook لديه وظيفة "اختيار التشغيل" ، حدد فقط ما تريد استخدامه ، وقم بتشغيله.
ثم نقوم بإنشاء شبكة عصبية إذا لم يكن ملفها موجودًا ، أو
تحميل المكالمة إذا كان موجودًا: بالطبع ، لا يمكننا استدعاء "حذف" ، ثم نتوقع وجود NN ، لذلك لاستخدام شبكة عصبية محفوظة ، لا تقم باستدعاء
حذف .
بمعنى آخر ، يمكننا إنشاء NN جديد ، أو استخدام NN الحالي ، اعتمادًا على الموقف وعلى ما نجربه حاليًا. سيناريو بسيط: قمنا بتدريب شبكة عصبية ، ثم ذهبنا في إجازة. عادوا ، وسمّت Google الجلسة ، لذا نحتاج إلى تحميل الجلسة المحفوظة مسبقًا: علق على "حذف" و "تحميل".
deleteSavedNet(working_path + strModelFileName)
نقاط التفتيش هي عنصر مهم للغاية في برنامجنا. يمكننا إنشاء مجموعة من الوظائف التي ينبغي استدعاؤها في نهاية كل حقبة من التدريب ، وتمريرها إلى نقطة التفتيش. على سبيل المثال ، يمكنك حفظ شبكة عصبية
إذا كانت تظهر نتائج أفضل من تلك المحفوظة بالفعل.
checkpoint = ModelCheckpoint(working_path + strModelFileName, monitor='val_acc', verbose=1, save_best_only=True, mode='auto', save_weights_only=False) callbacks_list = [ checkpoint ]
أخيرًا ، نقوم بتدريس الشبكة العصبية على مجموعة التدريب:
الرسوم البيانية للدقة والخسارة لأفضل التكوينات هي كما يلي:


كما ترون ، فإن الشبكة العصبية تتعلم ، وليست سيئة.
اختبار الشبكة العصبية
بعد الانتهاء من التدريب ، يجب علينا اختبار النتيجة ؛ لهذا ، تقدم NN الصور التي لم ترها من قبل - تلك التي قمنا بنسخها في مجلد الاختبار - واحدة لكل سلالة كلب.
تصدير شبكة العصبية إلى تطبيق جافا
بادئ ذي بدء ، نحن بحاجة إلى تنظيم تحميل الشبكة العصبية من القرص. السبب واضح: يتم التصدير في مجموعة أخرى من التعليمات البرمجية ، لذلك على الأرجح سنبدأ التصدير بشكل منفصل - عندما يتم توصيل الشبكة العصبية إلى حالتها المثلى. وهذا هو ، قبل التصدير مباشرة ، في نفس تشغيل البرنامج ، لن نقوم بتدريب الشبكة. إذا استخدمت الشفرة الموضحة هنا ، فلا فرق ، فقد تم اختيار الشبكة المثالية لك. ولكن إذا كنت تتعلم شيئًا خاصًا بك ، فإن تدريب كل شيء من جديد قبل الادخار يعد مضيعة للوقت ، إذا كنت قبل ذلك تحفظ كل شيء.
للسبب نفسه - عدم القفز فوق الرمز - أقوم بتضمين الملفات اللازمة للتصدير هنا. لا أحد يزعجك لنقلهم إلى بداية البرنامج إذا كان شعورك بالجمال يتطلب ذلك:
from keras.models import Model from keras.models import load_model from keras.layers import * import os import sys import tensorflow as tf
اختبار صغير بعد تحميل الشبكة العصبية ، فقط للتأكد من تحميل كل شيء - يعمل:
img = image.load_img(working_path + "test/affenpinscher.jpg")

بعد ذلك ، نحتاج إلى الحصول على أسماء طبقات الإدخال والإخراج للشبكة (إما هذه أو وظيفة الإنشاء ، يجب أن "نذكر" الطبقات بشكل صريح ، وهو ما لم نفعله).
model.summary() >>> Layer (type) >>> ====================== >>> input_7 (InputLayer) >>> ______________________ >>> conv2d_283 (Conv2D) >>> ______________________ >>> ... >>> dense_14 (Dense) >>> ====================== >>> Total params: 22,913,432 >>> Trainable params: 1,110,648 >>> Non-trainable params: 21,802,784
سنستخدم أسماء طبقات المدخلات والمخرجات فيما بعد عندما نستورد الشبكة العصبية في تطبيق Java.
رمز آخر يتجول في الشبكة للحصول على هذه البيانات:
def print_graph_nodes(filename): g = tf.GraphDef() g.ParseFromString(open(filename, 'rb').read()) print() print(filename) print("=======================INPUT===================") print([n for n in g.node if n.name.find('input') != -1]) print("=======================OUTPUT==================") print([n for n in g.node if n.name.find('output') != -1]) print("===================KERAS_LEARNING==============") print([n for n in g.node if n.name.find('keras_learning_phase') != -1]) print("===============================================") print()
.
Keras Neural Network
pb , , Android.
def keras_to_tensorflow(keras_model, output_dir, model_name,out_prefix="output_", log_tensorboard=True): if os.path.exists(output_dir) == False: os.mkdir(output_dir) out_nodes = [] for i in range(len(keras_model.outputs)): out_nodes.append(out_prefix + str(i + 1)) tf.identity(keras_model.output[i], out_prefix + str(i + 1)) sess = K.get_session() from tensorflow.python.framework import graph_util from tensorflow.python.framework graph_io init_graph = sess.graph.as_graph_def() main_graph = graph_util.convert_variables_to_constants( sess, init_graph, out_nodes) graph_io.write_graph(main_graph, output_dir, name=model_name, as_text=False) if log_tensorboard: from tensorflow.python.tools import import_pb_to_tensorboard import_pb_to_tensorboard.import_to_tensorboard( os.path.join(output_dir, model_name), output_dir)
:
model = load_model(working_path + strModelFileName) keras_to_tensorflow(model, output_dir=working_path + strModelFileName, model_name=working_path + "models/dogs.pb") print_graph_nodes(working_path + "models/dogs.pb")
.
Android
Android . , , , ( ) .
, Android Studio . « », — . activity.

, «assets» (, ).
Gradle
. ,
tensorflow-android . , Tensorflow (, , Keras) Java:

:
versionCode versionName . , Google Play. gdadle (, 1 -> 2 -> 3...) , « ».
, «» — 100 Mb Neural Network , instance «» Facebook .
instance :
<activity android:name=".MainActivity" android:launchMode="singleTask">
android:launchMode=«singleTask» MainActivity, Android, () , , instance.
, , - «» :
<intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-filter>
, , :
<uses-feature android:name="android.hardware.camera" android:required="true" /> <uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
Android, .
Layout .
layouts, , .
Portrait layout .
: (view) , (, «»), «Help», File/Gallery , ( ) «Process» .

, enabling/disabling , .
MainActivity
activity (extends) Android Activity:
public class MainActivity extends Activity
, .
, Bitmap. , Bitmap ( ) (m_bitmap), , 256x256 (m_bitmapForNn). (256) :
static Bitmap m_bitmap = null; static Bitmap m_bitmapForNn = null; private int m_nImageSize = 256;
; (. ), , :
private String INPUT_NAME = "input_7_1"; private String OUTPUT_NAME = "output_1";
TensofFlow. , ( assets):
private TensorFlowInferenceInterface tf;
private String MODEL_PATH =
"file:///android_asset/dogs.pb";
, , :
private String[] m_arrBreedsArray;
, Bitmap. , RGB , — , — , . , (, 120 , ):
private float[] m_arrPrediction = new float[120]; private float[] m_arrInput = null;
tensorflow inference library:
static { System.loadLibrary("tensorflow_inference"); }
, , , « », .
class PredictionTask extends AsyncTask<Void, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); }
In onCreate() of the MainActivity, we need to add the onClickListener for the «Process» button:
m_btn_process.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { processImage(); } });
processImage() , :
private void processImage() { try { enableControls(false);
UI- , . , .
instances , (flow of control): «» Facebook, , . , «» onCreate , onCreate .
:
1. onCreate MainActivity, onSharedIntent:
protected void onCreate( Bundle savedInstanceState) { super.onCreate(savedInstanceState); .... onSharedIntent(); ....
onNewIntent:
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); onSharedIntent(); }
onSharedIntent:
private void onSharedIntent() { Intent receivedIntent = getIntent(); String receivedAction = receivedIntent.getAction(); String receivedType = receivedIntent.getType(); if (receivedAction.equals(Intent.ACTION_SEND)) {
onCreate ( ) onNewIntent ( ).
! , , «» , «»
.