เบเบฒเบ™เบฎเบฑเบšเบฎเบนเป‰ Doodle เปเบ•เป‰เบกเบ”เปˆเบงเบ™: เบงเบดเบ—เบตเบเบฒเบ™เบชเป‰เบฒเบ‡เป€เบžเบทเปˆเบญเบ™เบเบฑเบš R, C++ เปเบฅเบฐเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural

เบเบฒเบ™เบฎเบฑเบšเบฎเบนเป‰ Doodle เปเบ•เป‰เบกเบ”เปˆเบงเบ™: เบงเบดเบ—เบตเบเบฒเบ™เบชเป‰เบฒเบ‡เป€เบžเบทเปˆเบญเบ™เบเบฑเบš R, C++ เปเบฅเบฐเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural

Hey Habr!

เปƒเบ™เบฅเบฐเบ”เบนเปƒเบšเป„เบกเป‰เบ›เบปเปˆเบ‡เบ—เบตเปˆเบœเปˆเบฒเบ™เบกเบฒ, Kaggle เป€เบ›เบฑเบ™เป€เบˆเบปเป‰เบฒเบžเบฒเบšเบˆเบฑเบ”เบเบฒเบ™เปเบ‚เปˆเบ‡เบ‚เบฑเบ™เป€เบžเบทเปˆเบญเบˆเบฑเบ”เบ›เบฐเป€เบžเบ”เบฎเบนเบšเบžเบฒเบšเบ—เบตเปˆเปเบ•เป‰เบกเบ”เป‰เบงเบเบกเบท, Quick Draw Doodle Recognition, เปƒเบ™เบ™เบฑเป‰เบ™, เปƒเบ™เบšเบฑเบ™เบ”เบฒเบญเบทเปˆเบ™เป†, เบ—เบตเบกเบ™เบฑเบเบงเบดเบ—เบฐเบเบฒเบชเบฒเบ” R- เป„เบ”เป‰เป€เบ‚เบปเป‰เบฒเบฎเปˆเบงเบก: Artem Klevtsova, เบœเบนเป‰เบˆเบฑเบ”เบเบฒเบ™ Philippa ะธ Andrey Ogurtsov. เบžเบงเบโ€‹เป€เบฎเบปเบฒโ€‹เบˆเบฐโ€‹เบšเปเปˆโ€‹เป„เบ”เป‰โ€‹เบญเบฐโ€‹เบ—เบดโ€‹เบšเบฒเบโ€‹เบเบฒเบ™โ€‹เปเบ‚เปˆเบ‡โ€‹เบ‚เบฑเบ™โ€‹เป‚เบ”เบโ€‹เบฅเบฐโ€‹เบญเบฝเบ”โ€‹, เบ—เบตเปˆโ€‹เป„เบ”เป‰โ€‹เป€เบฎเบฑเบ”โ€‹เปเบฅเป‰เบงโ€‹เปƒเบ™โ€‹ เบเบฒเบ™เบžเบดเบกเป€เบœเบตเบเปเบœเปˆเบ—เบตเปˆเบœเปˆเบฒเบ™เบกเบฒ.

เป€เบงเบฅเบฒเบ™เบตเป‰เบกเบฑเบ™เบšเปเปˆเป„เบ”เป‰เบœเบปเบ™เบเบฑเบšเบเบฒเบ™เบ›เบนเบเบเบฑเบ‡เบซเบผเบฝเบ™, เปเบ•เปˆเบ›เบฐเบชเบปเบšเบเบฒเบ™เบ—เบตเปˆเบกเบตเบ„เบธเบ™เบ„เปˆเบฒเบซเบผเบฒเบเบเปเปˆเป„เบ”เป‰เบฎเบฑเบš, เบชเบฐเบ™เบฑเป‰เบ™เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบขเบฒเบเบšเบญเบเบŠเบธเบกเบŠเบปเบ™เบเปˆเบฝเบงเบเบฑเบšเบชเบดเปˆเบ‡เบ—เบตเปˆเบซเบ™เป‰เบฒเบชเบปเบ™เปƒเบˆเปเบฅเบฐเป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ”เบ—เบตเปˆเบชเบธเบ”เบเปˆเบฝเบงเบเบฑเบš Kagle เปเบฅเบฐเปƒเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ›เบฐเบˆเปเบฒเบงเบฑเบ™. เปƒเบ™โ€‹เบšเบฑเบ™โ€‹เบ”เบฒโ€‹เบซเบปเบงโ€‹เบ‚เปเป‰โ€‹เบ—เบตเปˆโ€‹เบ›เบถเบโ€‹เบชเบฒโ€‹เบซเบฒโ€‹เบฅเบทโ€‹: เบŠเบตโ€‹เบงเบดเบ”โ€‹เบ—เบตเปˆโ€‹เบกเบตโ€‹เบ„เบงเบฒเบกโ€‹เบซเบเบธเป‰เบ‡โ€‹เบเบฒเบโ€‹เป‚เบ”เบโ€‹เบšเปเปˆโ€‹เบกเบตโ€‹เบเบฒเบ™โ€‹ OpenCV, JSON parsing (เบ•เบปเบงเบขเปˆเบฒเบ‡เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบเบงเบ”เป€เบšเบดเปˆเบ‡เบเบฒเบ™เบฅเบงเบกเบฅเบฐเบซเบฑเบ” C++ เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ scripts เบซเบผเบท packages เปƒเบ™ R เป‚เบ”เบเปƒเบŠเป‰ Rcpp), parameterization เบ‚เบญเบ‡ scripts เปเบฅเบฐ dockerization เบ‚เบญเบ‡เบเบฒเบ™เปเบเป‰เป„เบ‚เบชเบธเบ”เบ—เป‰เบฒเบ. เบฅเบฐเบซเบฑเบ”เบ—เบฑเบ‡เบซเบกเบปเบ”เบˆเบฒเบเบ‚เปเป‰เบ„เบงเบฒเบกเปƒเบ™เบฎเบนเบšเปเบšเบšเบ—เบตเปˆเป€เบซเบกเบฒเบฐเบชเบปเบกเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เปเบกเปˆเบ™เบกเบตเบขเบนเปˆเปƒเบ™ เบ„เบฑเบ‡เป€เบเบฑเบšเบกเป‰เบฝเบ™.

เป€เบ™เบทเป‰เบญเบซเบฒ:

  1. เป‚เบซเบผเบ”เบ‚เปเป‰เบกเบนเบ™เบˆเบฒเบ CSV เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ MonetDB เบขเปˆเบฒเบ‡เบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบš
  2. เบเบฒเบ™เบเบฐเบเบฝเบกเบŠเบธเบ”
  3. Iterators เบชเปเบฒเบฅเบฑเบš unloading batches เบˆเบฒเบเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™
  4. เบเบฒเบ™เป€เบฅเบทเบญเบเบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเปเบšเบšเบˆเปเบฒเบฅเบญเบ‡
  5. เบเบฒเบ™เบเปเบฒเบ™เบปเบ”เบ•เบปเบงเบเปเบฒเบ™เบปเบ”เบเบฒเบ™เบชเบฐเบ„เบฃเบดเบš
  6. Dockerization เบ‚เบญเบ‡ scripts
  7. เปƒเบŠเป‰ GPU เบซเบผเบฒเบเบญเบฑเบ™เปƒเบ™ Google Cloud
  8. เปเบ—เบ™เบ—เบตเปˆเบˆเบฐเป€เบ›เบฑเบ™เบเบฒเบ™เบชเบฐเบซเบฅเบธเบšเป„เบ”เป‰

1. เป‚เบซเบผเบ”เบ‚เปเป‰เบกเบนเบ™เบˆเบฒเบ CSV เป€เบ‚เบปเป‰เบฒเปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™ MonetDB เบขเปˆเบฒเบ‡เบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบš

เบ‚เปเป‰เบกเบนเบ™เปƒเบ™เบเบฒเบ™เปเบ‚เปˆเบ‡เบ‚เบฑเบ™เบ™เบตเป‰เปเบกเปˆเบ™เบšเปเปˆเบขเบนเปˆเปƒเบ™เบฎเบนเบšเปเบšเบšเบ‚เบญเบ‡เบฎเบนเบšเบžเบฒเบšเบ—เบตเปˆเบเบฝเบกเบžเป‰เบญเบก, เปเบ•เปˆเปƒเบ™เบฎเบนเบšเปเบšเบšเบ‚เบญเบ‡ 340 เป„เบŸเบฅเปŒ CSV (เบซเบ™เบถเปˆเบ‡เป„เบŸเบฅเปŒเบชเปเบฒเบฅเบฑเบšเปเบ•เปˆเบฅเบฐเบŠเบฑเป‰เบ™เบฎเบฝเบ™) เบ—เบตเปˆเบกเบต JSONs เบ—เบตเปˆเบกเบตเบˆเบธเบ”เบ›เบฐเบชเบฒเบ™เบ‡เบฒเบ™. เป‚เบ”เบเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบˆเบธเบ”เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบเบฑเบšเป€เบชเบฑเป‰เบ™, เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบฎเบฑเบšเบฎเบนเบšเบžเบฒเบšเบชเบธเบ”เบ—เป‰เบฒเบเบ—เบตเปˆเบงเบฑเบ”เปเบ—เบ 256x256 pixels. เบ™เบญเบเบˆเบฒเบเบ™เบฑเป‰เบ™, เปเบ•เปˆเบฅเบฐเบšเบฑเบ™เบ—เบถเบเบกเบตเบ›เป‰เบฒเบเบŠเบตเป‰เบšเบญเบเบงเปˆเบฒเบฎเบนเบšเบžเบฒเบšเป„เบ”เป‰เบ–เบทเบเบฎเบฑเบšเบฎเบนเป‰เบขเปˆเบฒเบ‡เบ–เบทเบเบ•เป‰เบญเบ‡เป‚เบ”เบเบœเบนเป‰เบˆเบฑเบ”เบ›เบฐเป€เบžเบ”เบ—เบตเปˆเปƒเบŠเป‰เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เป„เบ”เป‰เบ–เบทเบเป€เบเบฑเบšเบเปเบฒ, เบฅเบฐเบซเบฑเบ”เบชเบญเบ‡เบ•เบปเบงเบญเบฑเบเบชเบญเบ™เบ‚เบญเบ‡เบ›เบฐเป€เบ—เบ”เบ—เบตเปˆเบขเบนเปˆเบญเบฒเป„เบชเบ‚เบญเบ‡เบœเบนเป‰เบ‚เบฝเบ™เบ‚เบญเบ‡เบฎเบนเบšเบžเบฒเบš, เบ•เบปเบงเบฅเบฐเบšเบธเบ—เบตเปˆเป€เบ›เบฑเบ™เป€เบญเบเบฐเบฅเบฑเบ, เบชเบฐเปเบ•เบกเป€เบงเบฅเบฒ. เปเบฅเบฐเบŠเบทเปˆเบซเป‰เบญเบ‡เบฎเบฝเบ™เบ—เบตเปˆเบเบปเบ‡เบเบฑเบšเบŠเบทเปˆเป„เบŸเบฅเปŒ. เบชเบฐเบšเบฑเบšเบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบเบ‚เบญเบ‡เบ‚เปเป‰เบกเบนเบ™เบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบšเบกเบตเบ™เปเป‰เบฒเบซเบ™เบฑเบ 7.4 GB เบขเบนเปˆเปƒเบ™เบšเปˆเบญเบ™เป€เบเบฑเบšเบกเป‰เบฝเบ™เปเบฅเบฐเบ›เบฐเบกเบฒเบ™ 20 GB เบซเบผเบฑเบ‡เบˆเบฒเบเบเบฒเบ™เบซเบธเป‰เบกเบซเปเปˆ, เบ‚เปเป‰เบกเบนเบ™เป€เบ•เบฑเบกเบซเบผเบฑเบ‡เบˆเบฒเบเบเบฒเบ™เบซเบธเป‰เบกเบซเปเปˆเปƒเบŠเป‰เป€เบงเบฅเบฒเป€เบ–เบดเบ‡ 240 GB. เบœเบนเป‰โ€‹เบˆเบฑเบ”โ€‹เบ•เบฑเป‰เบ‡โ€‹เป„เบ”เป‰โ€‹เบฎเบฑเบšโ€‹เบ›เบฐโ€‹เบเบฑเบ™โ€‹เบงเปˆเบฒโ€‹เบ—เบฑเบ‡โ€‹เบชเบญเบ‡โ€‹เบชเบฐโ€‹เบšเบฑเบšโ€‹เบœเบฐโ€‹เบฅเบดเบ”โ€‹เบฎเบนเบšโ€‹เปเบ•เป‰เบกโ€‹เบ”เบฝเบงโ€‹เบเบฑเบ™โ€‹, เบŠเบถเปˆเบ‡โ€‹เบซเบกเบฒเบโ€‹เบ„เบงเบฒเบกโ€‹เบงเปˆเบฒโ€‹เบชเบฐโ€‹เบšเบฑเบšโ€‹เป€เบ•เบฑเบกโ€‹เปเบกเปˆเบ™โ€‹เบŠเปเป‰เบฒโ€‹เบŠเป‰เบญเบ™โ€‹. เปƒเบ™เบเปเบฅเบฐเบ™เบตเปƒเบ”เบเปเปˆเบ•เบฒเบก, เบเบฒเบ™เป€เบเบฑเบšเบฎเบฑเบเบชเบฒ 50 เบฅเป‰เบฒเบ™เบฎเบนเบšเบžเบฒเบšเปƒเบ™เป„เบŸเบฅเปŒเบเบฃเบฒเบŸเบดเบเบซเบผเบทเปƒเบ™เบฎเบนเบšเปเบšเบšเบ‚เบญเบ‡ arrays เปเบกเปˆเบ™เบ–เบทเบงเปˆเบฒเบšเปเปˆเบกเบตเบœเบปเบ™เบ›เบฐเป‚เบซเบเบ”เบ—เบฑเบ™เบ—เบต, เปเบฅเบฐเบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ•เบฑเบ”เบชเบดเบ™เปƒเบˆเบฅเบงเบกเป„เบŸเบฅเปŒ CSV เบ—เบฑเบ‡เบซเบกเบปเบ”เบˆเบฒเบเบšเปˆเบญเบ™เป€เบเบฑเบšเบกเป‰เบฝเบ™. train_simplified.zip เป€เบ‚เบปเป‰เบฒโ€‹เป„เบ›โ€‹เปƒเบ™โ€‹เบ–เบฒเบ™โ€‹เบ‚เปเป‰โ€‹เบกเบนเบ™โ€‹เบ—เบตเปˆโ€‹เบกเบตโ€‹เบเบฒเบ™โ€‹เบœเบฐโ€‹เบฅเบดเบ”โ€‹เบ•เปเปˆโ€‹เป„เบ›โ€‹เบ‚เบญเบ‡โ€‹เบฎเบนเบšโ€‹เบžเบฒเบšโ€‹เบ‚เบฐโ€‹เบซเบ™เบฒเบ”โ€‹เบ—เบตเปˆโ€‹เบ•เป‰เบญเบ‡โ€‹เบเบฒเบ™ "เบเปˆเบฝเบงโ€‹เบเบฑเบšโ€‹เบเบฒเบ™โ€‹เบšเบดเบ™โ€‹" เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เปเบ•เปˆโ€‹เบฅเบฐ batchโ€‹.

เบฅเบฐเบšเบปเบšเบ—เบตเปˆเบžเบดเบชเบนเบ”เป„เบ”เป‰เบ”เบตเป„เบ”เป‰เบ–เบทเบเป€เบฅเบทเบญเบเป€เบ›เบฑเบ™ DBMS MonetDB, เบ„เบทเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบชเปเบฒเบฅเบฑเบš R เป€เบ›เบฑเบ™เบŠเบธเบ” MonetDBLite. เบŠเบธเบ”เบ›เบฐเบเบญเบšเบกเบตเบชเบฐเบšเบฑเบšเบเบฑเบ‡เบ‚เบญเบ‡เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เปเบฅเบฐเบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบญเบปเบฒเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเป‚เบ”เบเบเบปเบ‡เบˆเบฒเบเบเบญเบ‡เบ›เบฐเบŠเบธเบก R เปเบฅเบฐเป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเบกเบฑเบ™เบขเบนเปˆเบ—เบตเปˆเบ™เบฑเป‰เบ™. เบเบฒเบ™เบชเป‰เบฒเบ‡เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เปเบฅเบฐเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบเบฑเบšเบกเบฑเบ™เบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เบ”เป‰เบงเบเบ„เปเบฒเบชเบฑเปˆเบ‡เบ”เบฝเบง:

con <- DBI::dbConnect(drv = MonetDBLite::MonetDBLite(), Sys.getenv("DBDIR"))

เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ•เป‰เบญเบ‡เบชเป‰เบฒเบ‡เบชเบญเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡: เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบซเบ™เบถเปˆเบ‡เบชเปเบฒเบฅเบฑเบšเบ‚เปเป‰เบกเบนเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”, เบญเบตเบเบญเบฑเบ™เบซเบ™เบถเปˆเบ‡เบชเปเบฒเบฅเบฑเบšเบ‚เปเป‰เบกเบนเบ™เบเบฒเบ™เบšเปเบฅเบดเบเบฒเบ™เบเปˆเบฝเบงเบเบฑเบšเป„เบŸเบฅเปŒเบ—เบตเปˆเบ”เบฒเบงเป‚เบซเบฅเบ” (เป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ”เบ–เป‰เบฒเบกเบตเบšเบฒเบ‡เบขเปˆเบฒเบ‡เบœเบดเบ”เบžเบฒเบ”เปเบฅเบฐเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ•เป‰เบญเบ‡เป„เบ”เป‰เบชเบทเบšเบ•เปเปˆเบซเบผเบฑเบ‡เบˆเบฒเบเบ”เบฒเบงเป‚เบซเบฅเบ”เบซเบผเบฒเบเป†เป„เบŸเบฅเปŒ):

เบเบฒเบ™เบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡

if (!DBI::dbExistsTable(con, "doodles")) {
  DBI::dbCreateTable(
    con = con,
    name = "doodles",
    fields = c(
      "countrycode" = "char(2)",
      "drawing" = "text",
      "key_id" = "bigint",
      "recognized" = "bool",
      "timestamp" = "timestamp",
      "word" = "text"
    )
  )
}

if (!DBI::dbExistsTable(con, "upload_log")) {
  DBI::dbCreateTable(
    con = con,
    name = "upload_log",
    fields = c(
      "id" = "serial",
      "file_name" = "text UNIQUE",
      "uploaded" = "bool DEFAULT false"
    )
  )
}

เบงเบดเบ—เบตเบ—เบตเปˆเป„เบงเบ—เบตเปˆเบชเบธเบ”เบ—เบตเปˆเบˆเบฐเป‚เบซเบฅเบ”เบ‚เปเป‰เบกเบนเบ™เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เปเบกเปˆเบ™เบเบฒเบ™เบ„เบฑเบ”เบฅเบญเบเป„เบŸเบฅเปŒ CSV เป‚เบ”เบเบเบปเบ‡เป‚เบ”เบเปƒเบŠเป‰ SQL - เบ„เปเบฒเบชเบฑเปˆเบ‡ COPY OFFSET 2 INTO tablename FROM path USING DELIMITERS ',','n','"' NULL AS '' BEST EFFORTเบšเปˆเบญเบ™เบ—เบตเปˆ tablename - เบŠเบทเปˆโ€‹เบ•เบฒโ€‹เบ•เบฐโ€‹เบฅเบฒเบ‡โ€‹เปเบฅเบฐโ€‹ path - เป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡เป„เบ›เบซเบฒเป„เบŸเบฅเปŒ. เปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆเป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเบฎเบงเบšเบฎเบงเบก, เบกเบฑเบ™เป„เบ”เป‰เบ–เบทเบเบ„เบปเป‰เบ™เบžเบปเบšเบงเปˆเบฒเบเบฒเบ™เบเปเปˆเบชเป‰เบฒเบ‡เปƒเบ™เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ” unzip เปƒเบ™ R เบšเปเปˆเป€เบฎเบฑเบ”เบงเบฝเบเบขเปˆเบฒเบ‡เบ–เบทเบเบ•เป‰เบญเบ‡เบเบฑเบšเป„เบŸเบฅเปŒเบˆเปเบฒเบ™เบงเบ™เบซเบ™เบถเปˆเบ‡เบˆเบฒเบเบšเปˆเบญเบ™เป€เบเบฑเบšเบกเป‰เบฝเบ™, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เปƒเบŠเป‰เบฅเบฐเบšเบปเบš unzip (เปƒเบŠเป‰เบžเบฒเบฅเบฒเบกเบดเป€เบ•เบต getOption("unzip")).

เบŸเบฑเบ‡เบŠเบฑเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ‚เบฝเบ™เปƒเบชเปˆเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™

