Кіріспе
TensorFlow және Keras қолданбаларының ең көп таралған түрлерінің бірі кескінді тану және жіктеу болып табылады. Кескінді жіктеу немесе тану үшін Keras қолданбасын қалай пайдалану керектігін білгіңіз келсе, бұл мақала сізге қалай әрекет ететінін үйретеді.
Анықтамалар
Егер сіз кескінді танудың негізгі ұғымдарын түсінбесеңіз, осы мақаланың негізгі бөлігін толық түсіну қиын болады. Сонымен, жалғастырмас бұрын, кейбір терминологияны анықтайық.
TensorFlow / Керас
TensorFlow — Google Brain командасымен Python үшін жасалған ашық бастапқы кітапхана. TensorFlow көптеген әртүрлі алгоритмдер мен модельдерді құрастырады, бұл пайдаланушыға кескінді тану және жіктеу және табиғи тілді өңдеу сияқты тапсырмаларда пайдалану үшін терең нейрондық желілерді енгізуге мүмкіндік береді. TensorFlow — әрқайсысы математикалық операцияны білдіретін өңдеу түйіндерінің қатарын жүзеге асыру арқылы жұмыс істейтін қуатты құрылым және түйіндердің барлық сериясы «график» деп аталады.
Keras туралы айтатын болсақ, бұл TensorFlow функцияларын (сонымен қатар Theano сияқты басқа ML кітапханалары) пайдалана алатын жоғары деңгейлі API (Application Programming Interface). Керас оның жетекші қағидалары ретінде ыңғайлылық пен модульдікпен жасалған. Практикалық тұрғыдан алғанда, Keras TensorFlow-тың көптеген қуатты, бірақ жиі күрделі мүмкіндіктерін мүмкіндігінше қарапайым етеді және Python бағдарламасымен ешқандай үлкен өзгерістер мен түзетулерсіз жұмыс істеуге конфигурацияланған.
Суретті тану (классификация)
Кескінді тану нейрондық желіге кескінді енгізу және сол кескінге қандай да бір белгіні тағайындау тапсырмасын білдіреді. Желі шығаратын белгі алдын ала анықталған сыныпқа сәйкес келеді. Оған бірден бірнеше сыныпты да, тек біреуін де тағайындауға болады. Бір ғана класс болса, әдетте «тану» термині қолданылады, ал бірнеше класстарды тану міндеті көбінесе «жіктеу» деп аталады.
Кескін классификацияларының ішкі жиыны қазірдің өзінде объектілердің белгілі бір даналары жануарлар, көліктер немесе адамдар сияқты белгілі бір сыныпқа жататындығы анықталған кездегі нысандардың анықтамасы болып табылады.
Мұндай классификацияның жарқын мысалы - Google-дан ең көп таралған captcha - ReCaptcha v2 шешімі, мұнда суреттер жинағынан тек сипаттамада көрсетілген сыныпқа жататындарды таңдау керек.
Шығару функциясы
Кескінді тану немесе жіктеуді орындау үшін нейрондық желі мүмкіндіктерді шығаруды орындауы керек. Мүмкіндіктер - максималды қызығушылық тудыратын және нейрондық желі арқылы берілетін деректер элементтері. Кескінді танудың нақты жағдайында мұндай мүмкіндіктер желі үлгі үшін талдайтын сызықтар мен нүктелер сияқты пикселдер топтары болып табылады.
Функцияны тану (немесе мүмкіндікті шығару) кіріс кескіннен тиісті мүмкіндіктерді талдауға болатындай етіп шығару процесі. Көптеген кескіндерде нейрондық желіге сәйкес мүмкіндіктерді табуға көмектесетін аннотациялар немесе метадеректер бар.
Нейрондық желілер кескіндерді тануды қалай үйренеді
Нейрондық желінің кескіндерді қалай танитынын түсіну сізге нейрондық желі үлгісін енгізу кезінде көмектеседі, сондықтан келесі бөлімдерде кескінді тану процесін жылдам қарастырайық.
Сүзгілер арқылы мүмкіндіктерді шығару
Нейрондық желінің бірінші қабаты кескіндегі барлық пикселдерді қабылдайды. Барлық деректер желіге енгізілгеннен кейін кескінге әртүрлі сүзгілер қолданылады, олар кескіннің әртүрлі бөліктері туралы түсінікті қалыптастырады. Бұл «мүмкіндік карталарын» жасайтын мүмкіндіктерді шығару.
Кескіннен ерекшеліктерді алудың бұл процесі «конволюциялық қабат» арқылы орындалады және конволюция жай ғана кескін бөлігінің көрінісін құрайды. Дәл осы конволюция тұжырымдамасынан біз конволюционды нейрондық желі (CNN) терминін аламыз, бұл нейрондық желі түрі кескінді жіктеу мен тануда жиі қолданылады.
Функцияларды салыстыру қалай жұмыс істейтінін көргіңіз келсе, қараңғы бөлмедегі суретке фонарь ұстап тұрғаныңызды елестетіңіз. Сәулені суреттің үстінен сырғытқанда суреттің ерекшеліктерімен танысасыз. Сүзгі - бұл желі кескіннің көрінісін қалыптастыру үшін пайдаланатын нәрсе және бұл метафорада фонардан түсетін жарық сүзгі болып табылады.
Шамның сәулесінің ені сіз бір уақытта көретін кескін бөлігінің өлшемін анықтайды және нейрондық желілерде ұқсас параметр бар - сүзгі өлшемі. Сүзгі өлшемі бір уақытта қанша пиксель тексерілетініне әсер етеді. CNN-де қолданылатын сүзгінің жалпы өлшемі 3 және ол биіктігі мен енін қамтиды, сондықтан сүзгі 3 x 3 пиксель аймағын тексереді.
Сүзгі өлшемі сүзгінің биіктігі мен енін қамтитынымен, сүзгінің тереңдігі де көрсетілуі керек.
Бірақ 2D кескіннің тереңдігі қалай болуы мүмкін?
Мәселе мынада, сандық кескіндер биіктік, ені және пикселдің түсін анықтайтын кейбір RGB мәні ретінде көрсетіледі, сондықтан бақыланатын «тереңдік» кескіндегі түс арналарының саны болып табылады. Сұр реңкті (түрлі-түсті емес) кескіндерде тек 1 түсті арна болады, ал түсті кескіндерде 3 арна тереңдігі бар.
Мұның бәрі толық түсті кескінге қолданылатын 3 өлшемді сүзгі үшін бұл сүзгінің соңғы өлшемдері 3 x 3 x 3 болатынын білдіреді. Осы сүзгі қамтитын әрбір пиксел үшін желі сүзгі мәндерін келесіге көбейтеді. пикселдердің сандық көрінісін алу үшін пикселдердің өздері. Содан кейін бұл процесс толық суретті алу үшін бүкіл кескінде орындалады. Сүзгі ағымдағы орнындағы мәнді есептегеннен кейін сүзгінің қанша пиксель жылжыту керектігін анықтайтын "қадам" деп аталатын параметрге сәйкес кескіннің қалған бөлігінде жылжиды. CNN үшін әдеттегі қадам өлшемі 2.
Барлық осы есептеулердің соңғы нәтижесі мүмкіндіктер картасы болып табылады. Бұл процесс әдетте кескіннің күрделілігін сақтауға көмектесетін бірнеше сүзгілермен орындалады.
Белсендіру функциялары
Кескіннің мүмкіндіктер картасы жасалғаннан кейін кескінді білдіретін мәндер белсендіру функциясы немесе белсендіру қабаты арқылы өтеді. Белсендіру функциясы осы мәндерді қабылдайды, олар конвульсия қабатының арқасында сызықтық формада болады (яғни тек сандар тізімі) және олардың сызықты еместігін арттырады, өйткені кескіндердің өзі сызықты емес.
Бұған қол жеткізу үшін қолданылатын әдеттегі белсендіру функциясы түзетілген сызықтық блок (ReLU) болып табылады, дегенмен кейде пайдаланылатын басқа белсендіру функциялары бар (олар туралы мына жерден оқуға болады. .
Қабаттарды біріктіру
Іске қосылғаннан кейін деректер біріктіру қабаты арқылы жіберіледі. Комбинация кескінді «жеңілдетеді»: ол кескінді көрсететін ақпаратты алады және оны қысады. Біріктіру процесі желіні икемді етеді және сәйкес мүмкіндіктерге негізделген нысандар мен кескіндерді жақсырақ тануға мүмкіндік береді.
Біз суретті қараған кезде, әдетте, бізді барлық ақпарат қызықтырмайды (мысалы, суреттің фонында не бар), тек бізді қызықтыратын белгілер - адамдар, жануарлар және т.б.
Сол сияқты, CNN-дегі біріктіру қабаты кескіннің қажетсіз бөліктерінен құтылып, біріктіру қабатының берілген өлшеміне байланысты тек өзекті деп санайтын бөліктерін қалдырады.
Желі кескіннің ең маңызды бөліктері туралы шешім қабылдауы керек болғандықтан, ол оның қарастырылып отырған объектінің мәнін шын мәнінде бейнелейтін кескіннің сол бөліктерін ғана меңгеруді күтеді. Бұл желі кейс зерттеудің барлық аспектілерін тым жақсы меңгерген кезде және маңызды емес айырмашылықтарды ескере отырып, жаңа деректерге бұдан былай жалпылай алмайтын кезде «артық орнатудың» алдын алуға көмектеседі.
Мәндерді біріктірудің әртүрлі әдістері бар, бірақ ең жиі қолданылатыны - максималды біріктіру. Максималды біріктіру бір сүзгідегі (бір кескін фрагменті ішінде) пикселдер арасындағы максималды мәнді алуды білдіреді. Бұл 2 x 2 сүзгісі пайдаланылса, ақпараттың 3/4 бөлігін сүзеді.
Максималды пиксель мәндері кескіннің ықтимал бұрмалануын есепке алу үшін пайдаланылады, ал параметрлердің саны (сурет өлшемі) шамадан тыс орнатуды бақылау үшін азаяды. Орташа немесе қосынды біріктіру сияқты басқа біріктіру принциптері бар, бірақ олар жиі пайдаланылмайды, себебі максималды біріктіру дәлдік береді.
Қысу
Біздің CNN соңғы қабаттары - тығыз байланысты қабаттар - әрі қарай өңдеу үшін деректерді векторлық пішінде ұсынуды талап етеді. Осы себепті деректерді «біріктіру» керек. Мұны істеу үшін мәндер ұзын векторға немесе дәйекті реттелген сандар бағанына қысылады.
Толық қосылған қабат
CNN соңғы қабаттары тығыз байланысқан қабаттар немесе жасанды нейрондық желілер (ANN). ANN негізгі функциясы кіріс мүмкіндіктерін талдау және оларды жіктеуге көмектесетін әртүрлі атрибуттарға біріктіру болып табылады. Бұл қабаттар қарастырылып отырған нысанның әртүрлі бөліктерін бейнелейтін нейрондардың жиынтығын құрайды және нейрондар жиынтығы, мысалы, иттің иілгіш құлақтарын немесе алманың қызаруын көрсете алады. Кіріс кескінге жауап ретінде осы нейрондардың жеткілікті мөлшері жанғанда, ол нысан ретінде жіктеледі.
Жаттығу жиынындағы есептелген мәндер мен күтілетін мән арасындағы қате немесе айырмашылық ANN көмегімен есептеледі. Содан кейін желі кері таралу әдісіне ұшырайды, мұнда келесі қабаттағы нейронға берілген нейронның әсері есептеледі, содан кейін оның әсері (салмағы) түзетіледі. Бұл модельдің өнімділігін оңтайландыру үшін жасалады. Бұл процесс желі деректерден үйреніп, кіріс мүмкіндіктері мен шығыс кластары арасындағы байланыстарды үйренген кезде қайта-қайта қайталанады.
Орташа толық қосылған қабаттардағы нейрондар ықтимал сыныптарға қатысты екілік мәндерді шығарады. Егер сізде төрт түрлі класс (айталық, ит, көлік, үй және адам) болса, нейрон кескінді бейнелейді деп есептейтін сынып үшін «1» мәніне және «0» мәніне ие болады. басқа сыныптар.
Соңғы толық қосылған қабат алдыңғы қабаттың шығысын ала отырып, бір сыныптың (бірлесіп) ішіндегі әрбір сыныпқа ықтималдықты тағайындайды. «Ит» санаты 0,75 мәніне орнатылса, бұл кескіннің ит болуының 75% мүмкіндігі бар дегенді білдіреді.
Машинамен оқыту жұмыс процесі
Кескін классификаторын оқыту мысалына көшпес бұрын, машиналық оқытудың жұмыс процесін немесе «құбырын» түсінуге біраз уақыт бөлейік. Нейрондық желі моделін оқыту процесі жеткілікті стандартты және оны төрт түрлі қадамға бөлуге болады.
Кескін классификаторы енді оқытылды және кескіндерді CNN-ге жіберуге болады, ол енді сол кескіннің мазмұнын анықтайды.
Деректерді дайындау
Біріншіден, сіз деректеріңізді жинап, оны шайырлы нейрондық желіні үйретуге болатындай етіп реттеуіңіз керек. Бұған суреттерді жинау және оларды белгілеу кіреді. Басқа біреу дайындаған деректер жинағын жүктеп алған болсаңыз да, оны жаттығу үшін пайдалану үшін алдын ала өңдеу немесе дайындық қажет болуы мүмкін. Деректерді дайындау - бұл жетіспейтін мәндер, бүлінген деректер, дұрыс емес деректер, дұрыс емес белгілер және т.
Бұл мақалада біз алдын ала өңделген деректер жинағын қолданамыз.
Үлгі жасау
Нейрондық желі моделін құру әртүрлі параметрлер мен гиперпараметрлерді таңдауды қамтиды. Үлгіңізде қолданылатын қабаттардың санын, кіріс және шығыс қабаттарының өлшемі қандай болатынын, қандай белсендіру функцияларын пайдаланатыныңызды, ерекше жағдайды (Dropout) пайдаланасыз ба, т.б.
Қандай параметрлер мен гиперпараметрлерді пайдалану керектігін түсіну уақыт өте келе (бұл көп үйренуді қажет етеді), бірақ сіз басында қолдануға болатын негізгі әдістер бар және біз олардың кейбірін мысалымызда қарастырамыз.
Жаттығу үлгілері
Модель жасалғаннан кейін сізге тек үлгінің данасын жасау және оны жаттығу деректеріне сәйкестендіру жеткілікті. Модельді оқытуда ең көп көңіл оқытуға қажетті уақыт мөлшеріне аударылады. Жаттығу дәуірлерінің санын орнату арқылы желілік оқыту ұзақтығын көрсетуге болады. Модельді неғұрлым ұзақ жаттықтырсаңыз, оның өнімділігі соғұрлым жоғары болады, бірақ тым көп жаттығу дәуірлерін пайдалансаңыз, үлгіні шамадан тыс орнату қаупі бар.
Жаттығуға арналған дәуірлер санын таңдау - бұл уақыт өте келе анықтауды үйренетін нәрсе және жалпы ереже бойынша, белгілі бір прогреске қол жеткізгеннен кейін басынан бастаудың қажеті болмас үшін жаттығулар арасындағы нейрондық желі салмағын үнемі сақтау керек. жаттығуда.
Бағалау үлгілері
Модельді бағалау үшін бірнеше қадамдар бар. Бірінші қадам модельдің өнімділігін сынақ деректерінің жиынтығымен салыстыру болып табылады: модель оқытылмаған деректер. Осылайша, сіз осы жаңа деректер жинағы арқылы модельдің өнімділігін тексеріп, әртүрлі көрсеткіштерді пайдаланып оның өнімділігін талдайсыз.
Нейрондық желі моделінің өнімділігін өлшеуге арналған әртүрлі көрсеткіштер бар, бірақ ең көп таралғаны «дәлдік» болып табылады, ол деректер жиынындағы кескіндердің жалпы санына бөлінген дұрыс жіктелген кескіндер саны болып табылады.
Модельдің дәлдігін тексеру деректер жинағында көргеннен кейін, сіз қайта оралып, сәл реттелетін параметрлерді пайдаланып желіні алдын ала жаттықтыратын шығарсыз, өйткені желіңізді бірінші рет жаттықтырған кезде оның өнімділігіне қанағаттанбауыңыз екіталай. Желінің дәлдігіне қанағаттанбайынша, желіңізді баптауды, оны қайта жаттықтыруды және өнімділікті өлшеуді жалғастырасыз.
Соңында сіз желі өнімділігін сынақ жиынында тексересіз. Бұл сіздің үлгіңіз бұрын көрмеген басқа деректер жинағы.
Сізге сұрақ туындауы мүмкін: бізге басқа сынақ деректер жинағы не үшін қажет? Ақыр соңында, сіз өзіңіздің модельіңіздің дәлдігі туралы түсінікке ие болдыңыз, бұл «сынақ жинағының» мақсаты емес пе?
Мәселе мынада: «тексеру деректер жинағымен» жұмыс істеу кезінде желіні дәл баптау кезінде жасаған барлық параметр өзгерістері осы жиынды бірнеше рет қайталап сынаумен біріктіріліп, сіздің желіңіздің кейбір мүмкіндіктерді үйренуіне әкелуі мүмкін. орнатылған, бірақ сонымен бірге ол үлгіден тыс деректерді де жалпыламайды. Сондықтан желіні мүлдем жаңа сынақ деректерімен қамтамасыз ету керек.
Сынақ жинағының мақсаты - модельдің шынайы әлемде жұмыс істеуге жарамды екеніне сенімді болу үшін шамадан тыс орнату сияқты мәселелерді тексеру.
CNN көмегімен кескінді тану
Біз қазірдің өзінде көп нәрсені қарастырдық және егер бұл ақпараттың бәрі сәл түсініксіз болса, онда жоғарыда келтірілген түсініктерді деректер жиынында оқытылған үлгі классификаторында біріктіру ақырында мәселені шешуі керек. Сондықтан Keras көмегімен кескінді танудың толық мысалын қарастырайық - деректерді жүктеуден бағалау моделінің тиімділігіне дейін.
Біріншіден, бізге оқыту деректер жинағы қажет. Бұл мысалда біз әйгілі CIFAR-10 деректер жинағын қолданамыз. CIFAR-10 – мысықтар, ұшақтар және автомобильдер сияқты 10 түрлі мүмкіндіктер класын білдіретін 60 000-нан астам кескінді қамтитын үлкен деректер жинағы.
Кескіндер толық түсті RGB, бірақ олар өте кішкентай, бар болғаны 32 x 32. CIFAR-10 деректер жинағының тамаша жағы ол Keras-пен бірге жеткізіледі, сондықтан деректер жинағын жүктеу өте оңай және кескіндердің өздеріне аз ғана алдын ала қажет болады. -өңдеу.
Бізге бірінші кезекте қажетті кітапханаларды импорттау керек. Бұл импорттың жол бойында қалай болатынын дәл көресіз, бірақ қазір біз Numpy және Keras-қа қатысты әртүрлі модульдерді қолданатынымызды есте сақтаңыз:
import numpy from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten, BatchNormalization, Activation from keras.layers.convolutional import Conv2D, MaxPooling2D from keras.constraints import maxnorm from keras.utils import np_utils
Біз кездейсоқ SEED (Feystel желісіне негізделген симметриялық блоктың криптографиялық алгоритмі) қолданамыз, осылайша осы мақалада алынған нәтижелерді сіз қайта жасай аласыз, сондықтан бізге numpy қажет:
# Set random seed for purposes of reproducibility seed = 21
Деректерді дайындау
Енді бізге тағы бір импорттау керек: деректер жиынының өзі.
from keras.datasets import cifar10
Енді деректер жинағын жүктейміз. Біз мұны деректерді қай айнымалыларға жүктегіміз келетінін көрсету арқылы, содан кейін load_data() функциясын пайдалану арқылы жасай аламыз:
# loading in the data (X_train, y_train), (X_test, y_test) = cifar10.load_data()
Көп жағдайда деректеріңізді пайдалануға дайын ету үшін алдын ала өңдеуден өтуіңіз керек болады, бірақ біз дайын және бумаланған деректер жинағын пайдаланатындықтан, бұл өңдеу минималды деңгейде сақталады. Біз орындағымыз келетін әрекеттердің бірі - кіріс деректерін қалыпқа келтіру.
Егер кіріс деректерінің мәндері тым кең ауқымда болса, бұл желі өнімділігіне теріс әсер етуі мүмкін. Біздің жағдайда кіріс мәндері 0 мен 255 аралығындағы мәні бар кескіндегі пикселдер болып табылады.
Сондықтан деректерді қалыпқа келтіру үшін кескін мәндерін жай ғана 255-ке бөлуге болады. Ол үшін алдымен деректерді өзгермелі нүкте пішіміне түрлендіру керек, өйткені олар қазіргі уақытта бүтін сандар. Біз мұны Numpy's astype() пәрменін пайдаланып жасай аламыз, содан кейін қажетті деректер түрін жариялай аламыз:
# normalize the inputs from 0-255 to between 0 and 1 by dividing by 255 X_train = X_train.astype('float32') X_test = X_test.astype('float32') X_train = X_train / 255.0 X_test = X_test / 255.0
Деректерді желіге дайындау үшін бізге қажет келесі нәрсе - оны біртұтас кодқа аудару. Біз біртұтас кодтаудың егжей-тегжейіне тоқталмаймыз, бірақ есте сақтау керек, кескіндерді нейрондық желі олар қандай пішінде болса, пайдалана алмайды - олар алдымен кодталуы керек, ал екілік классификацияны орындау кезінде унитарлық кодтауды қолданған дұрыс.
Бұл жерде біз екілік классификацияны сәтті қолданамыз, себебі кескін не белгілі бір классқа жатады, не ол жатпайды: ол арасында бір жерде болуы мүмкін емес. Біртұтас кодтау үшін Numpy to_categorical() командасы пайдаланылады. Сондықтан біз Keras-тан np_utils функциясын импорттадық, өйткені оның құрамында to_categorical().
Сондай-ақ, соңғы қабатты қанша нейронды қысу керектігін түсіну үшін деректер жиынындағы сыныптар санын орнатуымыз керек:
# one hot encode outputs y_train = np_utils.to_categorical(y_train) y_test = np_utils.to_categorical(y_test) class_num = y_test.shape[1]
Үлгі дизайны
Біз CNN моделін жобалау кезеңіне жеттік. Біріншіден, біз үлгі үшін пайдаланғымыз келетін пішімді анықтау керек. Керастың модельдерді құруға арналған бірнеше түрлі пішімдері (жоспарлары) бар, бірақ ең жиі қолданылатыны Sequential болып табылады - сондықтан біз оны Keras-тан импорттадық.
Үлгі жасау
model = Sequential()
Модельіміздің бірінші қабаты конволюционды қабат болып табылады. Ол енгізуді қабылдайды және оны конволюциялық сүзгілер арқылы іске қосады.
Мұны Кераста жүзеге асырған кезде бізге қажет арналардың (сүзгілердің) санын (бұл 32), сүзгінің өлшемін (біздің жағдайда 3 x 3), кіру пішінін (бірінші қабатты жасаған кезде), белсендіру функциясы және толтыру.
Жоғарыда айтылғандай, relu - ең көп таралған белсендіру функциясы және біз толтыруды padding = «бірдей» арқылы анықтаймыз, яғни кескіннің өлшемін өзгертпейміз:
model.add(Conv2D(32, (3, 3), input_shape=X_train.shape[1:], padding='same')) model.add(Activation('relu'))
Ескертпе: Сондай-ақ қажетті пәрмендерді бір жолға біріктіруге болады, мысалы:
model.add(Conv2D(32, (3, 3), input_shape=(3, 32, 32), activation='relu', padding='same'))
Енді қабаттар арасындағы қосылымдарды кездейсоқ жоятын шамадан тыс жою қабатын жасаймыз (0,2 ол бар қосылымдардың 20% жояды дегенді білдіреді):
model.add(Dropout(0.2))
Біз сондай-ақ пакетті қалыпқа келтіруді орындай аламыз. Пакеттік қалыпқа келтіру келесі деңгейге өтетін кірістерді қалыпқа келтіреді, бұл желі әрқашан біз қалаған бірдей таратумен белсендіру функцияларын шығаруын қамтамасыз етеді:
model.add(BatchNormalization())
Енді келесі конвульсиялық қабат пайда болады, бірақ сүзгі өлшемі ұлғаяды, осылайша желі күрделірек көріністерді біле алады:
model.add(Conv2D(64, (3, 3), padding='same')) model.add(Activation('relu'))
Міне, біріктіру қабаты, бұрын талқыланғандай, кескін классификаторын сәйкес үлгілерді үйренуі үшін дұрысырақ етуге көмектеседі. Біз сондай-ақ ерекше жағдайды (Тастау) және пакетті қалыпқа келтіруді сипаттаймыз:
model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.2)) model.add(BatchNormalization())
Бұл CNN іске асырудың бірінші бөлігіндегі жұмыс процесінің негізі: конволюция, белсендіру, алып тастау, біріктіру. Енді сіз неге Dropout, BatchNormalization, Activation, Conv2d және MaxPooling2d импорттағанымызды түсіндіңіз.
Сіз конволюциялық қабаттардың санын өз қалауыңыз бойынша өзгерте аласыз, бірақ олардың әрқайсысы есептеу құнын арттырады. Айналмалы қабаттарды қосқанда, үлгі күрделірек көріністерді білуі үшін әдетте сүзгілер санын көбейтетінін ескеріңіз. Егер бұл қабаттар үшін таңдалған сандар біршама ерікті болып көрінсе, сүзгілерді біртіндеп 2 мәніне (2^n) дәрежесіне орнату арқылы көбейту ұсынылады, бұл модельді үйрету кезінде аздап артықшылық беруі мүмкін. GPU-да.
Біріктіру деңгейлерінің тым көп болмауы маңызды, себебі әрқайсысы деректердің бір бөлігін алып тастайды. Тым жиі біріктіру деректерге жеткенде бір-бірімен тығыз байланысқан қабаттарды үйренуге әкеледі.
Қажетті біріктіру қабаттарының саны орындалатын тапсырмаға байланысты - бұл уақыт өте келе анықталатын нәрсе. Біздің жинақтағы кескіндер қазірдің өзінде өте кішкентай болғандықтан, біз оларды екі реттен артық біріктірмейміз.
Енді желіңізге жұмыс істеуге көбірек көрініс беру үшін осы қабаттарды қайталай аласыз:
model.add(Conv2D(64, (3, 3), padding='same')) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.2)) model.add(BatchNormalization()) model.add(Conv2D(128, (3, 3), padding='same')) model.add(Activation('relu')) model.add(Dropout(0.2)) model.add(BatchNormalization())
Конвульсия қабаттарымен жұмыс жасағаннан кейін біз деректерді қысуымыз керек, сондықтан біз жоғарыдағы Flatten функциясын импорттадық. Сондай-ақ, біз қайта шығару қабатын қосамыз:
model.add(Flatten()) model.add(Dropout(0.2))
Біз енді импортталған тығыз функциясын қолданамыз және бірінші тығыз байланысты қабатты жасаймыз. Біз тығыз қабаттағы нейрондардың санын көрсетуіміз керек. Келесі қабаттардағы нейрондардың саны азайып, ақыр соңында деректер жиынындағы сыныптар сияқты нейрондар санына жақындайтынын ескеріңіз (бұл жағдайда 10). Ядро шектеуі жаттығу кезінде деректерді реттей алады, бұл сонымен қатар шамадан тыс орнатуды болдырмауға көмектеседі. Сондықтан біз maxnorm-ды ертерек импорттадық.
model.add(Dense(256, kernel_constraint=maxnorm(3))) model.add(Activation('relu')) model.add(Dropout(0.2)) model.add(BatchNormalization()) model.add(Dense(128, kernel_constraint=maxnorm(3))) model.add(Activation('relu')) model.add(Dropout(0.2)) model.add(BatchNormalization())
Бұл соңғы қабатта біз нейрондар санымен сыныптар санын теңестіреміз. Әрбір нейрон классты білдіреді, сондықтан бұл қабаттың шығысы 10 нейронның векторы болады, олардың әрқайсысы қарастырылып отырған кескіннің өз класына жататынының кейбір ықтималдығын сақтайды.
Соңында, softmax белсендіру функциясы кескіннің осы нақты сыныпқа жататынын болжа отырып, оның шығыс мәні ретінде ең жоғары ықтималдығы бар нейронды таңдайды:
model.add(Dense(class_num)) model.add(Activation('softmax'))
Енді біз қолданғымыз келетін модельді әзірледік, оны құрастыру ғана қалды. Жаттығу үшін дәуірлер санын, сондай-ақ біз пайдаланғымыз келетін оңтайландырғышты көрсетейік.
Оптимизатор - ең аз жоғалту нүктесіне жақындау үшін желіңіздегі салмақтарды реттейтін нәрсе. Адамның алгоритмі ең көп қолданылатын оңтайландырушылардың бірі болып табылады, себебі ол көптеген тапсырмаларда жоғары өнімділік береді:
epochs = 25 optimizer = 'adam'
Енді таңдалған параметрлермен модельді құрастырайық. Сондай-ақ бағалау үшін көрсеткішті көрсетейік.
model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
Модель туралы жалпы түсінік алу үшін біз модельдің қысқаша мазмұнын басып шығара аламыз.
print(model.summary())
Түйіндемені басып шығару бізге кейбір ақпаратты береді:
Results: Layer (type) Output Shape Param # ================================================================= conv2d_1 (Conv2D) (None, 32, 32, 32) 896 _________________________________________________________________ activation_1 (Activation) (None, 32, 32, 32) 0 _________________________________________________________________ dropout_1 (Dropout) (None, 32, 32, 32) 0 _________________________________________________________________ batch_normalization_1 (Batch (None, 32, 32, 32) 128 _________________________________________________________________ conv2d_2 (Conv2D) (None, 32, 32, 64) 18496 _________________________________________________________________ activation_2 (Activation) (None, 32, 32, 64) 0 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 16, 16, 64) 0 _________________________________________________________________ dropout_2 (Dropout) (None, 16, 16, 64) 0 _________________________________________________________________ batch_normalization_2 (Batch (None, 16, 16, 64) 256 _________________________________________________________________ conv2d_3 (Conv2D) (None, 16, 16, 64) 36928 _________________________________________________________________ activation_3 (Activation) (None, 16, 16, 64) 0 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 8, 8, 64) 0 _________________________________________________________________ dropout_3 (Dropout) (None, 8, 8, 64) 0 _________________________________________________________________ batch_normalization_3 (Batch (None, 8, 8, 64) 256 _________________________________________________________________ conv2d_4 (Conv2D) (None, 8, 8, 128) 73856 _________________________________________________________________ activation_4 (Activation) (None, 8, 8, 128) 0 _________________________________________________________________ dropout_4 (Dropout) (None, 8, 8, 128) 0 _________________________________________________________________ batch_normalization_4 (Batch (None, 8, 8, 128) 512 _________________________________________________________________ flatten_1 (Flatten) (None, 8192) 0 _________________________________________________________________ dropout_5 (Dropout) (None, 8192) 0 _________________________________________________________________ dense_1 (Dense) (None, 256) 2097408 _________________________________________________________________ activation_5 (Activation) (None, 256) 0 _________________________________________________________________ dropout_6 (Dropout) (None, 256) 0 _________________________________________________________________ batch_normalization_5 (Batch (None, 256) 1024 _________________________________________________________________ dense_2 (Dense) (None, 128) 32896 _________________________________________________________________ activation_6 (Activation) (None, 128) 0 _________________________________________________________________ dropout_7 (Dropout) (None, 128) 0 _________________________________________________________________ batch_normalization_6 (Batch (None, 128) 512 _________________________________________________________________ dense_3 (Dense) (None, 10) 1290 _________________________________________________________________ activation_7 (Activation) (None, 10) 0 ================================================================= Total params: 2,264,458 Trainable params: 2,263,114 Non-trainable params: 1,344
Енді біз модельді оқытуды бастаймыз. Ол үшін үлгідегі fit() функциясын шақырып, таңдалған параметрлерді енгізу керек.
Бұл жерде қайталану мақсатында таңдалған SEED пайдаланылады.
numpy.random.seed(seed) model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=64)
50 000 үлгіден тұратын оқу жинағын және 10 000 үлгіден тұратын сынақ жинағын алайық.
Бұл код бөлігін іске қосу мыналарды береді:
Epoch 1/25 64/50000 [..............................] - ETA: 16:57 - loss: 3.1479 - acc: 0.0938 128/50000 [..............................] - ETA: 10:12 - loss: 3.0212 - acc: 0.0938 192/50000 [..............................] - ETA: 7:57 - loss: 2.9781 - acc: 0.1250 256/50000 [..............................] - ETA: 6:48 - loss: 2.8830 - acc: 0.1484 320/50000 [..............................] - ETA: 6:07 - loss: 2.8878 - acc: 0.1469 384/50000 [..............................] - ETA: 5:40 - loss: 2.8732 - acc: 0.1458 448/50000 [..............................] - ETA: 5:20 - loss: 2.8842 - acc: 0.1406 ... ... ... 49664/50000 [============================>.] - ETA: 1s - loss: 1.5160 - acc: 0.4611 49728/50000 [============================>.] - ETA: 1s - loss: 1.5157 - acc: 0.4612 49792/50000 [============================>.] - ETA: 1s - loss: 1.5153 - acc: 0.4614 49856/50000 [============================>.] - ETA: 0s - loss: 1.5147 - acc: 0.4615 49920/50000 [============================>.] - ETA: 0s - loss: 1.5144 - acc: 0.4617 49984/50000 [============================>.] - ETA: 0s - loss: 1.5141 - acc: 0.4617 50000/50000 [==============================] - 262s 5ms/step - loss: 1.5140 - acc: 0.4618 - val_loss: 1.0715 - val_acc: 0.6195 End of Epoch 1
Көп жағдайда тестілеу жиынынан басқа валидация жинағы қажет болатынын ескеріңіз, сондықтан тексеру жиыны ретінде пайдаланылатын оқу деректерінің пайызын көрсетуіңіз керек. Бұл жағдайда сынақ деректерінің шетке қойылғанына және оқу үшін пайдаланылмайтынына көз жеткізу үшін сынақ деректерін тапсырамыз. Бұл мысалда бізде қарапайым нәрселерді сақтау үшін тек сынақ деректері болады.
Енді біз модельді бағалай аламыз және оның қалай жұмыс істейтінін көре аламыз. Тек model.evaluate() деп қоңырау шалыңыз:
# Model evaluation scores = model.evaluate(X_test, y_test, verbose=0) print("Accuracy: %.2f%%" % (scores[1]*100))
Міне, біз нәтиже аламыз:
Accuracy: 83.01%
Сонымен бітті! Бізде қазір CNN кескінді тану бойынша дайындалған. Алғашқы іске қосу үшін жаман емес, бірақ жақсырақ өнімділікке қол жеткізу үшін үлгі құрылымы мен параметрлерімен тәжірибе жасағыңыз келуі мүмкін.
Каптчаны тану үшін нейрондық желілерді практикалық қолдану
CNN-дегі теориялық және эксперименттік жұмыс, әрине, күнделікті практикалық мәселелерді шешу үшін нейрондық желілерді пайдалану нұсқаларына әкеледі. Кескінді тану және жіктеу саласындағы ең өзектісі captcha шешу міндеті болып табылады, атап айтқанда, бүгінгі күні ең танымал Google ReCaptcha v2.
Біздің мысалға ұқсастығына қарамастан, іс жүзінде captcha шешу үшін жұмыс істейтін нейрондық желіні енгізу үнемі өзгеретін деректер жиынтығына байланысты (catcha-дағы суреттер) өте қымбат және тиімсіз шешім болып көрінеді. Кіріс деректерінің мұндай жиі және болжанбайтын жаңартылуы көптеген проблемаларды тудырады:
- жаңа деректерді үнемі жинау және өңдеу қажеттілігі
- адамның процесті үнемі бақылау және жұмыс барысында модельге өзгертулер енгізу қажеттілігі (параметрлері бар эксперименттерді қоса алғанда)
- модельді тәулік бойы оқыту үшін қуатты жабдықтың қажеттілігі
- және т.б.
Интернеттегі әртүрлі каптчаларды айналып өту мәселесінің әмбебап шешімі
Каптчаларды үздіксіз режимде, жоғары жылдамдықпен және салыстырмалы түрде төмен бағамен шешу үшін каптчаларды тану үшін онлайн қызметтері үлкен сұранысқа ие, бұл үшін нақты пайдаланушыларды тартады. Ішкі нарықта көшбасшы RuCaptcha.com қызметі болып табылады, ол өзінің бәсекелестерімен жақсы салыстырады:
жоғары дәлдік (99% дейін) және шешімдер жылдамдығы (кәдімгі мәтіндік captcha үшін 12 секунд және ReCaptcha үшін 24 секунд)
қолайлы тіркелген бағалар (қызмет серверлеріндегі жүктеменің артуымен баға өспейді): 1000 тұрақты captcha шешімі үшін 35 рубль және 1000 ReCaptcha шешімі үшін 160 рубль
сирек кездесетін сәтсіз тану үшін ақшаны қайтару
каптчалардың үлкен көлемін шешудің техникалық мүмкіндігі (минутына 10 000-нан астам)
қарапайым және функционалды API
әр түрлі бағдарламалау тілдеріне арналған дайын кітапханалар мен код үлгілері
* әзірлеушілер мен рефералдарға тартылған клиенттердің шығындарының 15% және қызметке тартылған қызметкерлердің кірісінің 10% алуға мүмкіндік беретін тартымды серіктестік бағдарламасы.
Қызметтің жұмысына қатысты туындаған сұрақтарды қолдау қызметі билет жүйесі арқылы жедел түрде шешеді.
Қорытынды
Енді сіз Keras-те кескінді тану бойынша алғашқы желіні енгіздіңіз, модельмен ойнап, оның параметрлерін өзгерту өнімділікке қалай әсер ететінін көру жақсы болар еді.
Бұл сізге әртүрлі модель параметрлері үшін оңтайлы мәндерді интуитивті түсінуге мүмкіндік береді. Үлгіңізде жұмыс істеу барысында параметрлер мен гиперпараметрлердің әртүрлі опцияларын зерттеуіңіз керек. Сіз онымен ыңғайлы болғаннан кейін, өзіңіздің кескін классификаторыңызды басқа деректер жинағында енгізуге тырысуға болады.
Кәдімгі практикалық жұмыс тапсырмаларына келетін болсақ, мысалы, captcha тану, нейрондық желіні құру және оқыту икемді және тиімді шешім емес. Мұндай мақсаттар үшін RuCaptcha.com онлайн қызметін пайдалану әлдеқайда жылдам, арзанырақ және ыңғайлырақ.
Собственно, а что исходников то нет?
Большая кнопка GITHUB РЕПОЗИТОРИЙ ни о чём не говорит?
Окей, нашел (возможно глаза привыкают к тому, что на сайтах мелькают объявления и большие яркие кнопки автоматически игнорируются). Но не нашел данные на которых обучалась нейросеть. Без них повторить "это" я все равно не смогу ведь...
хех... непривычно, что практически всё является полезным контентом? Самому непривычно... надеюсь, что протяну год в таком режиме, чтобы в конце сделать выводы - "может ли бесплатный ресурс жить без рекламных сетей?"
Что касается исходных данных, то извини, тут не помогу, есть причины, почему они не приложены. Ок?
Ок :)
Спасибо за Ваш труд, очень крутой у вас ресурс, особенно нравятся статьи по Django!
Не тому написали, ну да ладно )) Спасибо за отзыв :D
будем считать что авторы статьи по django примут на свой счет :D
Огромное спасибо за метериал, по-больше бы подобных статей (с подробным описанием работы и примерами применения) на тему современных технологий.
Вопрос поразмышлять. На текущий момент реализовано немало технологий в основе которых лежит комп. зрение. Одна из таких - это государственные сканнеры проходящих людей, например в аэропортах. Что лежит в основе такой технологии? как такой объем данных обрабатывается в реальном времени и как входные данные подгоняются под один тип?
почему то вместо 50000 обрабатывает по 782 картинки кажду. эпоху
А в чём проблема-то? Если не жалко тратить пару-тройку сотен рублей на хостинг/VDS в месяц, то любой сайт прекрасно существует без всякой рекламы сколь угодно долго.
Статья очень понравилась! Как раз искал пример, где работа с изображениями с помощью нейросети расписана по шагам для начинающих.
Время на развитие, трудозатраты на разработку, ответы на специализированные вопросы и т.д. вы видимо в расчёт не берёте.
Естественно, поскольку собственное время — ресурс бесплатный, и предполагается, что проект приносит удовольствие (или какие-то другие нематериальные бонусы типа чувства собственной значимости и компетентности).
Собственное время не бесплатно, поскольку бесценно и не возобновимо. И не все это понимают, а Вы понимаете?
А поддержание подобного ресурса со временем становится накладным, сколько бы удовольствия он не приносил, это не личный бложик обо всём и ни о чём. Я много раз порывался писать статьи обо всякой ерунде, но останавливал себя, поскольку это не то место, чтобы устраивать здесь свой дневник. Это специализированный ресурс, а подготовка специализированной статьи порой занимает много времени.
И при всём своём желании его развивать, у меня нет желания делать это в ущерб личной жизни. Поэтому со временем такой ресурс либо монетизируется и все силы бросаются на него, либо застывает без новых статей и нового материала, как сейчас.
Так что делайте выводы сами. Но далее обсуждать это не буду, это оффтоп и пустое столкновение мнений.
Понимаю. А ещё понимаю, что не потратить время нельзя. День всё равно пройдёт, и вопрос только в том, на что он будет потрачен: на то, что приносит в жизни удовольствие или нет.
Насчёт застывает — ничего страшного в этом нет (кроме негативного влияния на SEO). Я, например, у себя на сайте в некоторые разделы пишу 2—3 раза в год, когда есть идеи, вдохновение и желание поделиться информацией, и считаю это совершенно нормальным.
Впрочем, похоже, мы и правда не поймём друг друга. Слишком разная система жизненных ценностей. Так что оставлю вас в покое.
А что собственно выводит программа, как вывести то что она смогла распознать?