Како поступати са МНИСТ сликовним подацима у Тенсорфлов.јс

Постоји шала да 80 посто наука о подацима чисти, а 20 посто жали се на чишћење података ... чишћење података је много већи удио науке о подацима него што би страни аутори очекивали. Заправо су модели обуке типично релативно мали проценти (мање од 10 процената) онога што ради ученик машине или научник података.

 - Антхони Голдблоом, генерални директор Кагглеа

Манипулирање података је пресудан корак за било који проблем машинског учења. Овај ће чланак узети примјер МНИСТ-а за Тенсорфлов.јс (0.11.1) и проћи кроз код који рукује с уношењем података ред по ред.

Пример МНИСТ-а

18 увоз * као тф из '@ тенсорфлов / тфјс';
19
20 цонст ИМАГЕ_СИЗЕ = 784;
21 цонст НУМ_ЦЛАССЕС = 10;
22 цонст НУМ_ДАТАСЕТ_ЕЛЕМЕНТС = 65000;
23
24 цонст НУМ_ТРАИН_ЕЛЕМЕНТС = 55000;
25 цонст НУМ_ТЕСТ_ЕЛЕМЕНТС = НУМ_ДАТАСЕТ_ЕЛЕМЕНТС - НУМ_ТРАИН_ЕЛЕМЕНТС;
26
27 цонст МНИСТ_ИМАГЕС_СПРИТЕ_ПАТХ =
28 'хттпс://стораге.гооглеапис.цом/леарњс-дата/модел-буилдер/мнист_имагес.пнг';
29 цонст МНИСТ_ЛАБЕЛС_ПАТХ =
30 'хттпс: //стораге.гооглеапис.цом/леарњс-дата/модел-буилдер/мнист_лабелс_уинт8'; `

Прво, код увози Тенсорфлов (проверите да ли транслирате код!) И успоставља неке константе, укључујући:

  • ИМАГЕ_СИЗЕ - величина слике (ширина и висина 28к28 = 784)
  • НУМ_ЦЛАССЕС - број категорија ознака (број може бити 0-9, тако да постоји 10 часова)
  • НУМ_ДАТАСЕТ_ЕЛЕМЕНТС - укупан број слика (65 000)
  • НУМ_ТРАИН_ЕЛЕМЕНТС - број слика са тренинга (55 000)
  • НУМ_ТЕСТ_ЕЛЕМЕНТС - број тестних слика (10 000, ака остатак)
  • МНИСТ_ИМАГЕС_СПРИТЕ_ПАТХ & МНИСТ_ЛАБЕЛС_ПАТХ - стазе до слика и ознака

Слике су спојене у једну огромну слику која изгледа као:

МНИСТДата

Следеће, почевши од линије 38, је МнистДата, класа која има следеће функције:

  • оптерећење - одговорно за асинхроно учитавање података и података о означавању
  • нектТраинБатцх - учитајте следећу серију тренинга
  • нектТестБатцх - учитајте следећу пробну серију
  • нектБатцх - генеричка функција за враћање следеће серије, зависно од тога да ли се налази у тренингу или тест сету

Овај чланак ће само за потребе покретања проћи кроз функцију оптерећења.

учитавање

44 асинц лоад () {
45 // Поднесите захтев за МНИСТ-ом снимљеном сликом.
46 цонст имг = нова слика ();
47 цонст цанвас = доцумент.цреатеЕлемент ('платно');
48 цонст цтк = цанвас.гетЦонтект ('2д');

асинц је релативно нова језична карактеристика у Јавасцрипт-у за коју ће вам требати транспилер.

Објект Имаге је изворна ДОМ функција која представља слику у меморији. Омогућава повратне позиве за време када се слика учита, уз приступ атрибутима слике. цанвас је још један ДОМ елемент који омогућава лак приступ пикселским низовима и обраду у контексту.

Будући да су оба елемента ДОМ, ако радите у Ноде.јс (или Веб Воркеру) нећете имати приступ тим елементима. За алтернативни приступ, погледајте доле.

имгРекуест

49 цонст имгРекуест = ново обећање ((реши, одбаци) => {
50 имг.цроссОригин = '';
51 имг.онлоад = () => {
52 имг.видтх = имг.натуралВидтх;
53 имг.хеигхт = имг.натуралХеигхт;

Код иницијализира ново обећање које ће се ријешити након успјешног учитавања слике. Овај пример изричито не обрађује стање грешке.

цроссОригин је атрибут имг који омогућава учитавање слика преко домена и заобилази проблеме ЦОРС (цросс-оригин схаринг ресурса) приликом интеракције са ДОМ-ом. натуралВидтх и натуралХеигхт односе се на оригиналне димензије учитане слике и служе да се увери да је величина слике тачна приликом обављања израчуна.

55 цонст скупа податакаБитесБуффер =
56 нових АрраиБуффер-а (НУМ_ДАТАСЕТ_ЕЛЕМЕНТС * ИМАГЕ_СИЗЕ * 4);
57
58 цонст цхункСизе = 5000;
59 цанвас.видтх = имг.видтх;
60 цанвас.хеигхт = цхункСизе;

Код иницијализира нови међуспремник који садржи сваки пиксел сваке слике. Умножава укупан број слика са величином сваке слике са бројем канала (4).

Верујем да се цхункСизе користи да спречи да УИ истовремено учита превише података у меморију, мада нисам 100% сигуран.

62 за (нека је и = 0; и <НУМ_ДАТАСЕТ_ЕЛЕМЕНТС / цхункСизе; и ++) {
63 цонст скупац податакаБитесВиев = нови Флоат32Арраи (
64 скупа податакаБитесБуффер, и * ИМАГЕ_СИЗЕ * цхункСизе * 4,
65 ИМАГЕ_СИЗЕ * цхункСизе);
66 цтк.дравИмаге (
67 имг, 0, и * цхункСизе, имг.видтх, цхункСизе, 0, 0, имг.видтх,
68 комада величине);
69
70 цонст имагеДата = цтк.гетИмагеДата (0, 0, цанвас.видтх, цанвас.хеигхт);

Овај код пролази кроз сваку слику у спритеу и иницијализира нови ТипедАрраи за ту итерацију. Затим, контекстна слика добија комад цртежа. Коначно, та нацртана слика се претвара у сликовне податке користећи контекст функцију гетИмагеДата, која враћа објект који представља основне податке пиксела.

72 фор (нека ј = 0; ј <имагеДата.дата.ленгтх / 4; ј ++) {
73 // Сви канали имају једнаку вредност јер је слика у сивим тоновима
74 // само прочитајте црвени канал.
75 податакаБитесВиев [ј] = имагеДата.дата [ј * 4] / 255;
76}
77}

Прелазимо кроз пикселе и поделимо са 255 (максимална могућа вредност пиксела) да стегнемо вредности између 0 и 1. Потребан је само црвени канал, пошто је слика у сивим тоновима.

78 тхис.датасетИмагес = нови Флоат32Арраи (скупац податакаБитесБуффер);
79
80 ријешити ();
81};
82 имг.срц = МНИСТ_ИМАГЕС_СПРИТЕ_ПАТХ;
83});

Ова линија узима међуспремник, пребацује га у нови ТипедАрраи који садржи наше податке о пикселима и затим разрешава Промисе. Последња линија (подешавање срца) заправо почиње учитавање слике, чиме се покреће функција.

Једна ствар која ме је у почетку збунила је понашање ТипедАрраи-а у односу на његов бафер података. Можда ћете приметити да је скуп податакаБитесВиев постављен унутар петље, али се никада не враћа.

Под капом, скуп податакаБитесВиев референцира скуп података ме успремникаБитесБуффер (с којим је иницијализиран). Када код ажурира податке пиксела, индиректно уређује вредности самог међуспремника, што заузврат преиначује у нови Флоат32Арраи у линији 78.

Дохваћање сликовних података изван ДОМ-а

Ако сте у домену, требало би да користите ДОМ. Прегледник (преко платна) брине се за проналажење формата слика и преношење података међуспремника у пикселе. Али ако радите изван ДОМ-а (рецимо у Ноде.јс или у Веб Воркер-у), требат ће вам алтернативни приступ.

фетцх нуди механизам, респонсе.арраиБуффер, који вам омогућава приступ подножном међуспремнику датотеке. Ово можемо користити за ручно читање бајтова, избегавајући ДОМ у потпуности. Ево алтернативног приступа писању горњег кода (овај код захтева дохваћање, које се у Пољу може попунити нечим попут изоморфног-дохваћања):

цонст имгРекуест = дохват (МНИСТ_ИМАГЕС_СПРИТЕ_ПАТХ) .тхен (респ => респ.арраиБуффер ()). затим (буффер => {
  вратите ново обећање (ресите => {
    цонст читач = нови ПНГРеадер (међуспремник);
    ретурн реадер.парсе ((грешка, пнг) => {
      цонст пикелс = Флоат32Арраи.фром (пнг.пикелс) .мап (пикел => {
        повратни пиксел / 255;
      });
      тхис.датасетИмагес = пиксела;
      ријешити ();
    });
  });
});

То враћа међуспремник поља за одређену слику. Када ово пишем, прво сам покушао да анализирам улазни међуспремник, што не бих препоручио. (Ако сте заинтересовани да то урадите, ево неких информација о томе како да прочитате пуфер матрице за пнг.) Уместо тога, изабрао сам да користим пнгјс, који рукује пнг анализом за вас. Када се бавите другим форматима слика, мораћете сами да утврдите функције анализе.

Само гребање по површини

Разумевање манипулације подацима кључна је компонента машинског учења у ЈаваСцрипт-у. Разумевајући случајеве и захтеве за коришћење, можемо користити неколико кључних функција како бисмо елегантно форматирали наше податке за наше потребе.

Тенсорфлов.јс тим континуирано мења АПИ-је за податке у Тенсорфлов.јс. Ово може помоћи да се прилагоди више наших потреба како се развија АПИ. То такође значи да је вредно остати у току са развојем АПИ-ја јер Тенсорфлов.јс и даље расте и унапређује се.

Изворно објављен на тхекевинсцотт.цом

Посебна захвалност Ари Зилнику.