#' @title ะ˜ะทะฒะปะตั‡ะตะฝะธะต ะธ ะทะฐะณั€ัƒะทะบะฐ ั„ะฐะนะปะพะฒ
#'
#' @description
#' ะ˜ะทะฒะปะตั‡ะตะฝะธะต CSV-ั„ะฐะนะปะพะฒ ะธะท ZIP-ะฐั€ั…ะธะฒะฐ ะธ ะทะฐะณั€ัƒะทะบะฐ ะธั… ะฒ ะฑะฐะทัƒ ะดะฐะฝะฝั‹ั…
#'
#' @param con ะžะฑัŠะตะบั‚ ะฟะพะดะบะปัŽั‡ะตะฝะธั ะบ ะฑะฐะทะต ะดะฐะฝะฝั‹ั… (ะบะปะฐัั `MonetDBEmbeddedConnection`).
#' @param tablename ะะฐะทะฒะฐะฝะธะต ั‚ะฐะฑะปะธั†ั‹ ะฒ ะฑะฐะทะต ะดะฐะฝะฝั‹ั….
#' @oaram zipfile ะŸัƒั‚ัŒ ะบ ZIP-ะฐั€ั…ะธะฒัƒ.
#' @oaram filename ะ˜ะผั ั„ะฐะนะปะฐ ะฒะฝัƒั€ะธ ZIP-ะฐั€ั…ะธะฒะฐ.
#' @param preprocess ะคัƒะฝะบั†ะธั ะฟั€ะตะดะพะฑั€ะฐะฑะพั‚ะบะธ, ะบะพั‚ะพั€ะฐั ะฑัƒะดะตั‚ ะฟั€ะธะผะตะฝะตะฝะฐ ะธะทะฒะปะตั‡ั‘ะฝะฝะพะผัƒ ั„ะฐะนะปัƒ.
#'   ะ”ะพะปะถะฝะฐ ะฟั€ะธะฝะธะผะฐั‚ัŒ ะพะดะธะฝ ะฐั€ะณัƒะผะตะฝั‚ `data` (ะพะฑัŠะตะบั‚ `data.table`).
#'
#' @return `TRUE`.
#'
upload_file <- function(con, tablename, zipfile, filename, preprocess = NULL) {
  # ะŸั€ะพะฒะตั€ะบะฐ ะฐั€ะณัƒะผะตะฝั‚ะพะฒ
  checkmate::assert_class(con, "MonetDBEmbeddedConnection")
  checkmate::assert_string(tablename)
  checkmate::assert_string(filename)
  checkmate::assert_true(DBI::dbExistsTable(con, tablename))
  checkmate::assert_file_exists(zipfile, access = "r", extension = "zip")
  checkmate::assert_function(preprocess, args = c("data"), null.ok = TRUE)

  # ะ˜ะทะฒะปะตั‡ะตะฝะธะต ั„ะฐะนะปะฐ
  path <- file.path(tempdir(), filename)
  unzip(zipfile, files = filename, exdir = tempdir(), 
        junkpaths = TRUE, unzip = getOption("unzip"))
  on.exit(unlink(file.path(path)))

  # ะŸั€ะธะผะตะฝัะตะผ ั„ัƒะฝะบั†ะธั ะฟั€ะตะดะพะฑั€ะฐะฑะพั‚ะบะธ
  if (!is.null(preprocess)) {
    .data <- data.table::fread(file = path)
    .data <- preprocess(data = .data)
    data.table::fwrite(x = .data, file = path, append = FALSE)
    rm(.data)
  }

  # ะ—ะฐะฟั€ะพั ะบ ะ‘ะ” ะฝะฐ ะธะผะฟะพั€ั‚ CSV
  sql <- sprintf(
    "COPY OFFSET 2 INTO %s FROM '%s' USING DELIMITERS ',','n','"' NULL AS '' BEST EFFORT",
    tablename, path
  )
  # ะ’ั‹ะฟะพะปะฝะตะฝะธะต ะทะฐะฟั€ะพัะฐ ะบ ะ‘ะ”
  DBI::dbExecute(con, sql)

  # ะ”ะพะฑะฐะฒะปะตะฝะธะต ะทะฐะฟะธัะธ ะพะฑ ัƒัะฟะตัˆะฝะพะน ะทะฐะณั€ัƒะทะบะต ะฒ ัะปัƒะถะตะฑะฝัƒัŽ ั‚ะฐะฑะปะธั†ัƒ
  DBI::dbExecute(con, sprintf("INSERT INTO upload_log(file_name, uploaded) VALUES('%s', true)",
                              filename))

  return(invisible(TRUE))
}

เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เบเบฒเบ™เบซเบฑเบ™เบ›เปˆเบฝเบ™เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบเปˆเบญเบ™เบ—เบตเปˆเบˆเบฐเบ‚เบฝเบ™เบกเบฑเบ™เปƒเบชเปˆเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™, เบกเบฑเบ™เบžเบฝเบ‡เบžเปเบ—เบตเปˆเบˆเบฐเบœเปˆเบฒเบ™เปƒเบ™เบเบฒเบ™เป‚เบ•เป‰เบ–เบฝเบ‡ preprocess เบŸเบฑเบ‡เบŠเบฑเบ™เบ—เบตเปˆเบˆเบฐเบ›เปˆเบฝเบ™เบ‚เปเป‰เบกเบนเบ™.

เบฅเบฐเบซเบฑเบ”เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป‚เบซเบผเบ”เบ‚เปเป‰เบกเบนเบ™เบ•เบฒเบกเบฅเปเบฒเบ”เบฑเบšเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™:

เบเบฒเบ™เบ‚เบฝเบ™เบ‚เปเป‰เบกเบนเบ™เปƒเบชเปˆเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™

# ะกะฟะธัะพะบ ั„ะฐะนะปะพะฒ ะดะปั ะทะฐะฟะธัะธ
files <- unzip(zipfile, list = TRUE)$Name

# ะกะฟะธัะพะบ ะธัะบะปัŽั‡ะตะฝะธะน, ะตัะปะธ ั‡ะฐัั‚ัŒ ั„ะฐะนะปะพะฒ ัƒะถะต ะฑั‹ะปะฐ ะทะฐะณั€ัƒะถะตะฝะฐ
to_skip <- DBI::dbGetQuery(con, "SELECT file_name FROM upload_log")[[1L]]
files <- setdiff(files, to_skip)

if (length(files) > 0L) {
  # ะ—ะฐะฟัƒัะบะฐะตะผ ั‚ะฐะนะผะตั€
  tictoc::tic()
  # ะŸั€ะพะณั€ะตัั ะฑะฐั€
  pb <- txtProgressBar(min = 0L, max = length(files), style = 3)
  for (i in seq_along(files)) {
    upload_file(con = con, tablename = "doodles", 
                zipfile = zipfile, filename = files[i])
    setTxtProgressBar(pb, i)
  }
  close(pb)
  # ะžัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ั‚ะฐะนะผะตั€
  tictoc::toc()
}

# 526.141 sec elapsed - ะบะพะฟะธั€ะพะฒะฐะฝะธะต SSD->SSD
# 558.879 sec elapsed - ะบะพะฟะธั€ะพะฒะฐะฝะธะต USB->SSD

เป€เบงเบฅเบฒเป‚เบซเบผเบ”เบ‚เปเป‰เบกเบนเบ™เบญเบฒเบ”เบˆเบฐเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เป„เบ›เบ•เบฒเบกเบ„เบธเบ™เบฅเบฑเบเบชเบฐเบ™เบฐเบ„เบงเบฒเบกเป„เบงเบ‚เบญเบ‡เป„เบ”เบ—เบตเปˆเปƒเบŠเป‰. เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ, เบเบฒเบ™เบญเปˆเบฒเบ™เปเบฅเบฐเบเบฒเบ™เบ‚เบฝเบ™เบžเบฒเบเปƒเบ™เบซเบ™เบถเปˆเบ‡ SSD เบซเบผเบทเบˆเบฒเบ flash drive (เป„เบŸเบฅเปŒเปเบซเบผเปˆเบ‡) เป„เบ›เบซเบฒ SSD (DB) เปƒเบŠเป‰เป€เบงเบฅเบฒเบซเบ™เป‰เบญเบเบเบงเปˆเบฒ 10 เบ™เบฒเบ—เบต.

เบกเบฑเบ™เปƒเบŠเป‰เป€เบงเบฅเบฒเบชเบญเบ‡เบชเบฒเบกเบงเบดเบ™เบฒเบ—เบตเป€เบžเบทเปˆเบญเบชเป‰เบฒเบ‡เบ–เบฑเบ™เบ—เบตเปˆเบกเบตเบ›เป‰เบฒเบเบŠเบทเปˆเบ‚เบญเบ‡เบŠเบฑเป‰เบ™ integer เปเบฅเบฐเบ–เบฑเบ™เบ”เบฑเบ”เบชเบฐเบ™เบต (ORDERED INDEX) เบ”เป‰เบงเบเบ•เบปเบงเป€เบฅเบเปเบ–เบงเบ—เบตเปˆเบเบฒเบ™เบชเบฑเบ‡เป€เบเบ”เบเบฒเบ™เบˆเบฐเบ–เบทเบเบเบปเบเบ•เบปเบงเบขเปˆเบฒเบ‡เปƒเบ™เป€เบงเบฅเบฒเบชเป‰เบฒเบ‡เบŠเบธเบ”:

เบเบฒเบ™เบชเป‰เบฒเบ‡เบ–เบฑเบ™ เปเบฅเบฐเบ”เบฑเบ”เบŠเบฐเบ™เบตเป€เบžเบตเปˆเบกเป€เบ•เบตเบก

message("Generate lables")
invisible(DBI::dbExecute(con, "ALTER TABLE doodles ADD label_int int"))
invisible(DBI::dbExecute(con, "UPDATE doodles SET label_int = dense_rank() OVER (ORDER BY word) - 1"))

message("Generate row numbers")
invisible(DBI::dbExecute(con, "ALTER TABLE doodles ADD id serial"))
invisible(DBI::dbExecute(con, "CREATE ORDERED INDEX doodles_id_ord_idx ON doodles(id)"))

เป€เบžเบทเปˆเบญเปเบเป‰เป„เบ‚เบšเบฑเบ™เบซเบฒเบเบฒเบ™เบชเป‰เบฒเบ‡ batch เบชเบธเบ”เบšเบดเบ™, เบžเบงเบเป€เบฎเบปเบฒเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป„เบ”เป‰เบšเบฑเบ™เบฅเบธเบ„เบงเบฒเบกเป„เบงเบชเบนเบ‡เบชเบธเบ”เบ‚เบญเบ‡เบเบฒเบ™เบชเบฐเบเบฑเบ”เปเบ–เบงเบชเบธเปˆเบกเบˆเบฒเบเบ•เบฒเบ•เบฐเบฅเบฒเบ‡. doodles. เบชเปเบฒเบฅเบฑเบšเบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ™เปเบฒเปƒเบŠเป‰ 3 tricks. เบ—เปเบฒเบญเบดเบ”เปเบกเปˆเบ™เป€เบžเบทเปˆเบญเบซเบผเบธเบ”เบœเปˆเบญเบ™เบ‚เบฐเบซเบ™เบฒเบ”เบ‚เบญเบ‡เบ›เบฐเป€เบžเบ”เบ—เบตเปˆเป€เบเบฑเบšเบฎเบฑเบเบชเบฒ ID เบเบฒเบ™เบชเบฑเบ‡เป€เบเบ”เบเบฒเบ™. เปƒเบ™เบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบš, เบ›เบฐเป€เบžเบ”เบ—เบตเปˆเบ•เป‰เบญเบ‡เบเบฒเบ™เป€เบžเบทเปˆเบญเป€เบเบฑเบšเบฎเบฑเบเบชเบฒ ID เปเบกเปˆเบ™ bigint, เปเบ•เปˆเบˆเปเบฒเบ™เบงเบ™เบ‚เบญเบ‡เบเบฒเบ™เบชเบฑเบ‡เป€เบเบ”เบเบฒเบ™เป€เบฎเบฑเบ”เปƒเบซเป‰เบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เบ—เบตเปˆเบˆเบฐเป€เบซเบกเบฒเบฐเบ•เบปเบงเบฅเบฐเบšเบธเบ‚เบญเบ‡เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒ, เป€เบ—เบปเปˆเบฒเบเบฑเบšเบˆเปเบฒเบ™เบงเบ™เบ„เปเบฒเบชเบฑเปˆเบ‡, เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ›เบฐเป€เบžเบ”. int. เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ™เบตเป‰, เบเบฒเบ™เบ„เบปเป‰เบ™เบซเบฒเปเบกเปˆเบ™เป„เบงเบเบงเปˆเบฒ. trick เบ—เบตเบชเบญเบ‡เปเบกเปˆเบ™เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰ ORDERED INDEX โ€” เบžเบงเบโ€‹เป€เบฎเบปเบฒโ€‹เป„เบ”เป‰โ€‹เป€เบ‚เบปเป‰เบฒโ€‹เบกเบฒโ€‹เปƒเบ™โ€‹เบเบฒเบ™โ€‹เบ•เบฑเบ”โ€‹เบชเบดเบ™โ€‹เปƒเบˆโ€‹เบ™เบตเป‰โ€‹เป€เบ›เบฑเบ™โ€‹เบ›เบฐโ€‹เบˆเบฑเบโ€‹, เป‚เบ”เบโ€‹เบœเปˆเบฒเบ™โ€‹เบเบฒเบ™โ€‹เบ—เบฑเบ‡โ€‹เบซเบกเบปเบ”โ€‹เบ—เบตเปˆโ€‹เบกเบตโ€‹เบขเบนเปˆโ€‹ เบ—เบฒเบ‡เป€เบฅเบทเบญเบ. เบญเบฑเบ™เบ—เบตเบชเบฒเบกเปเบกเปˆเบ™เบเบฒเบ™เปƒเบŠเป‰เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเปเบšเบšเบžเบฒเบฅเบฒเบกเบดเป€เบ•เบต. เป‚เบ”เบเป€เบ™เบทเป‰เบญเปเบ—เป‰เปเบฅเป‰เบงเบ‚เบญเบ‡เบงเบดเบ—เบตเบเบฒเบ™เปเบกเปˆเบ™เป€เบžเบทเปˆเบญเบ›เบฐเบ•เบดเบšเบฑเบ”เบ„เปเบฒเบชเบฑเปˆเบ‡เบซเบ™เบถเปˆเบ‡เบ„เบฑเป‰เบ‡ PREPARE เบ”เป‰เบงเบเบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบเบฒเบ™เบชเบฐเปเบ”เบ‡เบญเบญเบเบ—เบตเปˆเบเบฝเบกเป„เบงเป‰เบ•เปเปˆเบกเบฒเปƒเบ™เป€เบงเบฅเบฒเบชเป‰เบฒเบ‡เบเบธเปˆเบกเบ„เปเบฒเบ–เบฒเบกเบ‚เบญเบ‡เบ›เบฐเป€เบžเบ”เบ”เบฝเบงเบเบฑเบ™, เปเบ•เปˆเปƒเบ™เบ„เบงเบฒเบกเป€เบ›เบฑเบ™เบˆเบดเบ‡เบกเบตเบ›เบฐเป‚เบซเบเบ”เปƒเบ™เบเบฒเบ™เบ›เบฝเบšเบ—เบฝเบšเบเบฑเบšเปเบšเบšเบ‡เปˆเบฒเบเป†. SELECT เป„เบ”เป‰เบเบฒเบเป€เบ›เบฑเบ™เบขเบนเปˆเปƒเบ™เบ‚เบญเบšเป€เบ‚เบ”เบ‚เบญเบ‡เบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”เบ—เบฒเบ‡เบชเบฐเบ–เบดเบ•เบด.

เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบญเบฑเบšเป‚เบซเบฅเบ”เบ‚เปเป‰เบกเบนเบ™เบˆเบฐเปƒเบŠเป‰ RAM เบšเปเปˆเป€เบเบตเบ™ 450 MB. เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เบงเบดเบ—เบตเบเบฒเบ™เบ—เบตเปˆเบญเบฐเบ—เบดเบšเบฒเบเบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบเป‰เบฒเบเบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบกเบตเบ™เปเป‰เบฒเบซเบ™เบฑเบเบซเบผเบฒเบเบชเบดเบšเบเบดเบเบฒเป„เบšเปƒเบ™เป€เบเบทเบญเบšเบ—เบธเบเบฎเบฒเบ”เปเบงเบ‡เบปเบšเบ›เบฐเบกเบฒเบ™, เบฅเบงเบกเบ—เบฑเบ‡เบญเบธเบ›เบฐเบเบญเบ™เบเบฐเบ”เบฒเบ™เบ”เบฝเบง, เป€เบŠเบดเปˆเบ‡เบ”เบตเบซเบผเบฒเบ.

เบ—เบฑเบ‡เบซเบกเบปเบ”เบ—เบตเปˆเบเบฑเบ‡เป€เบซเบผเบทเบญเปเบกเปˆเบ™เป€เบžเบทเปˆเบญเบงเบฑเบ”เปเบ—เบเบ„เบงเบฒเบกเป„เบงเปƒเบ™เบเบฒเบ™เบ”เบถเบ‡เบ‚เปเป‰เบกเบนเบ™ (เปเบšเบšเบชเบธเปˆเบก) เปเบฅเบฐเบ›เบฐเป€เบกเบตเบ™เบเบฒเบ™เบ‚เบฐเบซเบ™เบฒเบ”เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบเบฒเบ™เป€เบเบฑเบšเบ•เบปเบงเบขเปˆเบฒเบ‡เบ‚เบญเบ‡เบ‚เบฐเบซเบ™เบฒเบ”เบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™:

เบกเบฒเบ”เบ•เบฐเบ–เบฒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™

library(ggplot2)

set.seed(0)
# ะŸะพะดะบะปัŽั‡ะตะฝะธะต ะบ ะฑะฐะทะต ะดะฐะฝะฝั‹ั…
con <- DBI::dbConnect(MonetDBLite::MonetDBLite(), Sys.getenv("DBDIR"))

# ะคัƒะฝะบั†ะธั ะดะปั ะฟะพะดะณะพั‚ะพะฒะบะธ ะทะฐะฟั€ะพัะฐ ะฝะฐ ัั‚ะพั€ะพะฝะต ัะตั€ะฒะตั€ะฐ
prep_sql <- function(batch_size) {
  sql <- sprintf("PREPARE SELECT id FROM doodles WHERE id IN (%s)",
                 paste(rep("?", batch_size), collapse = ","))
  res <- DBI::dbSendQuery(con, sql)
  return(res)
}

# ะคัƒะฝะบั†ะธั ะดะปั ะธะทะฒะปะตั‡ะตะฝะธั ะดะฐะฝะฝั‹ั…
fetch_data <- function(rs, batch_size) {
  ids <- sample(seq_len(n), batch_size)
  res <- DBI::dbFetch(DBI::dbBind(rs, as.list(ids)))
  return(res)
}

# ะŸั€ะพะฒะตะดะตะฝะธะต ะทะฐะผะตั€ะฐ
res_bench <- bench::press(
  batch_size = 2^(4:10),
  {
    rs <- prep_sql(batch_size)
    bench::mark(
      fetch_data(rs, batch_size),
      min_iterations = 50L
    )
  }
)
# ะŸะฐั€ะฐะผะตั‚ั€ั‹ ะฑะตะฝั‡ะผะฐั€ะบะฐ
cols <- c("batch_size", "min", "median", "max", "itr/sec", "total_time", "n_itr")
res_bench[, cols]

#   batch_size      min   median      max `itr/sec` total_time n_itr
#        <dbl> <bch:tm> <bch:tm> <bch:tm>     <dbl>   <bch:tm> <int>
# 1         16   23.6ms  54.02ms  93.43ms     18.8        2.6s    49
# 2         32     38ms  84.83ms 151.55ms     11.4       4.29s    49
# 3         64   63.3ms 175.54ms 248.94ms     5.85       8.54s    50
# 4        128   83.2ms 341.52ms 496.24ms     3.00      16.69s    50
# 5        256  232.8ms 653.21ms 847.44ms     1.58      31.66s    50
# 6        512  784.6ms    1.41s    1.98s     0.740       1.1m    49
# 7       1024  681.7ms    2.72s    4.06s     0.377      2.16m    49

ggplot(res_bench, aes(x = factor(batch_size), y = median, group = 1)) +
  geom_point() +
  geom_line() +
  ylab("median time, s") +
  theme_minimal()

DBI::dbDisconnect(con, shutdown = TRUE)

เบเบฒเบ™เบฎเบฑเบšเบฎเบนเป‰ Doodle เปเบ•เป‰เบกเบ”เปˆเบงเบ™: เบงเบดเบ—เบตเบเบฒเบ™เบชเป‰เบฒเบ‡เป€เบžเบทเปˆเบญเบ™เบเบฑเบš R, C++ เปเบฅเบฐเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural

2. เบเบฒเบ™เบเบฐเบเบฝเบกเบŠเบธเบ”

เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบเบฐเบเบฝเบก batch เบ—เบฑเบ‡เบซเบกเบปเบ”เบ›เบฐเบเบญเบšเบ”เป‰เบงเบเบ‚เบฑเป‰เบ™เบ•เบญเบ™เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

  1. parsing JSONs เบซเบผเบฒเบเบญเบฑเบ™เบ—เบตเปˆเบกเบต vectors เบ‚เบญเบ‡ strings เบ—เบตเปˆเบกเบตเบˆเบธเบ”เบ›เบฐเบชเบฒเบ™เบ‡เบฒเบ™.
  2. เบเบฒเบ™โ€‹เปเบ•เป‰เบกโ€‹เป€เบชเบฑเป‰เบ™โ€‹เบชเบตโ€‹เป‚เบ”เบโ€‹เบญเบตเบ‡โ€‹เปƒเบชเปˆโ€‹เบเบฒเบ™โ€‹เบ›เบฐโ€‹เบชเบฒเบ™โ€‹เบ‡เบฒเบ™โ€‹เบ‚เบญเบ‡โ€‹เบˆเบธเบ”โ€‹เปƒเบ™โ€‹เบฎเบนเบšโ€‹เบžเบฒเบšโ€‹เบ‚เบฐโ€‹เบซเบ™เบฒเบ”โ€‹เบ—เบตเปˆโ€‹เบ•เป‰เบญเบ‡โ€‹เบเบฒเบ™ (เบ•เบปเบงโ€‹เบขเปˆเบฒเบ‡โ€‹, 256ร—256 เบซเบผเบท 128ร—128โ€‹)โ€‹.
  3. เบเบฒเบ™เปเบ›เบ‡เบฎเบนเบšเบžเบฒเบšเบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ tensor.

เป€เบ›เบฑเบ™เบชเปˆเบงเบ™เบซเบ™เบถเปˆเบ‡เบ‚เบญเบ‡เบเบฒเบ™เปเบ‚เปˆเบ‡เบ‚เบฑเบ™เบฅเบฐเบซเบงเปˆเบฒเบ‡ Python kernels, เบšเบฑเบ™เบซเบฒเป„เบ”เป‰เบ–เบทเบเปเบเป‰เป„เบ‚เบ•เบปเป‰เบ™เบ•เปเป‚เบ”เบเปƒเบŠเป‰ OpenCV. เบซเบ™เบถเปˆเบ‡เปƒเบ™ analogues เบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบเปเบฅเบฐเบŠเบฑเบ”เป€เบˆเบ™เบ—เบตเปˆเบชเบธเบ”เปƒเบ™ R เบˆเบฐเบกเบตเบฅเบฑเบเบชเบฐเบ™เบฐเบ™เบตเป‰:

เบเบฒเบ™โ€‹เบ›เบฐโ€‹เบ•เบดโ€‹เบšเบฑเบ” JSON เบเบฒเบ™โ€‹เบ›เปˆเบฝเบ™ Tensor เปƒเบ™ R

r_process_json_str <- function(json, line.width = 3, 
                               color = TRUE, scale = 1) {
  # ะŸะฐั€ัะธะฝะณ JSON
  coords <- jsonlite::fromJSON(json, simplifyMatrix = FALSE)
  tmp <- tempfile()
  # ะฃะดะฐะปัะตะผ ะฒั€ะตะผะตะฝะฝั‹ะน ั„ะฐะนะป ะฟะพ ะทะฐะฒะตั€ัˆะตะฝะธัŽ ั„ัƒะฝะบั†ะธะธ
  on.exit(unlink(tmp))
  png(filename = tmp, width = 256 * scale, height = 256 * scale, pointsize = 1)
  # ะŸัƒัั‚ะพะน ะณั€ะฐั„ะธะบ
  plot.new()
  # ะ ะฐะทะผะตั€ ะพะบะฝะฐ ะณั€ะฐั„ะธะบะฐ
  plot.window(xlim = c(256 * scale, 0), ylim = c(256 * scale, 0))
  # ะฆะฒะตั‚ะฐ ะปะธะฝะธะน
  cols <- if (color) rainbow(length(coords)) else "#000000"
  for (i in seq_along(coords)) {
    lines(x = coords[[i]][[1]] * scale, y = coords[[i]][[2]] * scale, 
          col = cols[i], lwd = line.width)
  }
  dev.off()
  # ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะธะทะพะฑั€ะฐะถะตะฝะธั ะฒ 3-ั… ะผะตั€ะฝั‹ะน ะผะฐััะธะฒ
  res <- png::readPNG(tmp)
  return(res)
}

r_process_json_vector <- function(x, ...) {
  res <- lapply(x, r_process_json_str, ...)
  # ะžะฑัŠะตะดะธะฝะตะฝะธะต 3-ั… ะผะตั€ะฝั‹ั… ะผะฐััะธะฒะพะฒ ะบะฐั€ั‚ะธะฝะพะบ ะฒ 4-ั… ะผะตั€ะฝั‹ะน ะฒ ั‚ะตะฝะทะพั€
  res <- do.call(abind::abind, c(res, along = 0))
  return(res)
}

เบเบฒเบ™เปเบ•เป‰เบกเบฎเบนเบšเปเบกเปˆเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เป‚เบ”เบเปƒเบŠเป‰เป€เบ„เบทเปˆเบญเบ‡เบกเบท R เบกเบฒเบ”เบ•เบฐเบ–เบฒเบ™เปเบฅเบฐเบ–เบทเบเบšเบฑเบ™เบ—เบถเบเป„เบงเป‰เปƒเบ™ PNG เบŠเบปเปˆเบงเบ„เบฒเบงเบ—เบตเปˆเป€เบเบฑเบšเป„เบงเป‰เปƒเบ™ RAM (เปƒเบ™ Linux, เป„เบ”เป€เบฅเบเบฐเบ—เปเบฅเบต R เบŠเบปเปˆเบงเบ„เบฒเบงเปเบกเปˆเบ™เบขเบนเปˆเปƒเบ™เป„เบ”เป€เบฅเบเบฐเบ—เปเบฅเบต /tmp, เบ•เบดเบ”เบ•เบฑเป‰เบ‡เบขเบนเปˆเปƒเบ™ RAM). เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™, เป„เบŸเบฅเปŒเบ™เบตเป‰เบˆเบฐเบ–เบทเบเบญเปˆเบฒเบ™เป€เบ›เบฑเบ™ array เบชเบฒเบกเบกเบดเบ•เบดเบฅเบฐเบ”เบฑเบšเบ—เบตเปˆเบกเบตเบ•เบปเบงเป€เบฅเบเบ•เบฑเป‰เบ‡เปเบ•เปˆ 0 เบซเบฒ 1. เบ™เบตเป‰เปเบกเปˆเบ™เบชเบดเปˆเบ‡เบชเปเบฒเบ„เบฑเบ™เป€เบžเบฒเบฐเบงเปˆเบฒ BMP เบ—เปเบฒเบกเบฐเบ”เบฒเบเบงเปˆเบฒเบˆเบฐเบ–เบทเบเบญเปˆเบฒเบ™เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบญเบฒเป€เบฃเบ”เบดเบšเบ—เบตเปˆเบกเบตเบฅเบฐเบซเบฑเบ”เบชเบต hex.

เบ‚เปโ€‹เปƒเบซเป‰โ€‹เบ—เบปเบ”โ€‹เบชเบญเบšโ€‹เบœเบปเบ™โ€‹เป„เบ”เป‰โ€‹เบฎเบฑเบšโ€‹:

zip_file <- file.path("data", "train_simplified.zip")
csv_file <- "cat.csv"
unzip(zip_file, files = csv_file, exdir = tempdir(), 
      junkpaths = TRUE, unzip = getOption("unzip"))
tmp_data <- data.table::fread(file.path(tempdir(), csv_file), sep = ",", 
                              select = "drawing", nrows = 10000)
arr <- r_process_json_str(tmp_data[4, drawing])
dim(arr)
# [1] 256 256   3
plot(magick::image_read(arr))

เบเบฒเบ™เบฎเบฑเบšเบฎเบนเป‰ Doodle เปเบ•เป‰เบกเบ”เปˆเบงเบ™: เบงเบดเบ—เบตเบเบฒเบ™เบชเป‰เบฒเบ‡เป€เบžเบทเปˆเบญเบ™เบเบฑเบš R, C++ เปเบฅเบฐเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural

batch เบ•เบปเบงเบ‚เบญเบ‡เบกเบฑเบ™เป€เบญเบ‡เบˆเบฐเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบชเป‰เบฒเบ‡เบ•เบฑเป‰เบ‡เบ‚เบถเป‰เบ™เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

res <- r_process_json_vector(tmp_data[1:4, drawing], scale = 0.5)
str(res)
 # num [1:4, 1:128, 1:128, 1:3] 1 1 1 1 1 1 1 1 1 1 ...
 # - attr(*, "dimnames")=List of 4
 #  ..$ : NULL
 #  ..$ : NULL
 #  ..$ : NULL
 #  ..$ : NULL

เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ™เบตเป‰เป€เบšเบดเปˆเบ‡เบ„เบทเบงเปˆเบฒเบšเปเปˆเป€เบซเบกเบฒเบฐเบชเบปเบกเบ—เบตเปˆเบชเบธเบ”เบชเปเบฒเบฅเบฑเบšเบžเบงเบเป€เบฎเบปเบฒ, เบ™เบฑเบšเบ•เบฑเป‰เบ‡เปเบ•เปˆเบเบฒเบ™เบชเป‰เบฒเบ‡เบŠเบธเบ”เปƒเบซเบเปˆเปƒเบŠเป‰เป€เบงเบฅเบฒเบ”เบปเบ™, เปเบฅเบฐเบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ•เบฑเบ”เบชเบดเบ™เปƒเบˆเบ—เบตเปˆเบˆเบฐเปƒเบŠเป‰เบ›เบฐเป‚เบเบ”เบˆเบฒเบเบ›เบฐเบชเบปเบšเบเบฒเบ™เบ‚เบญเบ‡เป€เบžเบทเปˆเบญเบ™เบฎเปˆเบงเบกเบ‡เบฒเบ™เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเป‚เบ”เบเปƒเบŠเป‰เบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ”เบ—เบตเปˆเบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบš. OpenCV. เปƒเบ™โ€‹เป€เบงโ€‹เบฅเบฒโ€‹เบ™เบฑเป‰เบ™โ€‹เบšเปเปˆโ€‹เบกเบตโ€‹เบŠเบธเบ”โ€‹เบ—เบตเปˆโ€‹เบเบฝเบกโ€‹เบžเป‰เบญเบกโ€‹เบชเปเบฒโ€‹เบฅเบฑเบš R (เบšเปเปˆโ€‹เบกเบตโ€‹เปƒเบ™โ€‹เบ›เบฑเบ”โ€‹เบˆเบธโ€‹เบšเบฑเบ™โ€‹)โ€‹, เบชเบฐโ€‹เบ™เบฑเป‰เบ™โ€‹เบเบฒเบ™โ€‹เบ›เบฐโ€‹เบ•เบดโ€‹เบšเบฑเบ”โ€‹เบ•เปเบฒโ€‹เปˆโ€‹เบชเบธเบ”โ€‹เบ—เบตเปˆโ€‹เบ‚เบญเบ‡โ€‹เบเบฒเบ™โ€‹เบ—เปเบฒโ€‹เบ‡เบฒเบ™โ€‹เบ—เบตเปˆโ€‹เบ•เป‰เบญเบ‡โ€‹เบเบฒเบ™โ€‹เป„เบ”เป‰โ€‹เบ–เบทเบโ€‹เบฅเบฒเบโ€‹เบฅเบฑเบโ€‹เบญเบฑเบโ€‹เบชเบญเบ™โ€‹เปƒเบ™ C ++ เบเบฑเบšโ€‹เบเบฒเบ™โ€‹เป€เบŠเบทเปˆเบญเบกโ€‹เป‚เบเบ‡โ€‹เป€เบ‚เบปเป‰เบฒโ€‹เป„เบ›โ€‹เปƒเบ™โ€‹เบฅเบฐโ€‹เบซเบฑเบ” R เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹. Rcpp.

เป€เบžเบทเปˆเบญเปเบเป‰เป„เบ‚เบšเบฑเบ™เบซเบฒ, เบŠเบธเบ”เปเบฅเบฐเบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ”เบ•เปเปˆเป„เบ›เบ™เบตเป‰เป„เบ”เป‰เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰:

  1. OpenCV เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเบฎเบนเบšเบžเบฒเบšเปเบฅเบฐเบเบฒเบ™เปเบ•เป‰เบกเป€เบชเบฑเป‰เบ™. เปƒเบŠเป‰เบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ”เบฅเบฐเบšเบปเบšเบ—เบตเปˆเบ•เบดเบ”เบ•เบฑเป‰เบ‡เป„เบงเป‰เบเปˆเบญเบ™เปเบฅเบฐเป„เบŸเบฅเปŒเบชเปˆเบงเบ™เบซเบปเบง, เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเป‚เบเบ‡เปเบšเบšเป€เบ„เบทเปˆเบญเบ™เป„เบซเบง.

  2. xtensor เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบš arrays multidimensional เปเบฅเบฐ tensors เบžเบงเบโ€‹เป€เบฎเบปเบฒโ€‹เป„เบ”เป‰โ€‹เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹เป„เบŸเบฅโ€‹เปŒ header เบฅเบงเบกโ€‹เบขเบนเปˆโ€‹เปƒเบ™โ€‹เบŠเบธเบ” R เบ‚เบญเบ‡โ€‹เบŠเบทเปˆโ€‹เบ”เบฝเบงโ€‹เบเบฑเบ™โ€‹. เบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ”เบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเบญเบฐเป€เบฃเบซเบผเบฒเบเบกเบดเบ•เบดเบฅเบฐเบ”เบฑเบš, เบ—เบฑเบ‡เปƒเบ™เปเบ–เบงเบ—เบตเปˆเบชเปเบฒเบ„เบฑเบ™เปเบฅเบฐเบ–เบฑเบ™เบ—เบตเปˆเบชเปเบฒเบ„เบฑเบ™.

  3. ndjson เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐ JSON. เบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ”เบ™เบตเป‰เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เปƒเบ™ xtensor เบญเบฑเบ”เบ•เบฐเป‚เบ™เบกเบฑเบ”เบ–เป‰เบฒเบกเบฑเบ™เบกเบตเบขเบนเปˆเปƒเบ™เป‚เบ„เบ‡เบเบฒเบ™.

  4. RcppThread เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบˆเบฑเบ”เบ•เบฑเป‰เบ‡เบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบซเบผเบฒเบเบเบฐเบ—เบนเป‰เบ‚เบญเบ‡ vector เบˆเบฒเบ JSON. เปƒเบŠเป‰เป„เบŸเบฅเปŒเบชเปˆเบงเบ™เบซเบปเบงเบ—เบตเปˆเบชเบฐเปœเบญเบ‡เปƒเบซเป‰เป‚เบ”เบเปเบžเบฑเบเป€เบเบ”เบ™เบตเป‰. เบˆเบฒเบเบ„เบงเบฒเบกเบ™เบดเบเบปเบกเบซเบผเบฒเบเบ‚เบถเป‰เบ™ RcppParallel เบŠเบธเบ”, เปƒเบ™เบšเบฑเบ™เบ”เบฒเบชเบดเปˆเบ‡เบญเบทเปˆเบ™เป†, เบกเบตเบเบปเบ™เป„เบเบเบฒเบ™เบ‚เบฑเบ”เบ‚เบงเบฒเบ‡ loop เบเปเปˆเบชเป‰เบฒเบ‡เปƒเบ™.

เบกเบฑเบ™เบ„เบงเบ™เบˆเบฐเป„เบ”เป‰เบฎเบฑเบšเบเบปเบเปƒเบซเป‰เป€เบซเบฑเบ™เบงเปˆเบฒ xtensor เบเบฒเบเป€เบ›เบฑเบ™ godsend: เบ™เบญเบเป€เบซเบ™เบทเบญเป„เบ›เบˆเบฒเบเบ„เบงเบฒเบกเบˆเบดเบ‡เบ—เบตเปˆเบงเปˆเบฒเบกเบฑเบ™เบกเบตเบซเบ™เป‰เบฒเบ—เบตเปˆเบเบงเป‰เบฒเบ‡เบ‚เบงเบฒเบ‡เปเบฅเบฐเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบชเบนเบ‡, เบ™เบฑเบเบžเบฑเบ”เบ—เบฐเบ™เบฒเบ‚เบญเบ‡เบกเบฑเบ™เป„เบ”เป‰เบเบฒเบเป€เบ›เบฑเบ™เบ—เบตเปˆเบ‚เป‰เบญเบ™เบ‚เป‰เบฒเบ‡เบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เปเบฅเบฐเบ•เบญเบšเบ„เปเบฒเบ–เบฒเบกเบ—เบฑเบ™เบ—เบตเปเบฅเบฐเบฅเบฒเบเบฅเบฐเบญเบฝเบ”. เบ”เป‰เบงเบเบเบฒเบ™เบŠเปˆเบงเบเป€เบซเบผเบทเบญเบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒ, เบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เบ—เบตเปˆเบˆเบฐเบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบซเบฑเบ™เบ›เปˆเบฝเบ™เบ‚เบญเบ‡ OpenCV matrices เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ xtensor tensors, เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบงเบดเบ—เบตเบเบฒเบ™เบชเบปเบกเบ—เบปเบš tensor เบฎเบนเบšเบžเบฒเบš 3 เบกเบดเบ•เบดเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ tensor 4 เบกเบดเบ•เบดเบ‚เบญเบ‡เบกเบดเบ•เบดเบ—เบตเปˆเบ–เบทเบเบ•เป‰เบญเบ‡ (batch เบ•เบปเบงเบ‚เบญเบ‡เบกเบฑเบ™เป€เบญเบ‡).

เบงเบฑเบ”เบชเบฐเบ”เบธเบชเบณเบฅเบฑเบšเบเบฒเบ™เบฎเบฝเบ™เบฎเบนเป‰ Rcpp, xtensor เปเบฅเบฐ RcppThread

https://thecoatlessprofessor.com/programming/unofficial-rcpp-api-documentation

https://docs.opencv.org/4.0.1/d7/dbd/group__imgproc.html

https://xtensor.readthedocs.io/en/latest/

https://xtensor.readthedocs.io/en/latest/file_loading.html#loading-json-data-into-xtensor

https://cran.r-project.org/web/packages/RcppThread/vignettes/RcppThread-vignette.pdf

เป€เบžเบทเปˆเบญเบฅเบงเบšเบฅเบงเบกเป„เบŸเบฅเปŒเบ—เบตเปˆเปƒเบŠเป‰เป„เบŸเบฅเปŒเบฅเบฐเบšเบปเบšเปเบฅเบฐเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเป‚เบเบ‡เปเบšเบšเป€เบ„เบทเปˆเบญเบ™เป„เบซเบงเบเบฑเบšเบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ”เบ—เบตเปˆเบ•เบดเบ”เบ•เบฑเป‰เบ‡เบขเบนเปˆเปƒเบ™เบฅเบฐเบšเบปเบš, เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ™เปเบฒเปƒเบŠเป‰เบเบปเบ™เป„เบ plugin เบ—เบตเปˆเบ›เบฐเบ•เบดเบšเบฑเบ”เบขเบนเปˆเปƒเบ™เบŠเบธเบ”. Rcpp. เป€เบžเบทเปˆเบญเบŠเบญเบเบซเบฒเป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡ เปเบฅเบฐเบ—เบธเบ‡เป‚เบ”เบเบญเบฑเบ”เบ•เบฐเป‚เบ™เบกเบฑเบ”, เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เปƒเบŠเป‰เป€เบ„เบทเปˆเบญเบ‡เปƒเบŠเป‰ Linux เบ—เบตเปˆเป€เบ›เบฑเบ™เบ—เบตเปˆเบ™เบดเบเบปเบก pkg-config.

เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‚เบญเบ‡ plugin Rcpp เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ” OpenCV

Rcpp::registerPlugin("opencv", function() {
  # ะ’ะพะทะผะพะถะฝั‹ะต ะฝะฐะทะฒะฐะฝะธั ะฟะฐะบะตั‚ะฐ
  pkg_config_name <- c("opencv", "opencv4")
  # ะ‘ะธะฝะฐั€ะฝั‹ะน ั„ะฐะนะป ัƒั‚ะธะปะธั‚ั‹ pkg-config
  pkg_config_bin <- Sys.which("pkg-config")
  # ะŸั€ะพะฒั€ะตะบะฐ ะฝะฐะปะธั‡ะธั ัƒั‚ะธะปะธั‚ั‹ ะฒ ัะธัั‚ะตะผะต
  checkmate::assert_file_exists(pkg_config_bin, access = "x")
  # ะŸั€ะพะฒะตั€ะบะฐ ะฝะฐะปะธั‡ะธั ั„ะฐะนะปะฐ ะฝะฐัั‚ั€ะพะตะบ OpenCV ะดะปั pkg-config
  check <- sapply(pkg_config_name, 
                  function(pkg) system(paste(pkg_config_bin, pkg)))
  if (all(check != 0)) {
    stop("OpenCV config for the pkg-config not found", call. = FALSE)
  }

  pkg_config_name <- pkg_config_name[check == 0]
  list(env = list(
    PKG_CXXFLAGS = system(paste(pkg_config_bin, "--cflags", pkg_config_name), 
                          intern = TRUE),
    PKG_LIBS = system(paste(pkg_config_bin, "--libs", pkg_config_name), 
                      intern = TRUE)
  ))
})

เป€เบ›เบฑเบ™เบœเบปเบ™เบกเบฒเบˆเบฒเบเบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบ‡เบฒเบ™เบ‚เบญเบ‡ plugin, เบ„เปˆเบฒเบ•เปเปˆเป„เบ›เบ™เบตเป‰เบˆเบฐเบ–เบทเบเบ—เบปเบ”เปเบ—เบ™เปƒเบ™เบฅเบฐเบซเบงเปˆเบฒเบ‡เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบฅเบงเบšเบฅเบงเบก:

Rcpp:::.plugins$opencv()$env

# $PKG_CXXFLAGS
# [1] "-I/usr/include/opencv"
#
# $PKG_LIBS
# [1] "-lopencv_shape -lopencv_stitching -lopencv_superres -lopencv_videostab -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_datasets -lopencv_dpm -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hdf -lopencv_line_descriptor -lopencv_optflow -lopencv_video -lopencv_plot -lopencv_reg -lopencv_saliency -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_rgbd -lopencv_viz -lopencv_surface_matching -lopencv_text -lopencv_ximgproc -lopencv_calib3d -lopencv_features2d -lopencv_flann -lopencv_xobjdetect -lopencv_objdetect -lopencv_ml -lopencv_xphoto -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_photo -lopencv_imgproc -lopencv_core"

เบฅเบฐโ€‹เบซเบฑเบ”โ€‹เบเบฒเบ™โ€‹เบ›เบฐโ€‹เบ•เบดโ€‹เบšเบฑเบ”โ€‹เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เปเบเบ JSON เปเบฅเบฐโ€‹เบเบฒเบ™โ€‹เบชเป‰เบฒเบ‡ batch เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เบชเบปเปˆเบ‡โ€‹เบเบฑเบšโ€‹เบฎเบนเบšโ€‹เปเบšเบšโ€‹เปเบกเปˆเบ™โ€‹เป„เบ”เป‰โ€‹เบฎเบฑเบšโ€‹เปƒเบซเป‰โ€‹เบžเบฒเบโ€‹เปƒเบ•เป‰ spoiler เป„เบ”เป‰โ€‹. เบ—เปเบฒเบญเบดเบ”, เป€เบžเบตเปˆเบกเบšเบฑเบ™เบŠเบตเป‚เบ„เบ‡เบเบฒเบ™เบ—เป‰เบญเบ‡เบ–เบดเปˆเบ™เป€เบžเบทเปˆเบญเบŠเบญเบเบซเบฒเป„เบŸเบฅเปŒ header (เบ•เป‰เบญเบ‡เบเบฒเบ™เบชเปเบฒเบฅเบฑเบš ndjson):

Sys.setenv("PKG_CXXFLAGS" = paste0("-I", normalizePath(file.path("src"))))

เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ” JSON เปƒเบ™เบเบฒเบ™เปเบ›เบ‡ tensor เปƒเบ™ C++

// [[Rcpp::plugins(cpp14)]]
// [[Rcpp::plugins(opencv)]]
// [[Rcpp::depends(xtensor)]]
// [[Rcpp::depends(RcppThread)]]

#include <xtensor/xjson.hpp>
#include <xtensor/xadapt.hpp>
#include <xtensor/xview.hpp>
#include <xtensor-r/rtensor.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <Rcpp.h>
#include <RcppThread.h>

// ะกะธะฝะพะฝะธะผั‹ ะดะปั ั‚ะธะฟะพะฒ
using RcppThread::parallelFor;
using json = nlohmann::json;
using points = xt::xtensor<double,2>;     // ะ˜ะทะฒะปะตั‡ั‘ะฝะฝั‹ะต ะธะท JSON ะบะพะพั€ะดะธะฝะฐั‚ั‹ ั‚ะพั‡ะตะบ
using strokes = std::vector<points>;      // ะ˜ะทะฒะปะตั‡ั‘ะฝะฝั‹ะต ะธะท JSON ะบะพะพั€ะดะธะฝะฐั‚ั‹ ั‚ะพั‡ะตะบ
using xtensor3d = xt::xtensor<double, 3>; // ะขะตะฝะทะพั€ ะดะปั ั…ั€ะฐะฝะตะฝะธั ะผะฐั‚ั€ะธั†ั‹ ะธะทะพะพะฑั€ะฐะถะตะฝะธั
using xtensor4d = xt::xtensor<double, 4>; // ะขะตะฝะทะพั€ ะดะปั ั…ั€ะฐะฝะตะฝะธั ะผะฝะพะถะตัั‚ะฒะฐ ะธะทะพะฑั€ะฐะถะตะฝะธะน
using rtensor3d = xt::rtensor<double, 3>; // ะžะฑั‘ั€ั‚ะบะฐ ะดะปั ัะบัะฟะพั€ั‚ะฐ ะฒ R
using rtensor4d = xt::rtensor<double, 4>; // ะžะฑั‘ั€ั‚ะบะฐ ะดะปั ัะบัะฟะพั€ั‚ะฐ ะฒ R

// ะกั‚ะฐั‚ะธั‡ะตัะบะธะต ะบะพะฝัั‚ะฐะฝั‚ั‹
// ะ ะฐะทะผะตั€ ะธะทะพะฑั€ะฐะถะตะฝะธั ะฒ ะฟะธะบัะตะปัั…
const static int SIZE = 256;
// ะขะธะฟ ะปะธะฝะธะธ
// ะกะผ. https://en.wikipedia.org/wiki/Pixel_connectivity#2-dimensional
const static int LINE_TYPE = cv::LINE_4;
// ะขะพะปั‰ะธะฝะฐ ะปะธะฝะธะธ ะฒ ะฟะธะบัะตะปัั…
const static int LINE_WIDTH = 3;
// ะะปะณะพั€ะธั‚ะผ ั€ะตัะฐะนะทะฐ
// https://docs.opencv.org/3.1.0/da/d54/group__imgproc__transform.html#ga5bb5a1fea74ea38e1a5445ca803ff121
const static int RESIZE_TYPE = cv::INTER_LINEAR;

// ะจะฐะฑะปะพะฝ ะดะปั ะบะพะฝะฒะตั€ั‚ะธั€ะพะฒะฐะฝะธั OpenCV-ะผะฐั‚ั€ะธั†ั‹ ะฒ ั‚ะตะฝะทะพั€
template <typename T, int NCH, typename XT=xt::xtensor<T,3,xt::layout_type::column_major>>
XT to_xt(const cv::Mat_<cv::Vec<T, NCH>>& src) {
  // ะ ะฐะทะผะตั€ะฝะพัั‚ัŒ ั†ะตะปะตะฒะพะณะพ ั‚ะตะฝะทะพั€ะฐ
  std::vector<int> shape = {src.rows, src.cols, NCH};
  // ะžะฑั‰ะตะต ะบะพะปะธั‡ะตัั‚ะฒะพ ัะปะตะผะตะฝั‚ะพะฒ ะฒ ะผะฐััะธะฒะต
  size_t size = src.total() * NCH;
  // ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต cv::Mat ะฒ xt::xtensor
  XT res = xt::adapt((T*) src.data, size, xt::no_ownership(), shape);
  return res;
}

// ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต JSON ะฒ ัะฟะธัะพะบ ะบะพะพั€ะดะธะฝะฐั‚ ั‚ะพั‡ะตะบ
strokes parse_json(const std::string& x) {
  auto j = json::parse(x);
  // ะ ะตะทัƒะปัŒั‚ะฐั‚ ะฟะฐั€ัะธะฝะณะฐ ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ ะผะฐััะธะฒะพะผ
  if (!j.is_array()) {
    throw std::runtime_error("'x' must be JSON array.");
  }
  strokes res;
  res.reserve(j.size());
  for (const auto& a: j) {
    // ะšะฐะถะดั‹ะน ัะปะตะผะตะฝั‚ ะผะฐััะธะฒะฐ ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ 2-ะผะตั€ะฝั‹ะผ ะผะฐััะธะฒะพะผ
    if (!a.is_array() || a.size() != 2) {
      throw std::runtime_error("'x' must include only 2d arrays.");
    }
    // ะ˜ะทะฒะปะตั‡ะตะฝะธะต ะฒะตะบั‚ะพั€ะฐ ั‚ะพั‡ะตะบ
    auto p = a.get<points>();
    res.push_back(p);
  }
  return res;
}

// ะžั‚ั€ะธัะพะฒะบะฐ ะปะธะฝะธะน
// ะฆะฒะตั‚ะฐ HSV
cv::Mat ocv_draw_lines(const strokes& x, bool color = true) {
  // ะ˜ัั…ะพะดะฝั‹ะน ั‚ะธะฟ ะผะฐั‚ั€ะธั†ั‹
  auto stype = color ? CV_8UC3 : CV_8UC1;
  // ะ˜ั‚ะพะณะพะฒั‹ะน ั‚ะธะฟ ะผะฐั‚ั€ะธั†ั‹
  auto dtype = color ? CV_32FC3 : CV_32FC1;
  auto bg = color ? cv::Scalar(0, 0, 255) : cv::Scalar(255);
  auto col = color ? cv::Scalar(0, 255, 220) : cv::Scalar(0);
  cv::Mat img = cv::Mat(SIZE, SIZE, stype, bg);
  // ะšะพะปะธั‡ะตัั‚ะฒะพ ะปะธะฝะธะน
  size_t n = x.size();
  for (const auto& s: x) {
    // ะšะพะปะธั‡ะตัั‚ะฒะพ ั‚ะพั‡ะตะบ ะฒ ะปะธะฝะธะธ
    size_t n_points = s.shape()[1];
    for (size_t i = 0; i < n_points - 1; ++i) {
      // ะขะพั‡ะบะฐ ะฝะฐั‡ะฐะปะฐ ัˆั‚ั€ะธั…ะฐ
      cv::Point from(s(0, i), s(1, i));
      // ะขะพั‡ะบะฐ ะพะบะพะฝั‡ะฐะฝะธั ัˆั‚ั€ะธั…ะฐ
      cv::Point to(s(0, i + 1), s(1, i + 1));
      // ะžั‚ั€ะธัะพะฒะบะฐ ะปะธะฝะธะธ
      cv::line(img, from, to, col, LINE_WIDTH, LINE_TYPE);
    }
    if (color) {
      // ะœะตะฝัะตะผ ั†ะฒะตั‚ ะปะธะฝะธะธ
      col[0] += 180 / n;
    }
  }
  if (color) {
    // ะœะตะฝัะตะผ ั†ะฒะตั‚ะพะฒะพะต ะฟั€ะตะดัั‚ะฐะฒะปะตะฝะธะต ะฝะฐ RGB
    cv::cvtColor(img, img, cv::COLOR_HSV2RGB);
  }
  // ะœะตะฝัะตะผ ั„ะพั€ะผะฐั‚ ะฟั€ะตะดัั‚ะฐะฒะปะตะฝะธั ะฝะฐ float32 ั ะดะธะฐะฟะฐะทะพะฝะพะผ [0, 1]
  img.convertTo(img, dtype, 1 / 255.0);
  return img;
}

// ะžะฑั€ะฐะฑะพั‚ะบะฐ JSON ะธ ะฟะพะปัƒั‡ะตะฝะธะต ั‚ะตะฝะทะพั€ะฐ ั ะดะฐะฝะฝั‹ะผะธ ะธะทะพะฑั€ะฐะถะตะฝะธั
xtensor3d process(const std::string& x, double scale = 1.0, bool color = true) {
  auto p = parse_json(x);
  auto img = ocv_draw_lines(p, color);
  if (scale != 1) {
    cv::Mat out;
    cv::resize(img, out, cv::Size(), scale, scale, RESIZE_TYPE);
    cv::swap(img, out);
    out.release();
  }
  xtensor3d arr = color ? to_xt<double,3>(img) : to_xt<double,1>(img);
  return arr;
}

// [[Rcpp::export]]
rtensor3d cpp_process_json_str(const std::string& x, 
                               double scale = 1.0, 
                               bool color = true) {
  xtensor3d res = process(x, scale, color);
  return res;
}

// [[Rcpp::export]]
rtensor4d cpp_process_json_vector(const std::vector<std::string>& x, 
                                  double scale = 1.0, 
                                  bool color = false) {
  size_t n = x.size();
  size_t dim = floor(SIZE * scale);
  size_t channels = color ? 3 : 1;
  xtensor4d res({n, dim, dim, channels});
  parallelFor(0, n, [&x, &res, scale, color](int i) {
    xtensor3d tmp = process(x[i], scale, color);
    auto view = xt::view(res, i, xt::all(), xt::all(), xt::all());
    view = tmp;
  });
  return res;
}

เบฅเบฐเบซเบฑเบ”เบ™เบตเป‰เบ„เบงเบ™เบˆเบฐเบ–เบทเบเบงเบฒเบ‡เป„เบงเป‰เปƒเบ™เป„เบŸเบฅเปŒ src/cv_xt.cpp เปเบฅเบฐเบฅเบงเบšเบฅเบงเบกเบเบฑเบšเบ„เปเบฒเบชเบฑเปˆเบ‡ Rcpp::sourceCpp(file = "src/cv_xt.cpp", env = .GlobalEnv); เบเบฑเบ‡เบ•เป‰เบญเบ‡เบเบฒเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบ nlohmann/json.hpp เบˆเบฒเบเบ™เบฑเป‰เบ™ เบ„เบฑเบ‡เป€เบเบฑเบšเบกเป‰เบฝเบ™. เบฅเบฐเบซเบฑเบ”เบ–เบทเบเปเบšเปˆเบ‡เบญเบญเบเป€เบ›เบฑเบ™เบซเบผเบฒเบเบซเบ™เป‰เบฒเบ—เบตเปˆ:

  • to_xt - เบซเบ™เป‰เบฒโ€‹เบ—เบตเปˆโ€‹เปเบกเปˆโ€‹เปเบšเบšโ€‹เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เบซเบฑเบ™โ€‹เบฎเบนเบšโ€‹เบžเบฒเบš matrix (cv::Mat) เบเบฑเบš tensor เป€เบ›เบฑเบ™ xt::xtensor;

  • parse_json โ€” เบŸเบฑเบ‡เบŠเบฑเบ™ parses a JSON string, เบชเบฐเบเบฑเบ”เบˆเบธเบ”เบ›เบฐเบชเบฒเบ™เบ‡เบฒเบ™เบ‚เบญเบ‡เบˆเบธเบ”, packing เปƒเบซเป‰เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ vector;

  • ocv_draw_lines - เบˆเบฒเบ vector เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเบ‚เบญเบ‡เบˆเบธเบ”, draws เบชเบฒเบเบซเบผเบฒเบเบชเบต;

  • process โ€” เบฅเบงเบกโ€‹เบซเบ™เป‰เบฒโ€‹เบ—เบตเปˆโ€‹เบ‚เป‰เบฒเบ‡โ€‹เป€เบ—เบดเบ‡โ€‹เบ™เบตเป‰โ€‹เปเบฅเบฐโ€‹เบเบฑเบ‡โ€‹เป€เบžเบตเปˆเบกโ€‹เบ„เบงเบฒเบกโ€‹เบชเบฒโ€‹เบกเบฒเบ”โ€‹เปƒเบ™โ€‹เบ‚เบฐโ€‹เบซเบ™เบฒเบ”โ€‹เบฎเบนเบšโ€‹เบžเบฒเบšโ€‹เบ—เบตเปˆโ€‹เป„เบ”เป‰โ€‹เบฎเบฑเบšโ€‹;

  • cpp_process_json_str - wrapper เปƒเบ™เป„เบฅเบเบฐเบเบฒเบ™เบ—เปเบฒเบ‡เบฒเบ™ process, เป€เบŠเบดเปˆเบ‡เบชเบปเปˆเบ‡เบญเบญเบเบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเป„เบ›เบซเบฒ R-object (เบญเบฒเป€เบฃ multidimensional);

  • cpp_process_json_vector - wrapper เปƒเบ™เป„เบฅเบเบฐเบเบฒเบ™เบ—เปเบฒเบ‡เบฒเบ™ cpp_process_json_str, เป€เบŠเบดเปˆเบ‡เบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ›เบฐเบกเบงเบ™เบœเบปเบ™ vector string เปƒเบ™เบฎเบนเบšเปเบšเบšเบซเบผเบฒเบ threaded.

เป€เบžเบทเปˆเบญเปเบ•เป‰เบกเป€เบชเบฑเป‰เบ™เบซเบผเบฒเบเบชเบต, เบฎเบนเบšเปเบšเบšเบชเบต HSV เป„เบ”เป‰เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰, เบ›เบฐเบ•เบดเบšเบฑเบ”เบ•เบฒเบกเป‚เบ”เบเบเบฒเบ™เบ›เปˆเบฝเบ™เป€เบ›เบฑเบ™ RGB. เบ‚เปโ€‹เปƒเบซเป‰โ€‹เบ—เบปเบ”โ€‹เบชเบญเบšโ€‹เบœเบปเบ™โ€‹เป„เบ”เป‰โ€‹เบฎเบฑเบšโ€‹:

arr <- cpp_process_json_str(tmp_data[4, drawing])
dim(arr)
# [1] 256 256   3
plot(magick::image_read(arr))

เบเบฒเบ™เบฎเบฑเบšเบฎเบนเป‰ Doodle เปเบ•เป‰เบกเบ”เปˆเบงเบ™: เบงเบดเบ—เบตเบเบฒเบ™เบชเป‰เบฒเบ‡เป€เบžเบทเปˆเบญเบ™เบเบฑเบš R, C++ เปเบฅเบฐเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural
เบเบฒเบ™เบ›เบฝเบšเบ—เบฝเบšเบ„เบงเบฒเบกเป„เบงเบ‚เบญเบ‡เบเบฒเบ™เบˆเบฑเบ”เบ•เบฑเป‰เบ‡เบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™ R เปเบฅเบฐ C++

res_bench <- bench::mark(
  r_process_json_str(tmp_data[4, drawing], scale = 0.5),
  cpp_process_json_str(tmp_data[4, drawing], scale = 0.5),
  check = FALSE,
  min_iterations = 100
)
# ะŸะฐั€ะฐะผะตั‚ั€ั‹ ะฑะตะฝั‡ะผะฐั€ะบะฐ
cols <- c("expression", "min", "median", "max", "itr/sec", "total_time", "n_itr")
res_bench[, cols]

#   expression                min     median       max `itr/sec` total_time  n_itr
#   <chr>                <bch:tm>   <bch:tm>  <bch:tm>     <dbl>   <bch:tm>  <int>
# 1 r_process_json_str     3.49ms     3.55ms    4.47ms      273.      490ms    134
# 2 cpp_process_json_str   1.94ms     2.02ms    5.32ms      489.      497ms    243

library(ggplot2)
# ะŸั€ะพะฒะตะดะตะฝะธะต ะทะฐะผะตั€ะฐ
res_bench <- bench::press(
  batch_size = 2^(4:10),
  {
    .data <- tmp_data[sample(seq_len(.N), batch_size), drawing]
    bench::mark(
      r_process_json_vector(.data, scale = 0.5),
      cpp_process_json_vector(.data,  scale = 0.5),
      min_iterations = 50,
      check = FALSE
    )
  }
)

res_bench[, cols]

#    expression   batch_size      min   median      max `itr/sec` total_time n_itr
#    <chr>             <dbl> <bch:tm> <bch:tm> <bch:tm>     <dbl>   <bch:tm> <int>
#  1 r                   16   50.61ms  53.34ms  54.82ms    19.1     471.13ms     9
#  2 cpp                 16    4.46ms   5.39ms   7.78ms   192.      474.09ms    91
#  3 r                   32   105.7ms 109.74ms 212.26ms     7.69        6.5s    50
#  4 cpp                 32    7.76ms  10.97ms  15.23ms    95.6     522.78ms    50
#  5 r                   64  211.41ms 226.18ms 332.65ms     3.85      12.99s    50
#  6 cpp                 64   25.09ms  27.34ms  32.04ms    36.0        1.39s    50
#  7 r                  128   534.5ms 627.92ms 659.08ms     1.61      31.03s    50
#  8 cpp                128   56.37ms  58.46ms  66.03ms    16.9        2.95s    50
#  9 r                  256     1.15s    1.18s    1.29s     0.851     58.78s    50
# 10 cpp                256  114.97ms 117.39ms 130.09ms     8.45       5.92s    50
# 11 r                  512     2.09s    2.15s    2.32s     0.463       1.8m    50
# 12 cpp                512  230.81ms  235.6ms 261.99ms     4.18      11.97s    50
# 13 r                 1024        4s    4.22s     4.4s     0.238       3.5m    50
# 14 cpp               1024  410.48ms 431.43ms 462.44ms     2.33      21.45s    50

ggplot(res_bench, aes(x = factor(batch_size), y = median, 
                      group =  expression, color = expression)) +
  geom_point() +
  geom_line() +
  ylab("median time, s") +
  theme_minimal() +
  scale_color_discrete(name = "", labels = c("cpp", "r")) +
  theme(legend.position = "bottom") 

เบเบฒเบ™เบฎเบฑเบšเบฎเบนเป‰ Doodle เปเบ•เป‰เบกเบ”เปˆเบงเบ™: เบงเบดเบ—เบตเบเบฒเบ™เบชเป‰เบฒเบ‡เป€เบžเบทเปˆเบญเบ™เบเบฑเบš R, C++ เปเบฅเบฐเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural

เบ”เบฑเปˆเบ‡เบ—เบตเปˆเป€เบˆเบปเป‰เบฒเบชเบฒเบกเบฒเบ”เป€เบซเบฑเบ™เป„เบ”เป‰, เบเบฒเบ™เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเป„เบงเป„เบ”เป‰เบเบฒเบเป€เบ›เบฑเบ™เบชเบดเปˆเบ‡เบชเปเบฒเบ„เบฑเบ™เบซเบผเบฒเบ, เปเบฅเบฐเบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เบšเปเปˆเป„เบ”เป‰เบ—เบตเปˆเบˆเบฐเบˆเบฑเบšเบฅเบฐเบซเบฑเบ” C ++ เป‚เบ”เบเบเบฒเบ™เบ‚เบฐเบซเบ™เบฒเบ™เบฅเบฐเบซเบฑเบ” R.

3. Iterators เบชเปเบฒเบฅเบฑเบš unloading batches เบˆเบฒเบเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™

R เบกเบตเบŠเบทเปˆเบชเบฝเบ‡เบ—เบตเปˆเบชเบปเบกเบ„เบงเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเป€เบซเบกเบฒเบฐเบเบฑเบš RAM, เปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆ Python เบกเบตเบฅเบฑเบเบชเบฐเบ™เบฐเป€เบžเบตเปˆเบกเป€เบ•เบตเบกเป‚เบ”เบเบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เปเป‰เบกเบนเบ™เปเบšเบšเบŠเปเป‰เบฒเป†, เบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆเบ™เบญเบเบซเบผเบฑเบ (เบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆเป‚เบ”เบเปƒเบŠเป‰เบซเบ™เปˆเบงเบเบ„เบงเบฒเบกเบˆเปเบฒเบžเบฒเบเบ™เบญเบ). เบ•เบปเบงเบขเปˆเบฒเบ‡เบ„เบฅเบฒเบชเบชเบดเบเปเบฅเบฐเบ—เบตเปˆเบเปˆเบฝเบงเบ‚เป‰เบญเบ‡เบชเปเบฒเบฅเบฑเบšเบžเบงเบเป€เบฎเบปเบฒเปƒเบ™เบชเบฐเบžเบฒเบšเบเบฒเบ™เบ‚เบญเบ‡เบšเบฑเบ™เบซเบฒเบ—เบตเปˆเบญเบฐเบ—เบดเบšเบฒเบเป„เบงเป‰เปเบกเปˆเบ™เป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural เป€เบฅเบดเบเบ—เบตเปˆเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเป‚เบ”เบเบงเบดเบ—เบตเบเบฒเบ™ gradient descent เป‚เบ”เบเบ›เบฐเบกเบฒเบ™เบ‚เบญเบ‡ gradient เปƒเบ™เปเบ•เปˆเบฅเบฐเบ‚เบฑเป‰เบ™เบ•เบญเบ™เป‚เบ”เบเปƒเบŠเป‰เบชเปˆเบงเบ™เบ™เป‰เบญเบเป†เบ‚เบญเบ‡เบเบฒเบ™เบชเบฑเบ‡เป€เบเบ”เบเบฒเบ™, เบซเบผเบท mini-batch.

เบเบญเบšเบเบฒเบ™เบฎเบฝเบ™เบฎเบนเป‰เป€เบฅเบดเบเบ—เบตเปˆเบ‚เบฝเบ™เปƒเบ™ Python เบกเบตเบซเป‰เบญเบ‡เบฎเบฝเบ™เบžเบดเป€เบชเบ”เบ—เบตเปˆเบ›เบฐเบ•เบดเบšเบฑเบ” iterators เป‚เบ”เบเบญเบตเบ‡เปƒเบชเปˆเบ‚เปเป‰เบกเบนเบ™: เบ•เบฒเบ•เบฐเบฅเบฒเบ‡, เบฎเบนเบšเบžเบฒเบšเปƒเบ™เป‚เบŸเบ™เป€เบ”เบต, เบฎเบนเบšเปเบšเบšเบ–เบฒเบ™เบชเบญเบ‡, เปเบฅเบฐเบญเบทเปˆเบ™เป†. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ™เปเบฒเปƒเบŠเป‰เบ—เบฒเบ‡เป€เบฅเบทเบญเบเบ—เบตเปˆเบเบฝเบกเบžเป‰เบญเบกเบซเบผเบทเบ‚เบฝเบ™เบ‚เบญเบ‡เบ—เปˆเบฒเบ™เป€เบญเบ‡เบชเปเบฒเบฅเบฑเบšเบงเบฝเบเบ‡เบฒเบ™เบชเบฐเป€เบžเบฒเบฐ. เปƒเบ™ R เบžเบงเบเป€เบฎเบปเบฒเบชเบฒเบกเบฒเบ”เปƒเบŠเป‰เบ›เบฐเป‚เบซเบเบ”เบˆเบฒเบเบฅเบฑเบเบชเบฐเบ™เบฐเบ—เบฑเบ‡เบซเบกเบปเบ”เบ‚เบญเบ‡เบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ” Python keras เบเบฑเบš backends เบ•เปˆเบฒเบ‡เป†เบ‚เบญเบ‡เบกเบฑเบ™เป‚เบ”เบเปƒเบŠเป‰เบŠเบธเบ”เบ‚เบญเบ‡เบŠเบทเปˆเบ”เบฝเบงเบเบฑเบ™, เป€เบŠเบดเปˆเบ‡เปƒเบ™เบ™เบฑเป‰เบ™เป€เบฎเบฑเบ”เบงเบฝเบเบขเบนเปˆเป€เบ—เบดเบ‡เบชเบธเบ”เบ‚เบญเบ‡เบŠเบธเบ” reticulate. เบชเบธเบ”เบ—เป‰เบฒเบเบชเบปเบกเบ„เบงเบ™เป„เบ”เป‰เบฎเบฑเบšเบšเบปเบ”เบ„เบงเบฒเบกเบเบฒเบงเปเบเบเบ•เปˆเบฒเบ‡เบซเบฒเบ; เบกเบฑเบ™เบšเปเปˆเบžเบฝเบ‡เปเบ•เปˆเบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบญเบตเป‰เบ™เปƒเบŠเป‰เบฅเบฐเบซเบฑเบ” Python เบˆเบฒเบ R, เปเบ•เปˆเบเบฑเบ‡เบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป‚เบญเบ™เบงเบฑเบ”เบ–เบธเบฅเบฐเบซเบงเปˆเบฒเบ‡ R เปเบฅเบฐ Python sessions, เบญเบฑเบ”เบ•เบฐเป‚เบ™เบกเบฑเบ”เบเบฒเบ™เปเบ›เบ‡เบ›เบฐเป€เบžเบ”เบ—เบตเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”.

เบžเบงเบเป€เบฎเบปเบฒเบเปเบฒเบˆเบฑเบ”เบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™เบ—เบตเปˆเบˆเบฐเป€เบเบฑเบšเบฎเบฑเบเบชเบฒเบ‚เปเป‰เบกเบนเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”เปƒเบ™ RAM เป‚เบ”เบเปƒเบŠเป‰ MonetDBLite, เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบ "เป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural" เบ—เบฑเบ‡เบซเบกเบปเบ”เบˆเบฐเบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เป‚เบ”เบเบฅเบฐเบซเบฑเบ”เบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบšเปƒเบ™ Python, เบžเบงเบเป€เบฎเบปเบฒเบžเบฝเบ‡เปเบ•เปˆเบ•เป‰เบญเบ‡เบ‚เบฝเบ™ iterator เปƒเบ™เป„เบฅเบเบฐเบ‚เปเป‰เบกเบนเบ™, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเบšเปเปˆเบกเบตเบซเบเบฑเบ‡เบžเป‰เบญเบก. เบชเปเบฒเบฅเบฑเบšเบชเบฐเบ–เบฒเบ™เบฐเบเบฒเบ™เบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเปƒเบ™ R เบซเบผเบท Python. เบกเบฑเบ™เบกเบตเบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™เบžเบฝเบ‡เปเบ•เปˆเบชเบญเบ‡เบขเปˆเบฒเบ‡เป€เบ—เบปเปˆเบฒเบ™เบฑเป‰เบ™: เบกเบฑเบ™เบ•เป‰เบญเบ‡เบเบฑเบšเบ„เบทเบ™ batches เปƒเบ™ loop เบ—เบตเปˆเบšเปเปˆเบกเบตเบ—เบตเปˆเบชเบดเป‰เบ™เบชเบธเบ”เปเบฅเบฐเบ›เบฐเบซเบเบฑเบ”เบชเบฐเบ–เบฒเบ™เบฐเบ‚เบญเบ‡เบกเบฑเบ™เบฅเบฐเบซเบงเปˆเบฒเบ‡เบเบฒเบ™เบŠเปเป‰เบฒเบ„เบทเบ™ (เบญเบฑเบ™เบชเบธเบ”เบ—เป‰เบฒเบเปƒเบ™ R เบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™เบงเบดเบ—เบตเบ—เบตเปˆเบ‡เปˆเบฒเบเบ—เบตเปˆเบชเบธเบ”เป‚เบ”เบเปƒเบŠเป‰เบเบฒเบ™เบ›เบดเบ”). เบเปˆเบญเบ™เบซเบ™เป‰เบฒเบ™เบตเป‰, เบกเบฑเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป„เบ”เป‰เบ›เปˆเบฝเบ™ R arrays เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ numpy arrays เบžเบฒเบเปƒเบ™ iterator, เปเบ•เปˆเบŠเบธเบ”เบ›เบฐเบˆเบธเบšเบฑเบ™เบ‚เบญเบ‡เบŠเบธเบ”. keras เป€เบฎเบฑเบ”เบกเบฑเบ™เป€เบญเบ‡.

เบœเบนเป‰เบเบงเบ”เบชเบญเบšเบ‚เปเป‰เบกเบนเบ™เบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบก เปเบฅเบฐเบเบฒเบ™เบเบงเบ”เบชเบญเบšเบ„เบงเบฒเบกเบ–เบทเบเบ•เป‰เบญเบ‡เป„เบ”เป‰เบญเบญเบเป€เบ›เบฑเบ™เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

Iterator เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเปเบฅเบฐเบ‚เปเป‰เบกเบนเบ™เบเบฒเบ™เบเบงเบ”เบชเบญเบš

train_generator <- function(db_connection = con,
                            samples_index,
                            num_classes = 340,
                            batch_size = 32,
                            scale = 1,
                            color = FALSE,
                            imagenet_preproc = FALSE) {
  # ะŸั€ะพะฒะตั€ะบะฐ ะฐั€ะณัƒะผะตะฝั‚ะพะฒ
  checkmate::assert_class(con, "DBIConnection")
  checkmate::assert_integerish(samples_index)
  checkmate::assert_count(num_classes)
  checkmate::assert_count(batch_size)
  checkmate::assert_number(scale, lower = 0.001, upper = 5)
  checkmate::assert_flag(color)
  checkmate::assert_flag(imagenet_preproc)

  # ะŸะตั€ะตะผะตัˆะธะฒะฐะตะผ, ั‡ั‚ะพะฑั‹ ะฑั€ะฐั‚ัŒ ะธ ัƒะดะฐะปัั‚ัŒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะฝั‹ะต ะธะฝะดะตะบัั‹ ะฑะฐั‚ั‡ะตะน ะฟะพ ะฟะพั€ัะดะบัƒ
  dt <- data.table::data.table(id = sample(samples_index))
  # ะŸั€ะพัั‚ะฐะฒะปัะตะผ ะฝะพะผะตั€ะฐ ะฑะฐั‚ั‡ะตะน
  dt[, batch := (.I - 1L) %/% batch_size + 1L]
  # ะžัั‚ะฐะฒะปัะตะผ ั‚ะพะปัŒะบะพ ะฟะพะปะฝั‹ะต ะฑะฐั‚ั‡ะธ ะธ ะธะฝะดะตะบัะธั€ัƒะตะผ
  dt <- dt[, if (.N == batch_size) .SD, keyby = batch]
  # ะฃัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ัั‡ั‘ั‚ั‡ะธะบ
  i <- 1
  # ะšะพะปะธั‡ะตัั‚ะฒะพ ะฑะฐั‚ั‡ะตะน
  max_i <- dt[, max(batch)]

  # ะŸะพะดะณะพั‚ะพะฒะบะฐ ะฒั‹ั€ะฐะถะตะฝะธั ะดะปั ะฒั‹ะณั€ัƒะทะบะธ
  sql <- sprintf(
    "PREPARE SELECT drawing, label_int FROM doodles WHERE id IN (%s)",
    paste(rep("?", batch_size), collapse = ",")
  )
  res <- DBI::dbSendQuery(con, sql)

  # ะะฝะฐะปะพะณ keras::to_categorical
  to_categorical <- function(x, num) {
    n <- length(x)
    m <- numeric(n * num)
    m[x * n + seq_len(n)] <- 1
    dim(m) <- c(n, num)
    return(m)
  }

  # ะ—ะฐะผั‹ะบะฐะฝะธะต
  function() {
    # ะะฐั‡ะธะฝะฐะตะผ ะฝะพะฒัƒัŽ ัะฟะพั…ัƒ
    if (i > max_i) {
      dt[, id := sample(id)]
      data.table::setkey(dt, batch)
      # ะกะฑั€ะฐัั‹ะฒะฐะตะผ ัั‡ั‘ั‚ั‡ะธะบ
      i <<- 1
      max_i <<- dt[, max(batch)]
    }

    # ID ะดะปั ะฒั‹ะณั€ัƒะทะบะธ ะดะฐะฝะฝั‹ั…
    batch_ind <- dt[batch == i, id]
    # ะ’ั‹ะณั€ัƒะทะบะฐ ะดะฐะฝะฝั‹ั…
    batch <- DBI::dbFetch(DBI::dbBind(res, as.list(batch_ind)), n = -1)

    # ะฃะฒะตะปะธั‡ะธะฒะฐะตะผ ัั‡ั‘ั‚ั‡ะธะบ
    i <<- i + 1

    # ะŸะฐั€ัะธะฝะณ JSON ะธ ะฟะพะดะณะพั‚ะพะฒะบะฐ ะผะฐััะธะฒะฐ
    batch_x <- cpp_process_json_vector(batch$drawing, scale = scale, color = color)
    if (imagenet_preproc) {
      # ะจะบะฐะปะธั€ะพะฒะฐะฝะธะต c ะธะฝั‚ะตั€ะฒะฐะปะฐ [0, 1] ะฝะฐ ะธะฝั‚ะตั€ะฒะฐะป [-1, 1]
      batch_x <- (batch_x - 0.5) * 2
    }

    batch_y <- to_categorical(batch$label_int, num_classes)
    result <- list(batch_x, batch_y)
    return(result)
  }
}

เบŸเบฑเบ‡เบŠเบฑเบ™เปƒเบŠเป‰เป€เบงเบฅเบฒเป€เบ›เบฑเบ™ input เบ•เบปเบงเปเบ›เบ—เบตเปˆเบกเบตเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบเบฑเบšเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™, เบˆเปเบฒเบ™เบงเบ™เบ‚เบญเบ‡เบชเบฒเบเบ—เบตเปˆเปƒเบŠเป‰, เบˆเปเบฒเบ™เบงเบ™เบ‚เบญเบ‡เบซเป‰เบญเบ‡เบฎเบฝเบ™, batch เบ‚เบฐเบซเบ™เบฒเบ”, เบ‚เบฐเบซเบ™เบฒเบ” (scale = 1 เบชเบญเบ”เบ„เป‰เบญเบ‡เบเบฑเบšเบเบฒเบ™เบชเบฐเปเบ”เบ‡เบฎเบนเบšเบžเบฒเบšเบ‚เบญเบ‡ 256x256 pixels, scale = 0.5 - 128x128 pixels), เบ•เบปเบงเบŠเบตเป‰เบšเบญเบเบชเบต (.color = FALSE เบฅเบฐเบšเบธเบเบฒเบ™เบชเบฐเปเบ”เบ‡เบœเบปเบ™เป€เบ›เบฑเบ™เบชเบตเป€เบ—เบปเบฒเป€เบกเบทเปˆเบญเปƒเบŠเป‰ color = TRUE เปเบ•เปˆเบฅเบฐเบˆเบฑเบ‡เบซเบงเบฐเบ–เบทเบเปเบ•เป‰เบกเบ”เป‰เบงเบเบชเบตเปƒเปเปˆ) เปเบฅเบฐเบ•เบปเบงเบŠเบตเป‰เบšเบญเบเบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบฅเปˆเบงเบ‡เปœเป‰เบฒเบชเบณเบฅเบฑเบšเป€เบ„เบทเบญเบ‚เปˆเบฒเบเบ—เบตเปˆเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเปƒเบ™ imagenet. เบญเบฑเบ™เบชเบธเบ”เบ—เป‰เบฒเบเปเบกเปˆเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เป€เบžเบทเปˆเบญเบ‚เบฐเบซเบ™เบฒเบ”เบ„เปˆเบฒ pixels โ€‹โ€‹เบฅเบงเบ‡เบˆเบฒเบเป„เบฅเบเบฐ [0, 1] เป„เบ›เบซเบฒเป„เบฅเบเบฐ [-1, 1], เป€เบŠเบดเปˆเบ‡เป„เบ”เป‰เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เปƒเบ™เป€เบงเบฅเบฒเบเบถเบเบญเบปเบšเบฎเบปเบกเบ—เบตเปˆเบชเบฐเบซเบ™เบญเบ‡. keras เปเบšเบš.

เบŸเบฑเบ‡เบŠเบฑเบ™เบžเบฒเบเบ™เบญเบเบ›เบฐเบเบญเบšเบ”เป‰เบงเบเบเบฒเบ™เบเบงเบ”เบชเบญเบšเบ›เบฐเป€เบžเบ”เบเบฒเบ™เป‚เบ•เป‰เบ–เบฝเบ‡, เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ data.table เบ”เป‰เบงเบเบ•เบปเบงเป€เบฅเบเป€เบชเบฑเป‰เบ™เบ›เบฐเบชเบปเบกเปเบšเบšเบชเบธเปˆเบกเบˆเบฒเบ samples_index เปเบฅเบฐเบˆเปเบฒเบ™เบงเบ™ batch, counter เปเบฅเบฐเบˆเปเบฒเบ™เบงเบ™เบชเบนเบ‡เบชเบธเบ”เบ‚เบญเบ‡ batches, เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบเบฒเบ™เบชเบฐเปเบ”เบ‡เบญเบญเบ SQL เบชเปเบฒเบฅเบฑเบš unloading เบ‚เปเป‰เบกเบนเบ™เบˆเบฒเบเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™. เบ™เบญเบเบˆเบฒเบเบ™เบฑเป‰เบ™, เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบเปเบฒเบ™เบปเบ”เบเบฒเบ™เบ›เบฝเบšเบ—เบฝเบšเป„เบงเบ‚เบญเบ‡เบซเบ™เป‰เบฒเบ—เบตเปˆเบžเบฒเบเปƒเบ™ keras::to_categorical(). เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ™เปเบฒเปƒเบŠเป‰เบ‚เปเป‰เบกเบนเบ™เป€เบเบทเบญเบšเบ—เบฑเบ‡เบซเบกเบปเบ”เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบก, เบ›เปˆเบญเบเปƒเบซเป‰เป€เบ„เบดเปˆเบ‡เบซเบ™เบถเปˆเบ‡เป€เบ›เบตเป€เบŠเบฑเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบเบงเบ”เบชเบญเบš, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ‚เบฐเบซเบ™เบฒเบ” epoch เป„เบ”เป‰เบ–เบทเบเบˆเปเบฒเบเบฑเบ”เป‚เบ”เบเบžเบฒเบฅเบฒเบกเบดเป€เบ•เบต. steps_per_epoch เป€เบกเบทเปˆเบญเป€เบญเบตเป‰เบ™ keras::fit_generator(), เปเบฅเบฐเป€เบ‡เบทเปˆเบญเบ™เป„เบ‚ if (i > max_i) เบžเบฝเบ‡เปเบ•เปˆเป€เบฎเบฑเบ”เบงเบฝเบเบชเปเบฒเบฅเบฑเบš validation iterator.

เปƒเบ™เบŸเบฑเบ‡เบŠเบฑเบ™เบžเบฒเบเปƒเบ™, เบ”เบฑเบ”เบŠเบฐเบ™เบตเปเบ–เบงเบ–เบทเบเบ”เบถเบ‡เบกเบฒเบชเปเบฒเบฅเบฑเบšเบŠเบธเบ”เบ•เปเปˆเป„เบ›, เบšเบฑเบ™เบ—เบถเบเบ–เบทเบเบเบปเบเป€เบฅเบตเบเบˆเบฒเบเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบกเบตเบเบฒเบ™เบ™เบฑเบšเบˆเปเบฒเบ™เบงเบ™เป€เบžเบตเปˆเบกเบ‚เบถเป‰เบ™, JSON parsing (function cpp_process_json_vector(), เบ‚เบฝเบ™เปƒเบ™ C ++) เปเบฅเบฐเบเบฒเบ™เบชเป‰เบฒเบ‡ array เบ—เบตเปˆเบชเบญเบ”เบ„เป‰เบญเบ‡เบเบฑเบ™เบเบฑเบšเบฎเบนเบšเบžเบฒเบš. เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™, vectors เบฎเป‰เบญเบ™เบซเบ™เบถเปˆเบ‡เบ—เบตเปˆเบกเบตเบ›เป‰เบฒเบเบŠเบฑเป‰เบ™เบ–เบทเบเบชเป‰เบฒเบ‡เบ‚เบทเป‰เบ™, arrays เบ—เบตเปˆเบกเบตเบ„เปˆเบฒ pixels โ€‹โ€‹เปเบฅเบฐ labels เบ–เบทเบเบฅเบงเบกเป€เบ‚เบปเป‰เบฒเบเบฑเบ™เปƒเบ™เบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆ, เบŠเบถเปˆเบ‡เป€เบ›เบฑเบ™เบกเบนเบ™เบ„เปˆเบฒเบเบฑเบšเบ„เบทเบ™. เป€เบžเบทเปˆเบญเป€เบฅเบฑเปˆเบ‡เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบ, เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ™เปเบฒเปƒเบŠเป‰เบเบฒเบ™เบชเป‰เบฒเบ‡เบ”เบฑเบ”เบชเบฐเบ™เบตเปƒเบ™เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ data.table เปเบฅเบฐเบเบฒเบ™เบ”เบฑเบ”เปเบเป‰เบœเปˆเบฒเบ™เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ - เป‚เบ”เบเบšเปเปˆเบกเบตเบŠเบธเบ”เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰ "chips" เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ เบกเบฑเบ™เบ‚เป‰เบญเบ™เบ‚เป‰เบฒเบ‡เบเบฒเบเบ—เบตเปˆเบˆเบฐเบˆเบดเบ™เบ•เบฐเบ™เบฒเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบขเปˆเบฒเบ‡เบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบเบฑเบšเบ‚เปเป‰เบกเบนเบ™เบˆเปเบฒเบ™เบงเบ™เบซเบผเบงเบ‡เบซเบผเบฒเบเปƒเบ™ R.

เบœเบปเบ™เบ‚เบญเบ‡เบเบฒเบ™เบงเบฑเบ”เปเบ—เบเบ„เบงเบฒเบกเป„เบงเปƒเบ™เบ„เบญเบกเบžเบดเบงเป€เบ•เบต Core i5 เบกเบตเบ”เบฑเปˆเบ‡เบ™เบตเป‰:

Iterator benchmark

library(Rcpp)
library(keras)
library(ggplot2)

source("utils/rcpp.R")
source("utils/keras_iterator.R")

con <- DBI::dbConnect(drv = MonetDBLite::MonetDBLite(), Sys.getenv("DBDIR"))

ind <- seq_len(DBI::dbGetQuery(con, "SELECT count(*) FROM doodles")[[1L]])
num_classes <- DBI::dbGetQuery(con, "SELECT max(label_int) + 1 FROM doodles")[[1L]]

# ะ˜ะฝะดะตะบัั‹ ะดะปั ะพะฑัƒั‡ะฐัŽั‰ะตะน ะฒั‹ะฑะพั€ะบะธ
train_ind <- sample(ind, floor(length(ind) * 0.995))
# ะ˜ะฝะดะตะบัั‹ ะดะปั ะฟั€ะพะฒะตั€ะพั‡ะฝะพะน ะฒั‹ะฑะพั€ะบะธ
val_ind <- ind[-train_ind]
rm(ind)
# ะšะพัั„ั„ะธั†ะธะตะฝั‚ ะผะฐััˆั‚ะฐะฑะฐ
scale <- 0.5

# ะŸั€ะพะฒะตะดะตะฝะธะต ะทะฐะผะตั€ะฐ
res_bench <- bench::press(
  batch_size = 2^(4:10),
  {
    it1 <- train_generator(
      db_connection = con,
      samples_index = train_ind,
      num_classes = num_classes,
      batch_size = batch_size,
      scale = scale
    )
    bench::mark(
      it1(),
      min_iterations = 50L
    )
  }
)
# ะŸะฐั€ะฐะผะตั‚ั€ั‹ ะฑะตะฝั‡ะผะฐั€ะบะฐ
cols <- c("batch_size", "min", "median", "max", "itr/sec", "total_time", "n_itr")
res_bench[, cols]

#   batch_size      min   median      max `itr/sec` total_time n_itr
#        <dbl> <bch:tm> <bch:tm> <bch:tm>     <dbl>   <bch:tm> <int>
# 1         16     25ms  64.36ms   92.2ms     15.9       3.09s    49
# 2         32   48.4ms 118.13ms 197.24ms     8.17       5.88s    48
# 3         64   69.3ms 117.93ms 181.14ms     8.57       5.83s    50
# 4        128  157.2ms 240.74ms 503.87ms     3.85      12.71s    49
# 5        256  359.3ms 613.52ms 988.73ms     1.54       30.5s    47
# 6        512  884.7ms    1.53s    2.07s     0.674      1.11m    45
# 7       1024     2.7s    3.83s    5.47s     0.261      2.81m    44

ggplot(res_bench, aes(x = factor(batch_size), y = median, group = 1)) +
    geom_point() +
    geom_line() +
    ylab("median time, s") +
    theme_minimal()

DBI::dbDisconnect(con, shutdown = TRUE)

เบเบฒเบ™เบฎเบฑเบšเบฎเบนเป‰ Doodle เปเบ•เป‰เบกเบ”เปˆเบงเบ™: เบงเบดเบ—เบตเบเบฒเบ™เบชเป‰เบฒเบ‡เป€เบžเบทเปˆเบญเบ™เบเบฑเบš R, C++ เปเบฅเบฐเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural

เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบกเบต RAM เบžเบฝเบ‡เบžเป, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฅเบฑเปˆเบ‡เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ‚เบญเบ‡เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เป„เบ”เป‰เบขเปˆเบฒเบ‡เบˆเบดเบ‡เบˆเบฑเบ‡เป‚เบ”เบเบเบฒเบ™เป‚เบญเบ™เบกเบฑเบ™เป„เบ›เบซเบฒ RAM เบ”เบฝเบงเบเบฑเบ™เบ™เบตเป‰ (32 GB เปเบกเปˆเบ™เบžเบฝเบ‡เบžเปเบชเปเบฒเบฅเบฑเบšเบงเบฝเบเบ‡เบฒเบ™เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ). เปƒเบ™ Linux, เบเบฒเบ™เปเบšเปˆเบ‡เบžเบฒเบ—เบดเบŠเบฑเบ™เบ–เบทเบเบ•เบดเบ”เบ•เบฑเป‰เบ‡เป‚เบ”เบเบ„เปˆเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™ /dev/shm, เบ„เบญเบšเบ„เบญเบ‡เป€เบ–เบดเบ‡เป€เบ„เบดเปˆเบ‡เบซเบ™เบถเปˆเบ‡เบ‚เบญเบ‡เบ„เบงเบฒเบกเบญเบฒเบ”เบชเบฒเบกเบฒเบ” RAM. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบ™เบฑเป‰เบ™เป€เบžเบตเปˆเบกเป€เบ•เบตเบกเป„เบ”เป‰เป‚เบ”เบเบเบฒเบ™เบ”เบฑเบ”เปเบเป‰ /etc/fstabเป€เบžเบทเปˆเบญเปƒเบซเป‰เป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบšเบฑเบ™เบ—เบถเบเป€เบŠเบฑเปˆเบ™ tmpfs /dev/shm tmpfs defaults,size=25g 0 0. เปƒเบซเป‰เปเบ™เปˆเปƒเบˆเบงเปˆเบฒ reboot เปเบฅเบฐเบเบงเบ”เป€เบšเบดเปˆเบ‡เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเป‚เบ”เบเบเบฒเบ™เปเบฅเปˆเบ™เบ„เปเบฒเบชเบฑเปˆเบ‡ df -h.

iterator เบชเปเบฒเบฅเบฑเบšเบ‚เปเป‰เบกเบนเบ™เบเบฒเบ™เบ—เบปเบ”เบชเบญเบšเป€เบšเบดเปˆเบ‡เบ‡เปˆเบฒเบเบ”เบฒเบเบซเบผเบฒเบ, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบเบฒเบ™เบ—เบปเบ”เบชเบญเบšเป€เบซเบกเบฒเบฐเบ—เบฑเบ‡เบซเบกเบปเบ”เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ RAM:

Iterator เบชเปเบฒเบฅเบฑเบšเบ‚เปเป‰เบกเบนเบ™เบเบฒเบ™เบ—เบปเบ”เบชเบญเบš

test_generator <- function(dt,
                           batch_size = 32,
                           scale = 1,
                           color = FALSE,
                           imagenet_preproc = FALSE) {

  # ะŸั€ะพะฒะตั€ะบะฐ ะฐั€ะณัƒะผะตะฝั‚ะพะฒ
  checkmate::assert_data_table(dt)
  checkmate::assert_count(batch_size)
  checkmate::assert_number(scale, lower = 0.001, upper = 5)
  checkmate::assert_flag(color)
  checkmate::assert_flag(imagenet_preproc)

  # ะŸั€ะพัั‚ะฐะฒะปัะตะผ ะฝะพะผะตั€ะฐ ะฑะฐั‚ั‡ะตะน
  dt[, batch := (.I - 1L) %/% batch_size + 1L]
  data.table::setkey(dt, batch)
  i <- 1
  max_i <- dt[, max(batch)]

  # ะ—ะฐะผั‹ะบะฐะฝะธะต
  function() {
    batch_x <- cpp_process_json_vector(dt[batch == i, drawing], 
                                       scale = scale, color = color)
    if (imagenet_preproc) {
      # ะจะบะฐะปะธั€ะพะฒะฐะฝะธะต c ะธะฝั‚ะตั€ะฒะฐะปะฐ [0, 1] ะฝะฐ ะธะฝั‚ะตั€ะฒะฐะป [-1, 1]
      batch_x <- (batch_x - 0.5) * 2
    }
    result <- list(batch_x)
    i <<- i + 1
    return(result)
  }
}

4. เบเบฒเบ™เบ„เบฑเบ”เป€เบฅเบทเบญเบเบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเปเบšเบšเบˆเปเบฒเบฅเบญเบ‡

เบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเบ—เปเบฒเบญเบดเบ”เบ—เบตเปˆเปƒเบŠเป‰เปเบกเปˆเบ™ mobilenet v1, เบฅเบฑเบเบชเบฐเบ™เบฐเบ—เบตเปˆเป„เบ”เป‰เบ–เบทเบเบ›เบถเบเบชเบฒเบซเบฒเบฅเบทเปƒเบ™ เบ™เบตเป‰ เบ‚เปเป‰เบ„เบงเบฒเบก. เบกเบฑเบ™เป„เบ”เป‰เบ–เบทเบเบฅเบงเบกเป€เบ‚เบปเป‰เบฒเป€เบ›เบฑเบ™เบกเบฒเบ”เบ•เบฐเบ–เบฒเบ™ keras เปเบฅเบฐ, เบ•เบฒเบกเบ„เบงเบฒเบกเป€เบซเบกเบฒเบฐเบชเบปเบก, เปเบกเปˆเบ™เบกเบตเบขเบนเปˆเปƒเบ™เบŠเบธเบ”เบ‚เบญเบ‡เบŠเบทเปˆเบ”เบฝเบงเบเบฑเบ™เบชเปเบฒเบฅเบฑเบš R. เปเบ•เปˆเป€เบกเบทเปˆเบญเบžเบฐเบเบฒเบเบฒเบกเปƒเบŠเป‰เบกเบฑเบ™เบเบฑเบšเบฎเบนเบšเบžเบฒเบšเบŠเปˆเบญเบ‡เบ”เบฝเบง, เบชเบดเปˆเบ‡เปเบ›เบเบ›เบฐเบซเบฅเบฒเบ”เป„เบ”เป‰เบซเบฑเบ™เบญเบญเบ: tensor เบ›เป‰เบญเบ™เบ‚เปเป‰เบกเบนเบ™เบ•เป‰เบญเบ‡เบกเบตเบ‚เบฐเบซเบ™เบฒเบ”เบชเบฐเป€เบซเบกเบต. (batch, height, width, 3), เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เบˆเปเบฒเบ™เบงเบ™เบŠเปˆเบญเบ‡เบšเปเปˆเบชเบฒเบกเบฒเบ”เบ›เปˆเบฝเบ™เปเบ›เบ‡เป„เบ”เป‰. เบšเปเปˆเบกเบตเบ‚เปเป‰ เบˆเบณ เบเบฑเบ”เบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเปƒเบ™ Python, เบชเบฐเบ™เบฑเป‰เบ™เบžเบงเบเป€เบฎเบปเบฒเบˆเบถเปˆเบ‡เบŸเป‰เบฒเบงเบ‚เบฝเบ™เบเบฒเบ™เบˆเบฑเบ”เบ•เบฑเป‰เบ‡เบ›เบฐเบ•เบดเบšเบฑเบ”เบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐ เบเบณ เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเป€เบญเบ‡, เบ›เบฐเบ•เบดเบšเบฑเบ”เบ•เบฒเบกเบšเบปเบ”เบ„เบงเบฒเบกเบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบš (เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เป€เบฅเบทเปˆเบญเบ™เบฅเบปเบ‡เปƒเบ™เบชเบฐเบšเบฑเบš keras):

เบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเบณ Mobilenet v1

library(keras)

top_3_categorical_accuracy <- custom_metric(
    name = "top_3_categorical_accuracy",
    metric_fn = function(y_true, y_pred) {
         metric_top_k_categorical_accuracy(y_true, y_pred, k = 3)
    }
)

layer_sep_conv_bn <- function(object, 
                              filters,
                              alpha = 1,
                              depth_multiplier = 1,
                              strides = c(2, 2)) {

  # NB! depth_multiplier !=  resolution multiplier
  # https://github.com/keras-team/keras/issues/10349

  layer_depthwise_conv_2d(
    object = object,
    kernel_size = c(3, 3), 
    strides = strides,
    padding = "same",
    depth_multiplier = depth_multiplier
  ) %>%
  layer_batch_normalization() %>% 
  layer_activation_relu() %>%
  layer_conv_2d(
    filters = filters * alpha,
    kernel_size = c(1, 1), 
    strides = c(1, 1)
  ) %>%
  layer_batch_normalization() %>% 
  layer_activation_relu() 
}

get_mobilenet_v1 <- function(input_shape = c(224, 224, 1),
                             num_classes = 340,
                             alpha = 1,
                             depth_multiplier = 1,
                             optimizer = optimizer_adam(lr = 0.002),
                             loss = "categorical_crossentropy",
                             metrics = c("categorical_crossentropy",
                                         top_3_categorical_accuracy)) {

  inputs <- layer_input(shape = input_shape)

  outputs <- inputs %>%
    layer_conv_2d(filters = 32, kernel_size = c(3, 3), strides = c(2, 2), padding = "same") %>%
    layer_batch_normalization() %>% 
    layer_activation_relu() %>%
    layer_sep_conv_bn(filters = 64, strides = c(1, 1)) %>%
    layer_sep_conv_bn(filters = 128, strides = c(2, 2)) %>%
    layer_sep_conv_bn(filters = 128, strides = c(1, 1)) %>%
    layer_sep_conv_bn(filters = 256, strides = c(2, 2)) %>%
    layer_sep_conv_bn(filters = 256, strides = c(1, 1)) %>%
    layer_sep_conv_bn(filters = 512, strides = c(2, 2)) %>%
    layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
    layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
    layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
    layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
    layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
    layer_sep_conv_bn(filters = 1024, strides = c(2, 2)) %>%
    layer_sep_conv_bn(filters = 1024, strides = c(1, 1)) %>%
    layer_global_average_pooling_2d() %>%
    layer_dense(units = num_classes) %>%
    layer_activation_softmax()

    model <- keras_model(
      inputs = inputs,
      outputs = outputs
    )

    model %>% compile(
      optimizer = optimizer,
      loss = loss,
      metrics = metrics
    )

    return(model)
}

เบ‚เปเป‰เป€เบชเบเบ‚เบญเบ‡เบงเบดเบ—เบตเบเบฒเบ™เบ™เบตเป‰เปเบกเปˆเบ™เป€เบซเบฑเบ™เป„เบ”เป‰เบŠเบฑเบ”เป€เบˆเบ™. เบ‚เป‰เบญเบเบ•เป‰เบญเบ‡เบเบฒเบ™เบ—เบปเบ”เบชเบญเบšเบซเบผเบฒเบเปเบšเบš, เปเบ•เปˆเปƒเบ™เบ—เบฒเบ‡เบเบปเบ‡เบเบฑเบ™เบ‚เป‰เบฒเบก, เบ‚เป‰เบญเบเบšเปเปˆเบ•เป‰เบญเบ‡เบเบฒเบ™เบ—เบตเปˆเบˆเบฐเบ‚เบฝเบ™เบ„เบทเบ™เปƒเบซเบกเปˆเปเบ•เปˆเบฅเบฐเบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเบ”เป‰เบงเบเบ•เบปเบ™เป€เบญเบ‡. เบžเบงเบเป€เบฎเบปเบฒเบเบฑเบ‡เบ‚เบฒเบ”เป‚เบญเบเบฒเบ”เบ—เบตเปˆเบˆเบฐเปƒเบŠเป‰เบ™เปเป‰เบฒเปœเบฑเบเบ‚เบญเบ‡เบ•เบปเบงเปเบšเบšเบ—เบตเปˆเป„เบ”เป‰เบเบถเบเบญเบปเบšเบฎเบปเบกเป„เบงเป‰เบฅเปˆเบงเบ‡เปœเป‰เบฒเปƒเบ™ imagenet. เบ•เบฒเบกเบ›เบปเบเบเบฐเบ•เบด, เบเบฒเบ™เบชเบถเบเบชเบฒเป€เบญเบเบฐเบชเบฒเบ™เบŠเปˆเบงเบ. เบŸเบฑเบ‡เบŠเบฑเบ™ get_config() เบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เบ—เปˆเบฒเบ™เป„เบ”เป‰เบฎเบฑเบšเบฅเบฒเบเบฅเบฐเบญเบฝเบ”เบ‚เบญเบ‡เบฎเบนเบšเปเบšเบšเปƒเบ™เบฎเบนเบšเปเบšเบšเบ—เบตเปˆเป€เบซเบกเบฒเบฐเบชเบปเบกเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ”เบฑเบ”เปเบเป‰ (base_model_conf$layers - เบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆ R เบ›เบปเบเบเบฐเบ•เบด), เปเบฅเบฐเบซเบ™เป‰เบฒเบ—เบตเปˆ from_config() เบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เปเบ›เบ‡เบ›เบตเป‰เบ™เบเบฑเบšเบงเบฑเบ”เบ–เบธเปเบšเบšเบˆเปเบฒเบฅเบญเบ‡:

base_model_conf <- get_config(base_model)
base_model_conf$layers[[1]]$config$batch_input_shape[[4]] <- 1L
base_model <- from_config(base_model_conf)

เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบกเบฑเบ™เบšเปเปˆเบเบฒเบเบ—เบตเปˆเบˆเบฐเบ‚เบฝเบ™เบซเบ™เป‰เบฒเบ—เบตเปˆเบ—เบปเปˆเบงเป†เป„เบ›เป€เบžเบทเปˆเบญเปƒเบซเป‰เป„เบ”เป‰เบชเบดเปˆเบ‡เบ—เบตเปˆเบชเบฐเบซเบ™เบญเบ‡เปƒเบซเป‰ keras เปเบšเบšเบˆเปเบฒเบฅเบญเบ‡เบ—เบตเปˆเบกเบตเบซเบผเบทเบšเปเปˆเบกเบตเบ™เป‰เปเบฒเบซเบ™เบฑเบเบ—เบตเปˆเบเบถเบเบญเบปเบšเบฎเบปเบกเบขเบนเปˆเปƒเบ™ imagenet:

เบŸเบฑเบ‡เบŠเบฑเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป‚เบซเบผเบ”เบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเบ—เบตเปˆเบเบฝเบกเบžเป‰เบญเบก

get_model <- function(name = "mobilenet_v2",
                      input_shape = NULL,
                      weights = "imagenet",
                      pooling = "avg",
                      num_classes = NULL,
                      optimizer = keras::optimizer_adam(lr = 0.002),
                      loss = "categorical_crossentropy",
                      metrics = NULL,
                      color = TRUE,
                      compile = FALSE) {
  # ะŸั€ะพะฒะตั€ะบะฐ ะฐั€ะณัƒะผะตะฝั‚ะพะฒ
  checkmate::assert_string(name)
  checkmate::assert_integerish(input_shape, lower = 1, upper = 256, len = 3)
  checkmate::assert_count(num_classes)
  checkmate::assert_flag(color)
  checkmate::assert_flag(compile)

  # ะŸะพะปัƒั‡ะฐะตะผ ะพะฑัŠะตะบั‚ ะธะท ะฟะฐะบะตั‚ะฐ keras
  model_fun <- get0(paste0("application_", name), envir = asNamespace("keras"))
  # ะŸั€ะพะฒะตั€ะบะฐ ะฝะฐะปะธั‡ะธั ะพะฑัŠะตะบั‚ะฐ ะฒ ะฟะฐะบะตั‚ะต
  if (is.null(model_fun)) {
    stop("Model ", shQuote(name), " not found.", call. = FALSE)
  }

  base_model <- model_fun(
    input_shape = input_shape,
    include_top = FALSE,
    weights = weights,
    pooling = pooling
  )

  # ะ•ัะปะธ ะธะทะพะฑั€ะฐะถะตะฝะธะต ะฝะต ั†ะฒะตั‚ะฝะพะต, ะผะตะฝัะตะผ ั€ะฐะทะผะตั€ะฝะพัั‚ัŒ ะฒั…ะพะดะฐ
  if (!color) {
    base_model_conf <- keras::get_config(base_model)
    base_model_conf$layers[[1]]$config$batch_input_shape[[4]] <- 1L
    base_model <- keras::from_config(base_model_conf)
  }

  predictions <- keras::get_layer(base_model, "global_average_pooling2d_1")$output
  predictions <- keras::layer_dense(predictions, units = num_classes, activation = "softmax")
  model <- keras::keras_model(
    inputs = base_model$input,
    outputs = predictions
  )

  if (compile) {
    keras::compile(
      object = model,
      optimizer = optimizer,
      loss = loss,
      metrics = metrics
    )
  }

  return(model)
}

เป€เบกเบทเปˆเบญเปƒเบŠเป‰เบฎเบนเบšเบžเบฒเบšเบŠเปˆเบญเบ‡เบ”เบฝเบง, เบšเปเปˆเบกเบตเบ™เปเป‰เบฒเปœเบฑเบเบ—เบตเปˆเป„เบ”เป‰เบเบถเบเป„เบงเป‰เบฅเปˆเบงเบ‡เปœเป‰เบฒ. เบ™เบตเป‰เบชเบฒเบกเบฒเบ”เปเบเป‰เป„เบ‚เป„เบ”เป‰: เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบŸเบฑเบ‡เบŠเบฑเบ™ get_weights() เป€เบญเบปเบฒเบ™เป‰เปเบฒเบซเบ™เบฑเบเบ•เบปเบงเปเบšเบšเปƒเบ™เบฎเบนเบšเปเบšเบšเบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆเบ‚เบญเบ‡ R arrays, เบ›เปˆเบฝเบ™เบ‚เบฐเบซเบ™เบฒเบ”เบ‚เบญเบ‡เบญเบปเบ‡เบ›เบฐเบเบญเบšเบ—เปเบฒเบญเบดเบ”เบ‚เบญเบ‡เบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆเบ™เบตเป‰ (เป‚เบ”เบเบเบฒเบ™เป€เบญเบปเบฒเบŠเปˆเบญเบ‡เบชเบตเบซเบ™เบถเปˆเบ‡เบซเบผเบทเบชเบฐเป€เบฅเปˆเบเบ—เบฑเบ‡เบชเบฒเบก), เปเบฅเบฐเบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เป‚เบซเบผเบ”เบ™เป‰เปเบฒเบซเบ™เบฑเบเบ„เบทเบ™เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ•เบปเบงเปเบšเบšเบ—เบตเปˆเบกเบตเบŸเบฑเบ‡เบŠเบฑเบ™. set_weights(). เบžเบงเบเป€เบฎเบปเบฒเบšเปเปˆเป€เบ„เบตเบเป€เบžเบตเปˆเบกเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ™เบตเป‰, เป€เบžเบฒเบฐเบงเปˆเบฒเปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบ™เบตเป‰เบกเบฑเบ™เบˆเบฐเปเบˆเป‰เบ‡เปเบฅเป‰เบงเบงเปˆเบฒเบกเบฑเบ™เบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบซเบผเบฒเบเบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเบฎเบนเบšเบžเบฒเบšเบชเบต.

เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบ—เบปเบ”เบฅเบญเบ‡เบชเปˆเบงเบ™เปƒเบซเบเปˆเป‚เบ”เบเปƒเบŠเป‰ mobilenet เบฎเบธเปˆเบ™ 1 เปเบฅเบฐ 2, เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบš resnet34. เบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเบ—เบตเปˆเบ—เบฑเบ™เบชเบฐเป„เบซเบกเบซเบผเบฒเบเป€เบŠเบฑเปˆเบ™ SE-ResNeXt เบ›เบฐเบ•เบดเบšเบฑเบ”เป„เบ”เป‰เบ”เบตเปƒเบ™เบเบฒเบ™เปเบ‚เปˆเบ‡เบ‚เบฑเบ™เบ™เบตเป‰. เปเบ•เปˆเบซเบ™เป‰เบฒเป€เบชเบเบ”เบฒเบ, เบžเบงเบเป€เบฎเบปเบฒเบšเปเปˆเบกเบตเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ—เบตเปˆเบเบฝเบกเบžเป‰เบญเบกเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบเปเบฒเบˆเบฑเบ”เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ, เปเบฅเบฐเบžเบงเบเป€เบฎเบปเบฒเบšเปเปˆเป„เบ”เป‰เบ‚เบฝเบ™เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเป€เบญเบ‡ (เปเบ•เปˆเบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ‚เบฝเบ™เปเบ™เปˆเบ™เบญเบ™).

5. Parameterization เบ‚เบญเบ‡ scripts

เป€เบžเบทเปˆเบญเบ„เบงเบฒเบกเบชเบฐเบ”เบงเบ, เบฅเบฐเบซเบฑเบ”เบ—เบฑเบ‡เปเบปเบ”เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเป„เบ”เป‰เบ–เบทเบเบญเบญเบเปเบšเบšเป€เบ›เบฑเบ™ script เบ”เบฝเบง, เป‚เบ”เบเบ™เปเบฒเปƒเบŠเป‰เบ•เบปเบงเบเปเบฒเบ™เบปเบ”เบเบฒเบ™ docopt เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

doc <- '
Usage:
  train_nn.R --help
  train_nn.R --list-models
  train_nn.R [options]

Options:
  -h --help                   Show this message.
  -l --list-models            List available models.
  -m --model=<model>          Neural network model name [default: mobilenet_v2].
  -b --batch-size=<size>      Batch size [default: 32].
  -s --scale-factor=<ratio>   Scale factor [default: 0.5].
  -c --color                  Use color lines [default: FALSE].
  -d --db-dir=<path>          Path to database directory [default: Sys.getenv("db_dir")].
  -r --validate-ratio=<ratio> Validate sample ratio [default: 0.995].
  -n --n-gpu=<number>         Number of GPUs [default: 1].
'
args <- docopt::docopt(doc)

Package docopt เป€เบ›เบฑเบ™เบ•เบปเบงเปเบ—เบ™เบ‚เบญเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ” http://docopt.org/ เบชเปเบฒเบฅเบฑเบš R. เบ”เป‰เบงเบเบเบฒเบ™เบŠเปˆเบงเบเป€เบซเบผเบทเบญเบ‚เบญเบ‡เบกเบฑเบ™, scripts เบ–เบทเบเป€เบ›เบตเบ”เบ•เบปเบงเบ”เป‰เบงเบเบ„เปเบฒเบชเบฑเปˆเบ‡เบ‡เปˆเบฒเบเป†เป€เบŠเบฑเปˆเบ™ Rscript bin/train_nn.R -m resnet50 -c -d /home/andrey/doodle_db เบซเบผเบท ./bin/train_nn.R -m resnet50 -c -d /home/andrey/doodle_db, เบ–เป‰เบฒเป„เบŸเบฅเปŒ train_nn.R เปเบกเปˆเบ™เบชเบฒเบกเบฒเบ”เบ›เบฐเบ•เบดเบšเบฑเบ”เป„เบ”เป‰ (เบ„เปเบฒเบชเบฑเปˆเบ‡เบ™เบตเป‰เบˆเบฐเป€เบฅเบตเปˆเบกเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเปเบšเบšเบˆเปเบฒเบฅเบญเบ‡ resnet50 เปƒเบ™เบฎเบนเบšเบชเบฒเบกเบชเบตเบ—เบตเปˆเบงเบฑเบ”เปเบ—เบ 128x128 pixels, เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบˆเบฐเบ•เป‰เบญเบ‡เบขเบนเปˆเปƒเบ™เป‚เบŸเบ™เป€เบ”เบต. /home/andrey/doodle_db). เบ—เปˆเบฒเบ™โ€‹เบชเบฒโ€‹เบกเบฒเบ”โ€‹เป€เบžเบตเปˆเบกโ€‹เบ„เบงเบฒเบกโ€‹เป„เบงโ€‹เบเบฒเบ™โ€‹เบฎเบฝเบ™โ€‹เบฎเบนเป‰โ€‹, เบ›เบฐโ€‹เป€เบžเบ” optimizer , เปเบฅเบฐโ€‹เบ•เบปเบงโ€‹เบเปเบฒโ€‹เบ™เบปเบ”โ€‹เบเบฒเบ™โ€‹เบ›เบฑเบšโ€‹เปเบ•เปˆเบ‡โ€‹เบญเบทเปˆเบ™เป†โ€‹เปƒเบ™โ€‹เบšเบฑเบ™โ€‹เบŠเบตโ€‹เบฅเบฒเบโ€‹เบเบฒเบ™โ€‹. เปƒเบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบเบฐเบเบฝเบกเบเบฒเบ™เบžเบดเบกเป€เบœเบตเบเปเบœเปˆ, เบกเบฑเบ™เป„เบ”เป‰เบซเบฑเบ™เบญเบญเบเบงเปˆเบฒเบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐ mobilenet_v2 เบˆเบฒเบโ€‹เบชเบฐโ€‹เบšเบฑเบšโ€‹เบ›เบฐโ€‹เบˆเบธโ€‹เบšเบฑเบ™โ€‹ keras เปƒเบ™ R เปƒเบŠเป‰ เบชเบฒเบกเบฒเบ”เบšเปเปˆเป„เบ”เป‰ เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบ—เบตเปˆเบšเปเปˆเป„เบ”เป‰เบžเบดเบˆเบฒเบฅเบฐเบ™เบฒเปƒเบ™เบŠเบธเบ” R, เบžเบงเบเป€เบฎเบปเบฒเบฅเปเบ–เป‰เบฒเปƒเบซเป‰เบžเบงเบเป€เบ‚เบปเบฒเปเบเป‰เป„เบ‚เบกเบฑเบ™.

เบงเบดเบ—เบตเบเบฒเบ™เบ™เบตเป‰เป€เบฎเบฑเบ”เปƒเบซเป‰เบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เบ—เบตเปˆเบˆเบฐเป€เบฅเบฑเปˆเบ‡เบเบฒเบ™เบ—เบปเบ”เบฅเบญเบ‡เบ—เบตเปˆเบกเบตเบฎเบนเบšเปเบšเบšเบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เบขเปˆเบฒเบ‡เบซเบผเบงเบ‡เบซเบผเบฒเบเป€เบกเบทเปˆเบญเบ—เบฝเบšเบเบฑเบšเบเบฒเบ™เป€เบ›เบตเบ”เบ•เบปเบงเปเบšเบšเบ”เบฑเป‰เบ‡เป€เบ”เบตเบกเบ‚เบญเบ‡ scripts เปƒเบ™ RStudio (เบžเบงเบเป€เบฎเบปเบฒเบชเบฑเบ‡เป€เบเบ”เป€เบซเบฑเบ™เบŠเบธเบ”เบ—เบตเปˆเป€เบ›เบฑเบ™เบ—เบฒเบ‡เป€เบฅเบทเบญเบเบ—เบตเปˆเป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰. tfruns). เปเบ•เปˆเบ›เบฐเป‚เบซเบเบ”เบ•เบปเป‰เบ™เบ•เปเปเบกเปˆเบ™เบ„เบงเบฒเบกเบชเบฒเบกเบฒเบ”เปƒเบ™เบเบฒเบ™เบˆเบฑเบ”เบเบฒเบ™เบเบฒเบ™เป€เบ›เบตเบ”เบ•เบปเบงเบ‚เบญเบ‡เบชเบฐเบ„เบดเบšเปƒเบ™ Docker เป„เบ”เป‰เบขเปˆเบฒเบ‡เบ‡เปˆเบฒเบเบ”เบฒเบเบซเบผเบทเบžเบฝเบ‡เปเบ•เปˆเบขเบนเปˆเปƒเบ™เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบ, เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เบ•เบดเบ”เบ•เบฑเป‰เบ‡ RStudio เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบตเป‰.

6. Dockerization เบ‚เบญเบ‡ scripts

เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เปƒเบŠเป‰ Docker เป€เบžเบทเปˆเบญเบฎเบฑเบšเบ›เบฐเบเบฑเบ™เบเบฒเบ™เป€เบ„เบทเปˆเบญเบ™เบ—เบตเปˆเบ‚เบญเบ‡เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเบชเปเบฒเบฅเบฑเบšเบ•เบปเบงเปเบšเบšเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเบฅเบฐเบซเบงเปˆเบฒเบ‡เบชเบฐเบกเบฒเบŠเบดเบเปƒเบ™เบ—เบตเบก เปเบฅเบฐเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบขเปˆเบฒเบ‡เป„เบงเบงเบฒเปƒเบ™เบ„เบฅเบฒเบง. เบ—เปˆเบฒเบ™โ€‹เบชเบฒโ€‹เบกเบฒเบ”โ€‹เป€เบฅเบตเปˆเบกโ€‹เบ•เบปเป‰เบ™โ€‹เบเบฒเบ™โ€‹เป„เบ”เป‰โ€‹เบฎเบฑเบšโ€‹เบ„เบงเบฒเบกโ€‹เบฎเบนเป‰โ€‹เบˆเบฑเบโ€‹เบเบฑเบšโ€‹เป€เบ„เบทเปˆเบญเบ‡โ€‹เบกเบทโ€‹เบ™เบตเป‰โ€‹, เบ—เบตเปˆโ€‹เบ‚เป‰เบญเบ™โ€‹เบ‚เป‰เบฒเบ‡โ€‹เบœเบดเบ”โ€‹เบ›เบปเบโ€‹เบเบฐโ€‹เบ•เบดโ€‹เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เป‚เบ„เบ‡โ€‹เบเบฒเบ™ R เป€เบ›เบฑเบ™โ€‹, เบกเบตโ€‹ เบ™เบตเป‰ เบŠเบธเบ”เบ‚เบญเบ‡เบชเบดเปˆเบ‡เบžเบดเบกเบซเบผเบท เบงเบดโ€‹เบ”เบตโ€‹เป‚เบญโ€‹เบงเบดโ€‹เบŠเบฒโ€‹เบเบฒเบ™โ€‹.

Docker เบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบชเป‰เบฒเบ‡เบฎเบนเบšเบžเบฒเบšเบ‚เบญเบ‡เบ—เปˆเบฒเบ™เป€เบญเบ‡เบˆเบฒเบเบˆเบธเบ”เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เปเบฅเบฐเบ™เปเบฒเปƒเบŠเป‰เบฎเบนเบšเบžเบฒเบšเบญเบทเปˆเบ™เป†เป€เบ›เบฑเบ™เบžเบทเป‰เบ™เบ–เบฒเบ™เปƒเบ™เบเบฒเบ™เบชเป‰เบฒเบ‡เบ‚เบญเบ‡เบ—เปˆเบฒเบ™เป€เบญเบ‡. เป€เบกเบทเปˆเบญเบงเบดเป€เบ„เบฒเบฐเบ—เบฒเบ‡เป€เบฅเบทเบญเบเบ—เบตเปˆเบกเบตเบขเบนเปˆ, เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบชเบฐเบซเบผเบธเบšเบงเปˆเบฒเบเบฒเบ™เบ•เบดเบ”เบ•เบฑเป‰เบ‡เป„เบ”เป€เบงเบต NVIDIA, CUDA + cuDNN เปเบฅเบฐเบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ” Python เปเบกเปˆเบ™เบชเปˆเบงเบ™เบซเบ™เบถเปˆเบ‡เบ—เบตเปˆเบ‚เป‰เบญเบ™เบ‚เป‰เบฒเบ‡เบ‚เบญเบ‡เบฎเบนเบšเบžเบฒเบš, เปเบฅเบฐเบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ•เบฑเบ”เบชเบดเบ™เปƒเบˆเป€เบญเบปเบฒเบฎเบนเบšเบžเบฒเบšเบ—เบตเปˆเป€เบ›เบฑเบ™เบ—เบฒเบ‡เบเบฒเบ™เป€เบ›เบฑเบ™เบžเบทเป‰เบ™เบ–เบฒเบ™. tensorflow/tensorflow:1.12.0-gpu, เป€เบžเบตเปˆเบกเบŠเบธเบ” R เบ—เบตเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เบขเบนเปˆเบ—เบตเปˆเบ™เบฑเป‰เบ™.

เป„เบŸเบฅเปŒ docker เบชเบธเบ”เบ—เป‰เบฒเบเป€เบšเบดเปˆเบ‡เบ„เบทเบงเปˆเบฒเบ™เบตเป‰:

dockerfile

FROM tensorflow/tensorflow:1.12.0-gpu

MAINTAINER Artem Klevtsov <[email protected]>

SHELL ["/bin/bash", "-c"]

ARG LOCALE="en_US.UTF-8"
ARG APT_PKG="libopencv-dev r-base r-base-dev littler"
ARG R_BIN_PKG="futile.logger checkmate data.table rcpp rapidjsonr dbi keras jsonlite curl digest remotes"
ARG R_SRC_PKG="xtensor RcppThread docopt MonetDBLite"
ARG PY_PIP_PKG="keras"
ARG DIRS="/db /app /app/data /app/models /app/logs"

RUN source /etc/os-release && 
    echo "deb https://cloud.r-project.org/bin/linux/ubuntu ${UBUNTU_CODENAME}-cran35/" > /etc/apt/sources.list.d/cran35.list && 
    apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9 && 
    add-apt-repository -y ppa:marutter/c2d4u3.5 && 
    add-apt-repository -y ppa:timsc/opencv-3.4 && 
    apt-get update && 
    apt-get install -y locales && 
    locale-gen ${LOCALE} && 
    apt-get install -y --no-install-recommends ${APT_PKG} && 
    ln -s /usr/lib/R/site-library/littler/examples/install.r /usr/local/bin/install.r && 
    ln -s /usr/lib/R/site-library/littler/examples/install2.r /usr/local/bin/install2.r && 
    ln -s /usr/lib/R/site-library/littler/examples/installGithub.r /usr/local/bin/installGithub.r && 
    echo 'options(Ncpus = parallel::detectCores())' >> /etc/R/Rprofile.site && 
    echo 'options(repos = c(CRAN = "https://cloud.r-project.org"))' >> /etc/R/Rprofile.site && 
    apt-get install -y $(printf "r-cran-%s " ${R_BIN_PKG}) && 
    install.r ${R_SRC_PKG} && 
    pip install ${PY_PIP_PKG} && 
    mkdir -p ${DIRS} && 
    chmod 777 ${DIRS} && 
    rm -rf /tmp/downloaded_packages/ /tmp/*.rds && 
    rm -rf /var/lib/apt/lists/*

COPY utils /app/utils
COPY src /app/src
COPY tests /app/tests
COPY bin/*.R /app/

ENV DBDIR="/db"
ENV CUDA_HOME="/usr/local/cuda"
ENV PATH="/app:${PATH}"

WORKDIR /app

VOLUME /db
VOLUME /app

CMD bash

เป€เบžเบทเปˆเบญเบ„เบงเบฒเบกเบชเบฐเบ”เบงเบ, เปเบžเบเป€เบเบ”เบ—เบตเปˆเปƒเบŠเป‰เป„เบ”เป‰เปƒเบชเปˆเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ•เบปเบงเปเบ›; เบชเปˆเบงเบ™เปƒเบซเบเปˆเบ‚เบญเบ‡เบ•เบปเบงเบญเบฑเบเบชเบญเบ™เบ—เบตเปˆเบ‚เบฝเบ™เป„เบ”เป‰เบ–เบทเบเบ„เบฑเบ”เบฅเบญเบเบžเบฒเบเปƒเบ™เบšเบฑเบ™เบˆเบธเปƒเบ™เบฅเบฐเบซเบงเปˆเบฒเบ‡เบเบฒเบ™เบ›เบฐเบเบญเบš. เบžเบงเบเป€เบฎเบปเบฒเบเบฑเบ‡เป„เบ”เป‰เบ›เปˆเบฝเบ™ shell เบ„เปเบฒเบชเบฑเปˆเบ‡เป€เบ›เบฑเบ™ /bin/bash เป€เบžเบทเปˆเบญเบ„เบงเบฒเบกเบชเบฐเบ”เบงเบเปƒเบ™เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เป€เบ™เบทเป‰เบญเบซเบฒ /etc/os-release. เบ™เบตเป‰เบซเบผเบตเบเป€เบงเบฑเป‰เบ™เบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™เบ—เบตเปˆเบˆเบฐเบฅเบฐเบšเบธเบชเบฐเบšเบฑเบš OS เปƒเบ™เบฅเบฐเบซเบฑเบ”.

เบ™เบญเบเบˆเบฒเบเบ™เบฑเป‰เบ™, script bash เบ‚เบฐเบซเบ™เบฒเบ”เบ™เป‰เบญเบเป„เบ”เป‰เบ–เบทเบเบ‚เบฝเบ™เป„เบงเป‰เบ—เบตเปˆเบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบ›เบตเบ”เบ•เบปเบง container เบ—เบตเปˆเบกเบตเบ„เปเบฒเบชเบฑเปˆเบ‡เบ•เปˆเบฒเบ‡เป†. เบชเปเบฒเบฅเบฑเบšเบ•เบปเบงเบขเปˆเบฒเบ‡, เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบชเบฒเบกเบฒเบ”เป€เบ›เบฑเบ™เบชเบฐเบ„เบดเบšเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural เบ—เบตเปˆเบงเบฒเบ‡เป„เบงเป‰เบเปˆเบญเบ™เบซเบ™เป‰เบฒเบ™เบตเป‰เบžเบฒเบเปƒเบ™ container, เบซเบผเบท shell เบ„เปเบฒเบชเบฑเปˆเบ‡เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™ debugging เปเบฅเบฐเบ•เบดเบ”เบ•เบฒเบกเบเบงเบ”เบเบฒเบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบ‡เบฒเบ™เบ‚เบญเบ‡ container เป„เบ”เป‰:

เบชเบฐเบ„เบฃเบดเบšเป€เบžเบทเปˆเบญเป€เบ›เบตเบ”เบเปˆเบญเบ‡เบšเบฑเบ™เบˆเบธ

#!/bin/sh

DBDIR=${PWD}/db
LOGSDIR=${PWD}/logs
MODELDIR=${PWD}/models
DATADIR=${PWD}/data
ARGS="--runtime=nvidia --rm -v ${DBDIR}:/db -v ${LOGSDIR}:/app/logs -v ${MODELDIR}:/app/models -v ${DATADIR}:/app/data"

if [ -z "$1" ]; then
    CMD="Rscript /app/train_nn.R"
elif [ "$1" = "bash" ]; then
    ARGS="${ARGS} -ti"
else
    CMD="Rscript /app/train_nn.R $@"
fi

docker run ${ARGS} doodles-tf ${CMD}

เบ–เป‰เบฒ script bash เบ™เบตเป‰เบ–เบทเบเปเบฅเปˆเบ™เป‚เบ”เบเบšเปเปˆเบกเบตเบžเบฒเบฅเบฒเบกเบดเป€เบ•เบต, script เบˆเบฐเบ–เบทเบเป€เบญเบตเป‰เบ™เบžเบฒเบเปƒเบ™ container train_nn.R เบ”เป‰เบงเบเบ„เปˆเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™; เบ–เป‰เบฒเบเบฒเบ™เป‚เบ•เป‰เบ–เบฝเบ‡เบ•เปเบฒเปเบซเบ™เปˆเบ‡เบ—เปเบฒเบญเบดเบ”เปเบกเปˆเบ™ "bash", เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™, เบšเบฑเบ™เบˆเบธเบˆเบฐเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบเบฒเบ™เป‚เบ•เป‰เบ•เบญเบšเบเบฑเบšเปเบเบฐเบ„เปเบฒเบชเบฑเปˆเบ‡. เปƒเบ™เบเปเบฅเบฐเบ™เบตเบญเบทเปˆเบ™เป†, เบกเบนเบ™เบ„เปˆเบฒเบ‚เบญเบ‡เบเบฒเบ™เป‚เบ•เป‰เบ–เบฝเบ‡เบ•เปเบฒเปเบซเบ™เปˆเบ‡เปเบกเปˆเบ™เบ—เบปเบ”เปเบ—เบ™: CMD="Rscript /app/train_nn.R $@".

เบกเบฑเบ™เป€เบ›เบฑเบ™เบกเบนเบ™เบ„เปˆเบฒเบ—เบตเปˆเบชเบฑเบ‡เป€เบเบ”เบงเปˆเบฒเป„เบ”เป€เบฅเบเบฐเบ—เปเบฅเบตเบ—เบตเปˆเบกเบตเบ‚เปเป‰เบกเบนเบ™เปเบซเบผเปˆเบ‡เปเบฅเบฐเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™, เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเป„เบ”เป€เบฅเบเบฐเบ—เปเบฅเบตเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เบฐเบซเบเบฑเบ”เบ•เบปเบงเปเบšเบšเบ—เบตเปˆเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบก, เบ–เบทเบเบ•เบดเบ”เบ•เบฑเป‰เบ‡เบขเบนเปˆเปƒเบ™เบ–เบฑเบ‡เบˆเบฒเบเบฅเบฐเบšเบปเบšเป‚เบฎเบ”, เป€เบŠเบดเปˆเบ‡เบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบ‚เบปเป‰เบฒเบซเบฒเบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเบ‚เบญเบ‡เบชเบฐเบ„เบดเบšเป„เบ”เป‰เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เบซเบกเบนเบ™เปƒเบŠเป‰เบ—เบตเปˆเบšเปเปˆเบˆเปเบฒเป€เบ›เบฑเบ™.

7. เบเบฒเบ™เปƒเบŠเป‰ GPU เบซเบผเบฒเบเบญเบฑเบ™เปƒเบ™ Google Cloud

เบซเบ™เบถเปˆเบ‡เปƒเบ™เบฅเบฑเบเบชเบฐเบ™เบฐเบ‚เบญเบ‡เบเบฒเบ™เปเบ‚เปˆเบ‡เบ‚เบฑเบ™เปเบกเปˆเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบšเปเปˆเบกเบตเบชเบฝเบ‡เบซเบผเบฒเบ (เป€เบšเบดเปˆเบ‡เบฎเบนเบšเบซเบปเบงเบ‚เปเป‰, เบขเบทเบกเบˆเบฒเบ @Leigh.plt เบˆเบฒเบ ODS slack). เบŠเบธเบ”เปƒเบซเบเปˆเบŠเปˆเบงเบเบ•เปเปˆเบชเบนเป‰เบเบฑเบšเบชเบดเปˆเบ‡เบ™เบตเป‰, เปเบฅเบฐเบซเบผเบฑเบ‡เบˆเบฒเบเบเบฒเบ™เบ—เบปเบ”เบฅเบญเบ‡เปƒเบ™ PC เบ—เบตเปˆเบกเบต 1 GPU, เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ•เบฑเบ”เบชเบดเบ™เปƒเบˆเบชเป‰เบฒเบ‡เปเบšเบšเบˆเปเบฒเบฅเบญเบ‡เบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเปƒเบ™เบซเบผเบฒเบเป† GPUs เปƒเบ™เบ„เบฅเบฒเบง. เปƒเบŠเป‰ GoogleCloud (เบ„เบนเปˆเบกเบทเบ—เบตเปˆเบ”เบตเบเปˆเบฝเบงเบเบฑเบšเบžเบทเป‰เบ™เบ–เบฒเบ™) เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบเบฒเบ™เบ„เบฑเบ”เป€เบฅเบทเบญเบเบ‚เบฐเบซเบ™เบฒเบ”เปƒเบซเบเปˆเบ‚เบญเบ‡เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบ—เบตเปˆเบกเบตเบขเบนเปˆ, เบฅเบฒเบ„เบฒเบ—เบตเปˆเบชเบปเบกเป€เบซเบ”เบชเบปเบกเบœเบปเบ™เปเบฅเบฐ $ 300 เป‚เบšเบ™เบฑเบ”. เบ”เป‰เบงเบเบ„เบงเบฒเบกเป‚เบฅเบšเบกเบฒเบ, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เบชเบฑเปˆเบ‡เบ•เบปเบงเบขเปˆเบฒเบ‡ 4xV100 เบ—เบตเปˆเบกเบต SSD เปเบฅเบฐ RAM เป‚เบ•เบ™, เปเบฅเบฐเบ™เบฑเป‰เบ™เปเบกเปˆเบ™เบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”เบญเบฑเบ™เปƒเบซเบเปˆเบซเบผเบงเบ‡. เป€เบ„เบทเปˆเบญเบ‡เบˆเบฑเบเบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเบเบดเบ™เป€เบ‡เบดเบ™เบขเปˆเบฒเบ‡เป„เบงเบงเบฒ; เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ—เปเบฒเบฅเบฒเบเบเบฒเบ™เบ—เบปเบ”เบฅเบญเบ‡เป„เบ”เป‰เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เบžเบดเบชเบนเบ”. เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบชเบถเบเบชเบฒ, เบกเบฑเบ™เบ”เบตเบเบงเปˆเบฒเบ—เบตเปˆเบˆเบฐเป€เบญเบปเบฒ K80. เปเบ•เปˆเบˆเปเบฒเบ™เบงเบ™ RAM เบ‚เบฐเบซเบ™เบฒเบ”เปƒเบซเบเปˆเบกเบฒเบชเบฐเบ”เบงเบ - SSD เบŸเบฑเบ‡เบšเปเปˆเบ›เบฐเบ—เบฑเบšเปƒเบˆเบเบฑเบšเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‚เบญเบ‡เบกเบฑเบ™, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เป„เบ”เป‰เบ–เบทเบเป‚เบญเบ™เป„เบ›เบซเบฒ. dev/shm.

เบ„เบงเบฒเบกเบชเบปเบ™เปƒเบˆเบ—เบตเปˆเบเบดเปˆเบ‡เปƒเบซเบเปˆเบ—เบตเปˆเบชเบธเบ”เปเบกเปˆเบ™เบŠเบดเป‰เบ™เบชเปˆเบงเบ™เบฅเบฐเบซเบฑเบ”เบ—เบตเปˆเบฎเบฑเบšเบœเบดเบ”เบŠเบญเบšเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰ GPU เบซเบผเบฒเบ. เบ—เปเบฒเบญเบดเบ”, เบฎเบนเบšเปเบšเบšเปเบกเปˆเบ™เบ–เบทเบเบชเป‰เบฒเบ‡เบ‚เบถเป‰เบ™เปƒเบ™ CPU เป‚เบ”เบเปƒเบŠเป‰เบ•เบปเบงเบˆเบฑเบ”เบเบฒเบ™เบชเบฐเบžเบฒเบšเบเบฒเบ™, เบ„เบทเบเบฑเบ™เบเบฑเบšเปƒเบ™ Python:

with(tensorflow::tf$device("/cpu:0"), {
  model_cpu <- get_model(
    name = model_name,
    input_shape = input_shape,
    weights = weights,
    metrics =(top_3_categorical_accuracy,
    compile = FALSE
  )
})

เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™, เบฎเบนเบšเปเบšเบšเบ—เบตเปˆเบšเปเปˆเป„เบ”เป‰เบฅเบงเบšเบฅเบงเบก (เบ™เบตเป‰เปเบกเปˆเบ™เบชเปเบฒเบ„เบฑเบ™) เบ–เบทเบเบ„เบฑเบ”เบฅเบญเบเป„เบ›เบซเบฒเบˆเปเบฒเบ™เบงเบ™ GPUs เบ—เบตเปˆเบกเบตเบขเบนเปˆ, เปเบฅเบฐเบžเบฝเบ‡เปเบ•เปˆเบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบกเบฑเบ™เบ–เบทเบเบฅเบงเบšเบฅเบงเบก:

model <- keras::multi_gpu_model(model_cpu, gpus = n_gpu)
keras::compile(
  object = model,
  optimizer = keras::optimizer_adam(lr = 0.0004),
  loss = "categorical_crossentropy",
  metrics = c(top_3_categorical_accuracy)
)

เป€เบ•เบฑเบเบ™เบดเบเบ„เบฅเบฒเบชเบชเบดเบเบ‚เบญเบ‡เบเบฒเบ™เปเบŠเปˆเปเบ‚เบ‡เบ—เบธเบเบŠเบฑเป‰เบ™เบเบปเบเป€เบงเบฑเป‰เบ™เบญเบฑเบ™เบชเบธเบ”เบ—เป‰เบฒเบ, เบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเบŠเบฑเป‰เบ™เบชเบธเบ”เบ—เป‰เบฒเบ, เบเบปเบเป€เบฅเบตเบเบเบฒเบ™เปเบŠเปˆเปเบ‚เปเบ‡เปเบฅเบฐเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเปเบšเบšเบˆเปเบฒเบฅเบญเบ‡เบ—เบฑเบ‡เบซเบกเบปเบ”เบชเปเบฒเบฅเบฑเบš GPU เบซเบผเบฒเบเป†เบญเบฑเบ™เบšเปเปˆเบชเบฒเบกเบฒเบ”เบ›เบฐเบ•เบดเบšเบฑเบ”เป„เบ”เป‰.

เบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเป„เบ”เป‰เบ–เบทเบเบ•เบดเบ”เบ•เบฒเบกเป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰. tensorboard, เบˆเปเบฒเบเบฑเบ”เบ•เบปเบงเป€เบฎเบปเบฒเป€เบญเบ‡เป€เบžเบทเปˆเบญเบšเบฑเบ™เบ—เบถเบเบšเบฑเบ™เบ—เบถเบเปเบฅเบฐเบฎเบนเบšเปเบšเบšเบเบฒเบ™เบ›เบฐเบซเบเบฑเบ”เบ—เบตเปˆเบกเบตเบŠเบทเปˆเบ‚เปเป‰เบกเบนเบ™เบซเบผเบฑเบ‡เบˆเบฒเบเปเบ•เปˆเบฅเบฐเบเบธเบ:

เป‚เบ—เบเบฑเบš

# ะจะฐะฑะปะพะฝ ะธะผะตะฝะธ ั„ะฐะนะปะฐ ะปะพะณะฐ
log_file_tmpl <- file.path("logs", sprintf(
  "%s_%d_%dch_%s.csv",
  model_name,
  dim_size,
  channels,
  format(Sys.time(), "%Y%m%d%H%M%OS")
))
# ะจะฐะฑะปะพะฝ ะธะผะตะฝะธ ั„ะฐะนะปะฐ ะผะพะดะตะปะธ
model_file_tmpl <- file.path("models", sprintf(
  "%s_%d_%dch_{epoch:02d}_{val_loss:.2f}.h5",
  model_name,
  dim_size,
  channels
))

callbacks_list <- list(
  keras::callback_csv_logger(
    filename = log_file_tmpl
  ),
  keras::callback_early_stopping(
    monitor = "val_loss",
    min_delta = 1e-4,
    patience = 8,
    verbose = 1,
    mode = "min"
  ),
  keras::callback_reduce_lr_on_plateau(
    monitor = "val_loss",
    factor = 0.5, # ัƒะผะตะฝัŒัˆะฐะตะผ lr ะฒ 2 ั€ะฐะทะฐ
    patience = 4,
    verbose = 1,
    min_delta = 1e-4,
    mode = "min"
  ),
  keras::callback_model_checkpoint(
    filepath = model_file_tmpl,
    monitor = "val_loss",
    save_best_only = FALSE,
    save_weights_only = FALSE,
    mode = "min"
  )
)

8. เปเบ—เบ™เบ—เบตเปˆเบˆเบฐเป€เบ›เบฑเบ™เบเบฒเบ™เบชเบฐเบซเบฅเบธเบš

เบšเบฑเบ™เบซเบฒเบˆเปเบฒเบ™เบงเบ™เบซเบ™เบถเปˆเบ‡เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบžเบปเบšเบเบฑเบ‡เบšเปเปˆเบ—เบฑเบ™เป„เบ”เป‰เปเบเป‰เป„เบ‚:

  • ะฒ keras เบšเปเปˆเบกเบตเบŸเบฑเบ‡เบŠเบฑเบ™เบ—เบตเปˆเบเบฝเบกเบžเป‰เบญเบกเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบŠเบญเบเบซเบฒเบญเบฑเบ”เบ•เบฐเป‚เบ™เบกเบฑเบ”เบชเปเบฒเบฅเบฑเบšเบญเบฑเบ”เบ•เบฒเบเบฒเบ™เบฎเบฝเบ™เบฎเบนเป‰เบ—เบตเปˆเบ”เบตเบ—เบตเปˆเบชเบธเบ” (analogue lr_finder เปƒเบ™เบซเปเบชเบฐเบกเบธเบ” fast.ai); เบ”เป‰เบงเบเบ„เบงเบฒเบกเบžเบฐเบเบฒเบเบฒเบกเบšเบฒเบ‡เบขเปˆเบฒเบ‡, เบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เบ—เบตเปˆเบˆเบฐเบชเบปเปˆเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‚เบญเบ‡เบžเบฒเบเบชเปˆเบงเบ™เบ—เบตเบชเบฒเบกเป„เบ›เบซเบฒ R, เบชเปเบฒเบฅเบฑเบšเบ•เบปเบงเบขเปˆเบฒเบ‡, เบ™เบตเป‰;
  • เป€เบ›เบฑเบ™เบœเบปเบ™เบกเบฒเบˆเบฒเบเบˆเบธเบ”เบ—เบตเปˆเบœเปˆเบฒเบ™เบกเบฒ, เบกเบฑเบ™เบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบฅเบทเบญเบเบ„เบงเบฒเบกเป„เบงเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเบ—เบตเปˆเบ–เบทเบเบ•เป‰เบญเบ‡เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเปƒเบŠเป‰ GPUs เบซเบผเบฒเบ;
  • เบกเบตเบเบฒเบ™เบ‚เบฒเบ”เบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural เบ—เบตเปˆเบ—เบฑเบ™เบชเบฐเป„เบซเบก, เป‚เบ”เบเบชเบฐเป€เบžเบฒเบฐเปเบกเปˆเบ™เบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเป€เบšเบทเป‰เบญเบ‡เบ•เบปเป‰เบ™เปƒเบ™ imagenet;
  • เบšเปเปˆโ€‹เบกเบตโ€‹เบ™เบฐโ€‹เป‚เบโ€‹เบšเบฒเบโ€‹เบงเบปเบ‡โ€‹เบˆเบญเบ™โ€‹เปƒเบ”โ€‹เบซเบ™เบถเปˆเบ‡โ€‹เปเบฅเบฐโ€‹เบญเบฑเบ”โ€‹เบ•เบฒโ€‹เบเบฒเบ™โ€‹เบฎเบฝเบ™โ€‹เบฎเบนเป‰โ€‹เบˆเปเบฒโ€‹เปเบ™เบ (เบเบฒเบ™โ€‹เป€เบŠเบทเปˆเบญเบกโ€‹เบชเบฒเบ™ cosine เปเบกเปˆเบ™โ€‹เบขเบนเปˆโ€‹เปƒเบ™โ€‹เบ„เปเบฒโ€‹เบฎเป‰เบญเบ‡โ€‹เบชเบฐโ€‹เบซเบกเบฑเบโ€‹เบ‚เบญเบ‡โ€‹เบžเบงเบโ€‹เป€เบฎเบปเบฒโ€‹ เบ›เบฐเบ•เบดเบšเบฑเบ”, เบ‚เบญเบšโ€‹เปƒเบˆ เบชเบฐเบเบตเปเบ”เบ™).

เบชเบดเปˆเบ‡เบ—เบตเปˆเป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ”เบ—เบตเปˆเป„เบ”เป‰เบฎเบฝเบ™เบฎเบนเป‰เบˆเบฒเบเบเบฒเบ™เปเบ‚เปˆเบ‡เบ‚เบฑเบ™เบ™เบตเป‰:

  • เปƒเบ™เบฎเบฒเบ”เปเบงเบ—เบตเปˆเบกเบตเบžเบฐเบฅเบฑเบ‡เบ‡เบฒเบ™เบ•เปˆเปเบฒ, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเบ›เบฐเบฅเบดเบกเบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเป€เบซเบกเบฒเบฐเบชเบปเบก (เบซเบผเบฒเบเบ„เบฑเป‰เบ‡เบ‚เบญเบ‡ RAM) เป‚เบ”เบเบšเปเปˆเบกเบตเบ„เบงเบฒเบกเป€เบˆเบฑเบšเบ›เบงเบ”. เบ–เบปเบ‡โ€‹เบขเบฒเบ‡ เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ เบŠเปˆเบงเบเบ›เบฐเบขเบฑเบ”เบ„เบงเบฒเบกเบŠเบปเบ‡เบˆเปเบฒเป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบเบฒเบ™เบ”เบฑเบ”เปเบ›เบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡, เป€เบŠเบดเปˆเบ‡เบซเบผเบตเบเป€เบงเบฑเป‰เบ™เบเบฒเบ™เบ„เบฑเบ”เบฅเบญเบเบžเบงเบเบกเบฑเบ™, เปเบฅเบฐเป€เบกเบทเปˆเบญเบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เบขเปˆเบฒเบ‡เบ–เบทเบเบ•เป‰เบญเบ‡, เบ„เบงเบฒเบกเบชเบฒเบกเบฒเบ”เบ‚เบญเบ‡เบกเบฑเบ™เป€เบเบทเบญเบšเบชเบฐเป€เบซเบกเบตเบชเบฐเปเบ”เบ‡เปƒเบซเป‰เป€เบซเบฑเบ™เป€เบ–เบดเบ‡เบ„เบงเบฒเบกเป„เบงเบชเบนเบ‡เบชเบธเบ”เปƒเบ™เบšเบฑเบ™เบ”เบฒเป€เบ„เบทเปˆเบญเบ‡เบกเบทเบ—เบฑเบ‡เบซเบกเบปเบ”เบ—เบตเปˆเบฎเบนเป‰เบˆเบฑเบเบเบฑเบšเบžเบงเบเป€เบฎเบปเบฒเบชเปเบฒเบฅเบฑเบšเบžเบฒเบชเบฒเบชเบฐเบ„เบดเบš. เบเบฒเบ™เบ›เบฐเบซเบเบฑเบ”เบ‚เปเป‰เบกเบนเบ™เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™, เปƒเบ™เบซเบผเบฒเบเป†เบเปเบฅเบฐเบ™เบต, เบšเปเปˆเบ•เป‰เบญเบ‡เบ„เบดเบ”เบเปˆเบฝเบงเบเบฑเบšเบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™เบ—เบตเปˆเบˆเบฐเบšเบตเบšเบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ RAM.
  • เบŸเบฑเบ‡เบŠเบฑเบ™เบŠเป‰เบฒเปƒเบ™ R เบชเบฒเบกเบฒเบ”เบ–เบทเบเปเบ—เบ™เบ—เบตเปˆเบ”เป‰เบงเบเป„เบงเปƒเบ™ C++ เป‚เบ”เบเปƒเบŠเป‰เบŠเบธเบ” Rcpp. เบ–เป‰เบฒโ€‹เบซเบฒเบโ€‹เบงเปˆเบฒโ€‹เบ™เบญเบโ€‹เป€เบซเบ™เบทเบญโ€‹เป„เบ›โ€‹เบˆเบฒเบโ€‹เบเบฒเบ™โ€‹เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹ RcppThread เบซเบผเบท RcppParallel, เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบซเบผเบฒเบเบเบฐเบ—เบนเป‰เบ‚เป‰เบฒเบกเป€เบงเบ—เบต, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบšเปเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบกเบตเบเบฒเบ™เบ‚เบฐเบซเบ™เบฒเบ™เบฅเบฐเบซเบฑเบ”เบขเบนเปˆเปƒเบ™เบฅเบฐเบ”เบฑเบš R.
  • เบŠเบธเบ” Rcpp เบชเบฒเบกเบฒเบ”เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เป‚เบ”เบเบšเปเปˆเบกเบตเบ„เบงเบฒเบกเบฎเบนเป‰เบ—เบตเปˆเบฎเป‰เบฒเบเปเบฎเบ‡เบ‚เบญเบ‡ C ++, เบ•เปเบฒเปˆเบชเบธเบ”เบ—เบตเปˆเบ—เบตเปˆเบเปเบฒเบ™เบปเบ”เป„เบงเป‰เปเบกเปˆเบ™เป„เบ”เป‰เบฅเบฐเบšเบธเป„เบงเป‰ เบ—เบตเปˆเบ™เบตเป‰. เป„เบŸเบฅเปŒเบซเบปเบงเบชเปเบฒเบฅเบฑเบšเบˆเปเบฒเบ™เบงเบ™เบ‚เบญเบ‡เบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ” C เป€เบขเบฑเบ™เป€เบŠเบฑเปˆเบ™ xtensor เบกเบตเบขเบนเปˆเปƒเบ™ CRAN, เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบžเบทเป‰เบ™เบ–เบฒเบ™เป„เบ”เป‰เบ–เบทเบเบชเป‰เบฒเบ‡เบ•เบฑเป‰เบ‡เบ‚เบถเป‰เบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบˆเบฑเบ”เบ•เบฑเป‰เบ‡เบ›เบฐเบ•เบดเบšเบฑเบ”เป‚เบ„เบ‡เบเบฒเบ™เบ—เบตเปˆเบ›เบฐเบชเบปเบกเบ›เบฐเบชเบฒเบ™เบฅเบฐเบซเบฑเบ” C ++ เบ—เบตเปˆเบกเบตเบ›เบฐเบชเบดเบ”เบ•เบดเบžเบฒเบšเบชเบนเบ‡เบ—เบตเปˆเบเบฝเบกเบžเป‰เบญเบกเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ R. เบ„เบงเบฒเบกเบชเบฐเบ”เบงเบเบชเบฐเบšเบฒเบเป€เบžเบตเปˆเบกเป€เบ•เบตเบกเปเบกเปˆเบ™เบเบฒเบ™เป€เบ™เบฑเป‰เบ™ syntax เปเบฅเบฐเบ•เบปเบงเบงเบดเป€เบ„เบฒเบฐเบฅเบฐเบซเบฑเบ” C++ เบ„เบปเบ‡เบ—เบตเปˆเปƒเบ™ RStudio.
  • docopt เบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เบ—เปˆเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™ scripts เบ”เป‰เบงเบเบ•เบปเบ™เป€เบญเบ‡เบ—เบตเปˆเบกเบตเบžเบฒเบฅเบฒเบกเบดเป€เบ•เบต. เบ™เบตเป‰เปเบกเปˆเบ™เบชเบฐเบ”เบงเบเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เปƒเบ™เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบซเปˆเบฒเบ‡เป„เบเบชเบญเบเบซเบผเบตเบ, incl. เบžเบฒเบเปƒเบ•เป‰ docker. เปƒเบ™ RStudio, เบกเบฑเบ™เบšเปเปˆเบชเบฐเบ”เบงเบเบ—เบตเปˆเบˆเบฐเบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบ—เบปเบ”เบฅเบญเบ‡เบซเบผเบฒเบเบŠเบปเปˆเบงเป‚เบกเบ‡เบเบฑเบšเป€เบ„เบทเบญเบ‚เปˆเบฒเบ neural เบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบก, เปเบฅเบฐเบเบฒเบ™เบ•เบดเบ”เบ•เบฑเป‰เบ‡ IDE เปƒเบ™เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบ‚เบญเบ‡เบ•เบปเบงเบกเบฑเบ™เป€เบญเบ‡เปเบกเปˆเบ™เบšเปเปˆเบชเบปเบกเป€เบซเบ”เบชเบปเบกเบœเบปเบ™เบชเบฐเป€เบซเบกเบต.
  • Docker เบฎเบฑเบšเบ›เบฐเบเบฑเบ™เบเบฒเบ™เป€เบ„เบทเปˆเบญเบ™เบ—เบตเปˆเบ‚เบญเบ‡เบฅเบฐเบซเบฑเบ”เปเบฅเบฐเบเบฒเบ™เปเบœเปˆเบžเบฑเบ™เบ‚เบญเบ‡เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเบฅเบฐเบซเบงเปˆเบฒเบ‡เบœเบนเป‰เบžเบฑเบ”เบ—เบฐเบ™เบฒเบ—เบตเปˆเบกเบตเบฅเบธเป‰เบ™ OS เปเบฅเบฐเบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ”เบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™, เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบ„เบงเบฒเบกเบ‡เปˆเบฒเบเปƒเบ™เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบ. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบ›เบตเบ”เบ—เปเปˆเบเบฒเบ™เบเบถเบเบญเบปเบšเบฎเบปเบกเบ—เบฑเบ‡เบซเบกเบปเบ”เบ”เป‰เบงเบเบ„เปเบฒเบชเบฑเปˆเบ‡เบ”เบฝเบง.
  • Google Cloud เป€เบ›เบฑเบ™เบงเบดเบ—เบตเบ—เบตเปˆเปƒเบŠเป‰เบ‡เบปเบšเบ›เบฐเบกเบฒเบ™เป€เบžเบทเปˆเบญเบ—เบปเบ”เบฅเบญเบ‡เปƒเบŠเป‰เบฎเบฒเบ”เปเบงเบฅเบฒเบ„เบฒเปเบžเบ‡, เปเบ•เปˆเบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เป€เบฅเบทเบญเบเบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบขเปˆเบฒเบ‡เบฅเบฐเบกเบฑเบ”เบฅเบฐเบงเบฑเบ‡.
  • เบเบฒเบ™โ€‹เบงเบฑเบ”โ€‹เปเบ—เบโ€‹เบ„เบงเบฒเบกโ€‹เป„เบงโ€‹เบ‚เบญเบ‡โ€‹เบฅเบฐโ€‹เบซเบฑเบ”โ€‹เบชเปˆเบงเบ™โ€‹เบšเบธเบโ€‹เบ„เบปเบ™โ€‹เปเบกเปˆเบ™โ€‹เป€เบ›เบฑเบ™โ€‹เบ›เบฐโ€‹เป‚เบซเบเบ”โ€‹เบซเบผเบฒเบโ€‹, เป‚เบ”เบโ€‹เบชเบฐโ€‹เป€เบžเบฒเบฐโ€‹เปเบกเปˆเบ™โ€‹เปƒเบ™โ€‹เป€เบงโ€‹เบฅเบฒโ€‹เบ—เบตเปˆโ€‹เบเบฒเบ™โ€‹เบ›เบฐโ€‹เบชเบปเบก R เปเบฅเบฐ C ++โ€‹, เปเบฅเบฐโ€‹เบเบฑเบšโ€‹เบŠเบธเบ”โ€‹. bench - เบเบฑเบ‡โ€‹เบ‡เปˆเบฒเบโ€‹เบซเบผเบฒเบโ€‹.

เป‚เบ”เบเบฅเบงเบกเปเบฅเป‰เบง, เบ›เบฐเบชเบปเบšเบเบฒเบ™เบ™เบตเป‰เปเบกเปˆเบ™เปƒเบซเป‰เบฅเบฒเบ‡เบงเบฑเบ™เบซเบผเบฒเบ เปเบฅเบฐเบžเบงเบเป€เบฎเบปเบฒเบชเบทเบšเบ•เปเปˆเป€เบฎเบฑเบ”เบงเบฝเบเป€เบžเบทเปˆเบญเปเบเป‰เป„เบ‚เบšเบฒเบ‡เบšเบฑเบ™เบซเบฒเบ—เบตเปˆเบเบปเบเบ‚เบถเป‰เบ™เบกเบฒ.

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™