เช•เซเชตเชฟเช• เชกเซเชฐเซ‹ เชกเซ‚เชกเชฒ เชฐเซ‡เช•เช—เซเชจเชฟเชถเชจ: R, C++ เช…เชจเซ‡ เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช• เชธเชพเชฅเซ‡ เชฎเชฟเชคเซเชฐเซ‹ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฌเชจเชพเชตเชตเซเช‚

เช•เซเชตเชฟเช• เชกเซเชฐเซ‹ เชกเซ‚เชกเชฒ เชฐเซ‡เช•เช—เซเชจเชฟเชถเชจ: R, C++ เช…เชจเซ‡ เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช• เชธเชพเชฅเซ‡ เชฎเชฟเชคเซเชฐเซ‹ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฌเชจเชพเชตเชตเซเช‚

เชนเซ‡ เชนเชฌเชฐ!

เช›เซ‡เชฒเซเชฒเชพ เชชเชพเชจเช–เชฐเชฎเชพเช‚, เช•เชพเช—เชฒเซ‡ เชนเชพเชฅเชฅเซ€ เชฆเซ‹เชฐเซ‡เชฒเชพ เชšเชฟเชคเซเชฐเซ‹เชจเซ‡ เชตเชฐเซเช—เซ€เช•เซƒเชค เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชเช• เชธเซเชชเชฐเซเชงเชพเชจเซเช‚ เช†เชฏเซ‹เชœเชจ เช•เชฐเซเชฏเซเช‚ เชนเชคเซเช‚, เช•เซเชตเชฟเช• เชกเซเชฐเซ‹ เชกเซ‚เชกเชฒ เชฐเซ‡เช•เช—เซเชจเชฟเชถเชจ, เชœเซ‡เชฎเชพเช‚ เช…เชจเซเชฏเซ‹ เชตเชšเซเชšเซ‡, เช†เชฐ-เชตเซˆเชœเซเชžเชพเชจเชฟเช•เซ‹เชจเซ€ เชŸเซ€เชฎเซ‡ เชญเชพเช— เชฒเซ€เชงเซ‹ เชนเชคเซ‹: เช†เชฐเซเชŸเซ‡เชฎ เช•เซเชฒเซ‡เชตเชคเซเชธเซ‹เชตเชพ, เชซเชฟเชฒเชฟเชชเชพ เชฎเซ‡เชจเซ‡เชœเชฐ ะธ เช†เชจเซเชฆเซเชฐเซ‡ เช“เช—เซเชฐเซเชคเซเชธเซ‹เชต. เช…เชฎเซ‡ เชธเซเชชเชฐเซเชงเชพเชจเซเช‚ เชตเชฟเช—เชคเชตเชพเชฐ เชตเชฐเซเชฃเชจ เช•เชฐเซ€เชถเซเช‚ เชจเชนเซ€เช‚; เชคเซ‡ เชชเชนเซ‡เชฒเชพเชฅเซ€ เชœ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซเช‚ เช›เซ‡ เชคเชพเชœเซ‡เชคเชฐเชจเซเช‚ เชชเซเชฐเช•เชพเชถเชจ.

เช† เชตเช–เชคเซ‡ เชคเซ‡ เชฎเซ‡เชกเชฒ เชซเชพเชฐเซเชฎเชฟเช‚เช— เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเซ€ เชถเช•เซเชฏเซเช‚ เชจเชฅเซ€, เชชเชฐเช‚เชคเซ เช˜เชฃเซ‹ เชฎเซ‚เชฒเซเชฏเชตเชพเชจ เช…เชจเซเชญเชต เชฎเซ‡เชณเชตเซเชฏเซ‹ เชนเชคเซ‹, เชคเซ‡เชฅเซ€ เชนเซเช‚ เชธเชฎเซเชฆเชพเชฏเชจเซ‡ เช•เชพเช—เชฒเซ‡ เช…เชจเซ‡ เชฐเซ‹เชœเชฟเช‚เชฆเชพ เช•เชพเชฎเชฎเชพเช‚ เช˜เชฃเซ€ เชฌเชงเซ€ เชฐเชธเชชเซเชฐเชฆ เช…เชจเซ‡ เช‰เชชเชฏเซ‹เช—เซ€ เชตเชธเซเชคเซเช“ เชตเชฟเชถเซ‡ เชœเชฃเชพเชตเชตเชพ เชฎเชพเช‚เช—เซ เช›เซเช‚. เชšเชฐเซเชšเชพ เช•เชฐเซ‡เชฒเชพ เชตเชฟเชทเชฏเซ‹เชฎเชพเช‚: เชตเชฟเชจเชพ เชฎเซเชถเซเช•เซ‡เชฒ เชœเซ€เชตเชจ เช“เชชเชจเชธเซ€เชตเซ€, JSON เชชเชฆเชšเซเช›เซ‡เชฆเชจ (เช† เช‰เชฆเชพเชนเชฐเชฃเซ‹ R เชฎเชพเช‚ เชธเซเช•เซเชฐเชฟเชชเซเชŸเซ‹ เช…เชฅเชตเชพ เชชเซ‡เช•เซ‡เชœเซ‹เชฎเชพเช‚ C++ เช•เซ‹เชกเชจเชพ เชเช•เซ€เช•เชฐเชฃเชจเซ€ เชคเชชเชพเชธ เช•เชฐเซ‡ เช›เซ‡. เช†เชฐเชธเซ€เชชเซ€เชชเซ€), เชธเซเช•เซเชฐเชฟเชชเซเชŸเซเชธเชจเซเช‚ เชชเซ‡เชฐเชพเชฎเซ€เชŸเชฐเชพเช‡เชเซ‡เชถเชจ เช…เชจเซ‡ เช…เช‚เชคเชฟเชฎ เชธเซ‹เชฒเซเชฏเซเชถเชจเชจเซเช‚ เชกเซ‹เช•เชฐเชพเช‡เชเซ‡เชถเชจ. เชเช•เซเชเซ‡เช•เซเชฏเซเชถเชจ เชฎเชพเชŸเซ‡ เชฏเซ‹เช—เซเชฏ เชซเซ‹เชฐเซเชฎเชฎเชพเช‚ เชฎเซ‡เชธเซ‡เชœเชฎเชพเช‚เชฅเซ€ เชคเชฎเชพเชฎ เช•เซ‹เชก เช‰เชชเชฒเชฌเซเชง เช›เซ‡ เชญเช‚เชกเชพเชฐ.

เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพ:

  1. เชฎเซ‹เชจเซ‡เชŸเชกเซ€เชฌเซ€เชฎเชพเช‚ CSVเชฎเชพเช‚เชฅเซ€ เชกเซ‡เชŸเชพเชจเซ‡ เช…เชธเชฐเช•เชพเชฐเช• เชฐเซ€เชคเซ‡ เชฒเซ‹เชก เช•เชฐเซ‹
  2. เชฌเซ‡เชš เชคเซˆเชฏเชพเชฐ เช•เชฐเซ€ เชฐเชนเซเชฏเชพ เช›เซ€เช
  3. เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚เชฅเซ€ เชฌเซ‡เชšเชจเซ‡ เช…เชจเชฒเซ‹เชก เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชชเซเชจเชฐเชพเชตเชฐเซเชคเช•เซ‹
  4. เชเช• เชฎเซ‹เชกเซ‡เชฒ เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐ เชชเชธเช‚เชฆ เช•เชฐเซ€ เชฐเชนเซเชฏเชพ เช›เซ€เช
  5. เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชชเซ‡เชฐเชพเชฎเซ€เชŸเชฐเชพเช‡เชเซ‡เชถเชจ
  6. เชธเซเช•เซเชฐเชฟเชชเซเชŸเซ‹เชจเซเช‚ เชกเซ‹เช•เชฐเชพเช‡เชเซ‡เชถเชจ
  7. Google Cloud เชชเชฐ เชฌเชนเซเชตเชฟเชง GPU เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเซ‹
  8. เชคเซ‡เชจเชพ เชฌเชฆเชฒเซ‡ เชเช• เชจเชฟเชทเซเช•เชฐเซเชท

1. เชฎเซ‹เชจเซ‡เชŸเชกเซ€เชฌเซ€ เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ CSVเชฎเชพเช‚เชฅเซ€ เชกเซ‡เชŸเชพเชจเซ‡ เช…เชธเชฐเช•เชพเชฐเช• เชฐเซ€เชคเซ‡ เชฒเซ‹เชก เช•เชฐเซ‹

เช† เชธเซเชชเชฐเซเชงเชพเชจเซ‹ เชกเซ‡เชŸเชพ เชคเซˆเชฏเชพเชฐ เชˆเชฎเซ‡เชœเชจเชพ เชฐเซ‚เชชเชฎเชพเช‚ เชจเชนเซ€เช‚, เชชเชฐเช‚เชคเซ เชชเซ‹เชˆเชจเซเชŸ เช•เซ‹เช“เชฐเซเชกเชฟเชจเซ‡เชŸเซเชธ เชธเชพเชฅเซ‡ JSON เชงเชฐเชพเชตเชคเซ€ 340 CSV เชซเชพเชˆเชฒเซ‹ (เชฆเชฐเซ‡เช• เชตเชฐเซเช— เชฎเชพเชŸเซ‡ เชเช• เชซเชพเชˆเชฒ)เชจเชพ เชฐเซ‚เชชเชฎเชพเช‚ เชชเซเชฐเชฆเชพเชจ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡. เช† เชฌเชฟเช‚เชฆเซเช“เชจเซ‡ เชฐเซ‡เช–เชพเช“ เชธเชพเชฅเซ‡ เชœเซ‹เชกเซ€เชจเซ‡, เช…เชฎเชจเซ‡ 256x256 เชชเชฟเช•เซเชธเซ‡เชฒ เชฎเชพเชชเชตเชพเชจเซ€ เช…เช‚เชคเชฟเชฎ เช›เชฌเซ€ เชฎเชณเซ‡ เช›เซ‡. เชคเซ‡เชฎเชœ เชฆเชฐเซ‡เช• เชฐเซ‡เช•เซ‹เชฐเซเชก เชฎเชพเชŸเซ‡ เชเช• เชฒเซ‡เชฌเชฒ เช›เซ‡ เชœเซ‡ เชฆเชฐเซเชถเชพเชตเซ‡ เช›เซ‡ เช•เซ‡ เชกเซ‡เชŸเชพเชธเซ‡เชŸ เชเช•เชคเซเชฐเชฟเชค เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เชคเซ‡ เชธเชฎเชฏเซ‡ เช‰เชชเชฏเซ‹เช—เชฎเชพเช‚ เชฒเซ‡เชตเชพเชคเชพ เชตเชฐเซเช—เซ€เช•เซƒเชค เชฆเซเชตเชพเชฐเชพ เชšเชฟเชคเซเชฐเชจเซ‡ เชฏเซ‹เช—เซเชฏ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซเช‚ เชนเชคเซเช‚ เช•เซ‡ เชจเชนเซ€เช‚, เชšเชฟเชคเซเชฐเชจเชพ เชฒเซ‡เช–เช•เชจเชพ เชฐเชนเซ‡เช เชพเชฃเชจเชพ เชฆเซ‡เชถเชจเซ‹ เชฌเซ‡-เช…เช•เซเชทเชฐเชจเซ‹ เช•เซ‹เชก, เชเช• เช…เชจเชจเซเชฏ เช“เชณเช–เช•เชฐเซเชคเชพ, เชŸเชพเช‡เชฎเชธเซเชŸเซ‡เชฎเซเชช. เช…เชจเซ‡ เชตเชฐเซเช—เชจเซเช‚ เชจเชพเชฎ เชœเซ‡ เชซเชพเช‡เชฒเชจเชพ เชจเชพเชฎ เชธเชพเชฅเซ‡ เชฎเซ‡เชณ เช–เชพเชฏ เช›เซ‡. เชฎเซ‚เชณ เชกเซ‡เชŸเชพเชจเชพ เชธเชฐเชณ เชธเช‚เชธเซเช•เชฐเชฃเชจเซเช‚ เชตเชœเชจ เช†เชฐเซเช•เชพเช‡เชตเชฎเชพเช‚ 7.4 GB เชนเซ‹เชฏ เช›เซ‡ เช…เชจเซ‡ เช…เชจเชชเซ‡เช• เช•เชฐเซเชฏเชพ เชชเช›เซ€ เช†เชถเชฐเซ‡ 20 GB เชนเซ‹เชฏ เช›เซ‡, เช…เชจเชชเซ…เช• เช•เชฐเซเชฏเชพ เชชเช›เซ€ เชธเช‚เชชเซ‚เชฐเซเชฃ เชกเซ‡เชŸเชพ 240 GB เชฒเซ‡ เช›เซ‡. เช†เชฏเซ‹เชœเช•เซ‹เช เชธเซเชจเชฟเชถเซเชšเชฟเชค เช•เชฐเซเชฏเซเช‚ เช•เซ‡ เชฌเช‚เชจเซ‡ เชธเช‚เชธเซเช•เชฐเชฃเซ‹ เชธเชฎเชพเชจ เชฐเซ‡เช–เชพเช‚เช•เชจเซ‹เชจเซเช‚ เชชเซเชจเชƒเช‰เชคเซเชชเชพเชฆเชจ เช•เชฐเซ‡ เช›เซ‡, เชเชŸเชฒเซ‡ เช•เซ‡ เชธเช‚เชชเซ‚เชฐเซเชฃ เชธเช‚เชธเซเช•เชฐเชฃ เชจเชฟเชฐเชฐเซเชฅเช• เชนเชคเซเช‚. เช•เซ‹เชˆ เชชเชฃ เชธเช‚เชœเซ‹เช—เซ‹เชฎเชพเช‚, เช—เซเชฐเชพเชซเชฟเช• เชซเชพเชˆเชฒเซ‹เชฎเชพเช‚ เช…เชฅเชตเชพ เชเชฐเซ‡เชจเชพ เชธเซเชตเชฐเซ‚เชชเชฎเชพเช‚ 50 เชฎเชฟเชฒเชฟเชฏเชจ เชˆเชฎเซ‡เชœเซ‹ เชธเช‚เช—เซเชฐเชนเชฟเชค เช•เชฐเชตเชพเชจเซเช‚ เชคเชฐเชค เชœ เชฌเชฟเชจเชฒเชพเชญเช•เชพเชฐเซ€ เชฎเชพเชจเชตเชพเชฎเชพเช‚ เช†เชตเชคเซเช‚ เชนเชคเซเช‚, เช…เชจเซ‡ เช…เชฎเซ‡ เช†เชฐเซเช•เชพเช‡เชตเชฎเชพเช‚เชฅเซ€ เชฌเชงเซ€ CSV เชซเชพเช‡เชฒเซ‹เชจเซ‡ เชฎเชฐเซเชœ เช•เชฐเชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเชฏเซเช‚. train_simplified.zip เชฆเชฐเซ‡เช• เชฌเซ‡เชš เชฎเชพเชŸเซ‡ "เชซเซเชฒเชพเชฏ เชชเชฐ" เชœเชฐเซ‚เชฐเซ€ เช•เชฆเชจเซ€ เช›เชฌเซ€เช“เชจเซ€ เช…เชจเซเช—เชพเชฎเซ€ เชชเซ‡เชขเซ€ เชธเชพเชฅเซ‡ เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚.

DBMS เชคเชฐเซ€เช•เซ‡ เชธเชพเชฐเซ€ เชฐเซ€เชคเซ‡ เชธเชพเชฌเชฟเชค เชธเชฟเชธเซเชŸเชฎ เชชเชธเช‚เชฆ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ€ เชนเชคเซ€ เชฎเซ‹เชจเซ‡เชŸเชกเซ€เชฌเซ€, เชเชŸเชฒเซ‡ เช•เซ‡ เชชเซ‡เช•เซ‡เชœ เชคเชฐเซ€เช•เซ‡ 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"
    )
  )
}

เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชกเซ‡เชŸเชพ เชฒเซ‹เชก เช•เชฐเชตเชพเชจเซ€ เชธเซŒเชฅเซ€ เชเชกเชชเซ€ เชฐเซ€เชค SQL - เช†เชฆเซ‡เชถเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ CSV เชซเชพเช‡เชฒเซ‹เชจเซ€ เชธเซ€เชงเซ€ เชจเช•เชฒ เช•เชฐเชตเชพเชจเซ‹ เชนเชคเซ‹ COPY OFFSET 2 INTO tablename FROM path USING DELIMITERS ',','n','"' NULL AS '' BEST EFFORTเชœเซเชฏเชพเช‚ tablename - เชŸเซ‡เชฌเชฒเชจเซเช‚ เชจเชพเชฎ เช…เชจเซ‡ path - เชซเชพเช‡เชฒเชจเซ‹ เชฎเชพเชฐเซเช—. เช†เชฐเซเช•เชพเช‡เชต เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชคเซ€ เชตเช–เชคเซ‡, เชเชตเซเช‚ เชœเชพเชฃเชตเชพ เชฎเชณเซเชฏเซเช‚ เชนเชคเซเช‚ เช•เซ‡ เชฌเชฟเชฒเซเชŸ-เช‡เชจ เช…เชฎเชฒเซ€เช•เชฐเชฃ unzip เช†เชฐ เชฎเชพเช‚ เช†เชฐเซเช•เชพเช‡เชตเชฎเชพเช‚เชฅเซ€ เชธเช‚เช–เซเชฏเชพเชฌเช‚เชง เชซเชพเช‡เชฒเซ‹ เชธเชพเชฅเซ‡ เชฏเซ‹เช—เซเชฏ เชฐเซ€เชคเซ‡ เช•เชพเชฎ เช•เชฐเชคเซเช‚ เชจเชฅเซ€, เชคเซ‡เชฅเซ€ เช…เชฎเซ‡ เชธเชฟเชธเซเชŸเชฎเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹ 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 เชจเซ€ เช…เช‚เชฆเชฐ เช…เชฅเชตเชพ เชซเซเชฒเซ‡เชถ เชกเซเชฐเชพเช‡เชต (เชธเซเชฐเซ‹เชค เชซเชพเช‡เชฒ) เชฅเซ€ SSD (DB) เชฎเชพเช‚ เชตเชพเช‚เชšเชตเชพ เช…เชจเซ‡ เชฒเช–เชตเชพเชฎเชพเช‚ 10 เชฎเชฟเชจเชฟเชŸเชฅเซ€ เช“เช›เซ‹ เชธเชฎเชฏ เชฒเชพเช—เซ‡ เช›เซ‡.

เชชเซ‚เชฐเซเชฃเชพเช‚เช• เชตเชฐเซเช— เชฒเซ‡เชฌเชฒ เช…เชจเซ‡ เช‡เชจเซเชกเซ‡เช•เซเชธ เช•เซ‰เชฒเชฎ เชธเชพเชฅเซ‡ เช•เซ‰เชฒเชฎ เชฌเชจเชพเชตเชตเชพเชฎเชพเช‚ เชฅเซ‹เชกเซ€ เชตเชงเซ เชธเซ‡เช•เชจเซเชก เชฒเชพเช—เซ‡ เช›เซ‡ (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)"))

เชซเซเชฒเชพเชฏ เชชเชฐ เชฌเซ‡เชš เชฌเชจเชพเชตเชตเชพเชจเซ€ เชธเชฎเชธเซเชฏเชพเชจเซ‡ เชนเชฒ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เช…เชฎเชพเชฐเซ‡ เชŸเซ‡เชฌเชฒเชฎเชพเช‚เชฅเซ€ เชฐเซ‡เชจเซเชกเชฎ เชชเช‚เช•เซเชคเชฟเช“ เช•เชพเชขเชตเชพเชจเซ€ เชฎเชนเชคเซเชคเชฎ เชเชกเชช เชนเชพเช‚เชธเชฒ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡. doodles. เช† เชฎเชพเชŸเซ‡ เช…เชฎเซ‡ 3 เชฏเซเช•เซเชคเชฟเช“เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹. เชชเซเชฐเชฅเชฎ เชชเซเชฐเช•เชพเชฐเชจเซเช‚ เชชเชฐเชฟเชฎเชพเชฃ เช˜เชŸเชพเชกเชตเชพเชจเซเช‚ เชนเชคเซเช‚ เชœเซ‡ เช…เชตเชฒเซ‹เช•เชจ ID เชจเซ‡ เชธเช‚เช—เซเชฐเชนเชฟเชค เช•เชฐเซ‡ เช›เซ‡. เชฎเซ‚เชณ เชกเซ‡เชŸเชพ เชธเซ‡เชŸเชฎเชพเช‚, ID เชธเซเชŸเซ‹เชฐ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชœเชฐเซ‚เชฐเซ€ เชชเซเชฐเช•เชพเชฐ เช›เซ‡ bigint, เชชเชฐเช‚เชคเซ เช…เชตเชฒเซ‹เช•เชจเซ‹เชจเซ€ เชธเช‚เช–เซเชฏเชพ เชคเซ‡เชฎเชจเชพ เช“เชณเช–เช•เชฐเซเชคเชพเช“เชจเซ‡, เช“เชฐเซเชกเชฟเชจเชฒ เชจเช‚เชฌเชฐเชจเซ€ เชธเชฎเชพเชจ, เชชเซเชฐเช•เชพเชฐเชฎเชพเช‚ เชซเชฟเชŸ เช•เชฐเชตเชพเชจเซเช‚ เชถเช•เซเชฏ เชฌเชจเชพเชตเซ‡ เช›เซ‡. int. เช† เช•เชฟเชธเซเชธเชพเชฎเชพเช‚ เชถเซ‹เชง เชตเชงเซ เชเชกเชชเซ€ เช›เซ‡. เชฌเซ€เชœเซ€ เชฏเซเช•เซเชคเชฟ เชตเชพเชชเชฐเชตเชพเชจเซ€ เชนเชคเซ€ ORDERED INDEX - เช…เชฎเซ‡ เช† เชจเชฟเชฐเซเชฃเชฏ เชชเชฐ เชชเซเชฐเชพเชฏเซ‹เช—เชฟเช• เชฐเซ€เชคเซ‡ เช†เชตเซเชฏเชพ เช›เซ€เช, เช‰เชชเชฒเชฌเซเชง เชคเชฎเชพเชฎ เชฌเชพเชฌเชคเซ‹เชฎเชพเช‚เชฅเซ€ เชชเชธเชพเชฐ เชฅเชˆเชจเซ‡ เชตเชฟเช•เชฒเซเชชเซ‹. เชคเซเชฐเซ€เชœเซเช‚ เชชเซ‡เชฐเชพเชฎเซ€เชŸเชฐเชพเช‡เชเซเชก เช•เซเชตเซ‡เชฐเซ€เชเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชจเซ‹ เชนเชคเซ‹. เชชเชฆเซเชงเชคเชฟเชจเซ‹ เชธเชพเชฐ เช เช†เชฆเซ‡เชถเชจเซ‡ เชเช•เชตเชพเชฐ เช…เชฎเชฒเชฎเชพเช‚ เชฎเซ‚เช•เชตเชพเชจเซ‹ เช›เซ‡ PREPARE เชธเชฎเชพเชจ เชชเซเชฐเช•เชพเชฐเชจเชพ เชชเซเชฐเชถเซเชจเซ‹เชจเซ‹ เชธเชฎเซ‚เชน เชฌเชจเชพเชตเชคเซ€ เชตเช–เชคเซ‡ เชคเซˆเชฏเชพเชฐ เช…เชญเชฟเชตเซเชฏเช•เซเชคเชฟเชจเชพ เช…เชจเซเช—เชพเชฎเซ€ เช‰เชชเชฏเซ‹เช— เชธเชพเชฅเซ‡, เชชเชฐเช‚เชคเซ เชตเชพเชธเซเชคเชตเชฎเชพเช‚ เชเช• เชธเชฐเชณเชจเซ€ เชคเซเชฒเชจเชพเชฎเชพเช‚ เชเช• เชซเชพเชฏเชฆเซ‹ เช›เซ‡ SELECT เช†เช‚เช•เชกเชพเช•เซ€เชฏ เชญเซ‚เชฒเชจเซ€ เชถเซเชฐเซ‡เชฃเซ€เชฎเชพเช‚ เชนเซ‹เชตเชพเชจเซเช‚ เชฌเชนเชพเชฐ เช†เชตเซเชฏเซเช‚ เช›เซ‡.

เชกเซ‡เชŸเชพ เช…เชชเชฒเซ‹เชก เช•เชฐเชตเชพเชจเซ€ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ 450 MB เชฅเซ€ เชตเชงเซ RAM เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชคเซ€ เชจเชฅเซ€. เชเชŸเชฒเซ‡ เช•เซ‡, เชตเชฐเซเชฃเชตเซ‡เชฒ เช…เชญเชฟเช—เชฎ เชคเชฎเชจเซ‡ เช•เซ‡เชŸเชฒเชพเช• เชธเชฟเช‚เช—เชฒ-เชฌเซ‹เชฐเซเชก เช‰เชชเช•เชฐเชฃเซ‹ เชธเชนเชฟเชค, เชฒเช—เชญเช— เช•เซ‹เชˆเชชเชฃ เชฌเชœเซ‡เชŸ เชนเชพเชฐเซเชกเชตเซ‡เชฐ เชชเชฐ เชฆเชธ เช—เซ€เช—เชพเชฌเชพเช‡เชŸเซเชธ เชตเชœเชจเชจเชพ เชกเซ‡เชŸเชพเชธเซ‡เชŸเซเชธเชจเซ‡ เช–เชธเซ‡เชกเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡, เชœเซ‡ เช–เซ‚เชฌ เชธเชฐเชธ เช›เซ‡.

เชœเซ‡ เชฌเชพเช•เซ€ เชฐเชนเซ‡ เช›เซ‡ เชคเซ‡ (เชฐเซ‡เชจเซเชกเชฎ) เชกเซ‡เชŸเชพ เชชเซเชจเชƒเชชเซเชฐเชพเชชเซเชค เช•เชฐเชตเชพเชจเซ€ เชเชกเชชเชจเซ‡ เชฎเชพเชชเชตเชพ เช…เชจเซ‡ เชตเชฟเชตเชฟเชง เช•เชฆเชจเชพ เชฌเซ‡เชšเชจเชพ เชจเชฎเซ‚เชจเชพ เชฒเซ‡เชคเซ€ เชตเช–เชคเซ‡ เชธเซเช•เซ‡เชฒเชฟเช‚เช—เชจเซเช‚ เชฎเซ‚เชฒเซเชฏเชพเช‚เช•เชจ เช•เชฐเชตเชพเชจเซเช‚ เช›เซ‡:

เชกเซ‡เชŸเชพเชฌเซ‡เช เชฌเซ‡เชจเซเชšเชฎเชพเชฐเซเช•

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)

เช•เซเชตเชฟเช• เชกเซเชฐเซ‹ เชกเซ‚เชกเชฒ เชฐเซ‡เช•เช—เซเชจเชฟเชถเชจ: R, C++ เช…เชจเซ‡ เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช• เชธเชพเชฅเซ‡ เชฎเชฟเชคเซเชฐเซ‹ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฌเชจเชพเชตเชตเซเช‚

2. เชฌเซ‡เชš เชคเซˆเชฏเชพเชฐ เช•เชฐเซ€ เชฐเชนเซเชฏเชพ เช›เซ€เช

เชธเชฎเช—เซเชฐ เชฌเซ‡เชš เชคเซˆเชฏเชพเชฐ เช•เชฐเชตเชพเชจเซ€ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพเชฎเชพเช‚ เชจเซ€เชšเซ‡เชจเชพ เชชเช—เชฒเชพเช‚เช“ เชถเชพเชฎเซ‡เชฒ เช›เซ‡:

  1. เชชเซ‹เชˆเชจเซเชŸเชจเชพ เช•เซ‹เช“เชฐเซเชกเชฟเชจเซ‡เชŸเซเชธ เชธเชพเชฅเซ‡ เชธเซเชŸเซเชฐเชฟเช‚เช—เซเชธเชจเชพ เชตเซ‡เช•เซเชŸเชฐ เชงเชฐเชพเชตเชคเชพ เช˜เชฃเชพ JSON เชจเซ‡ เชชเชพเชฐเซเชธเชฟเช‚เช—.
  2. เชœเชฐเซ‚เชฐเซ€ เช•เชฆเชจเซ€ เช›เชฌเซ€ เชชเชฐ เชฌเชฟเช‚เชฆเซเช“เชจเชพ เช•เซ‹เช“เชฐเซเชกเชฟเชจเซ‡เชŸเซเชธ เชชเชฐ เช†เชงเชพเชฐเชฟเชค เชฐเช‚เช—เซ€เชจ เชฐเซ‡เช–เชพเช“ เชฆเซ‹เชฐเชตเซ€ (เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, 256ร—256 เช…เชฅเชตเชพ 128ร—128).
  3. เชชเชฐเชฟเชฃเชพเชฎเซ€ เช›เชฌเซ€เช“เชจเซ‡ เชŸเซ‡เชจเซเชธเชฐเชฎเชพเช‚ เชฐเซ‚เชชเชพเช‚เชคเชฐเชฟเชค เช•เชฐเชตเซ€.

เชชเชพเชฏเชฅเซ‹เชจ เช•เชฐเซเชจเชฒเซ‹ เชตเชšเซเชšเซ‡เชจเซ€ เชธเซเชชเชฐเซเชงเชพเชจเชพ เชญเชพเช— เชฐเซ‚เชชเซ‡, เชธเชฎเชธเซเชฏเชพเชจเซ‹ เช‰เช•เซ‡เชฒ เชฎเซเช–เซเชฏเชคเซเชตเซ‡ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เชนเชคเซ‹ เช“เชชเชจเชธเซ€เชตเซ€. R เชฎเชพเช‚ เชธเซŒเชฅเซ€ เชธเชฐเชณ เช…เชจเซ‡ เชธเซŒเชฅเซ€ เชธเซเชชเชทเซเชŸ เชเชจเชพเชฒเซ‹เช— เช†เชจเชพ เชœเซ‡เชตเซ‹ เชฆเซ‡เช–เชพเชถเซ‡:

R เชฎเชพเช‚ JSON เชฅเซ€ เชŸเซ‡เชจเซเชธเชฐ เชฐเซ‚เชชเชพเช‚เชคเชฐเชฃเชจเซ‹ เช…เชฎเชฒ

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 เชธเชพเชงเชจเซ‹เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ เช…เชจเซ‡ RAM เชฎเชพเช‚ เชธเช‚เช—เซเชฐเชนเชฟเชค เช•เชพเชฎเชšเชฒเชพเช‰ PNG เชฎเชพเช‚ เชธเชพเชšเชตเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ (เชฒเชฟเชจเช•เซเชธ เชชเชฐ, เช…เชธเซเชฅเชพเชฏเซ€ R เชกเชฟเชฐเซ‡เช•เซเชŸเชฐเซ€เช“ เชกเชฟเชฐเซ‡เช•เซเชŸเชฐเซ€เชฎเชพเช‚ เชธเซเชฅเชฟเชค เช›เซ‡. /tmp, RAM เชฎเชพเช‚ เชฎเชพเช‰เชจเซเชŸ เชฅเชฏเซ‡เชฒ เช›เซ‡). เช† เชซเชพเช‡เชฒ เชชเช›เซ€ 0 เชฅเซ€ 1 เชธเซเชงเซ€เชจเซ€ เชธเช‚เช–เซเชฏเชพเช“ เชธเชพเชฅเซ‡ เชคเซเชฐเชฟ-เชชเชฐเชฟเชฎเชพเชฃเซ€เชฏ เชเชฐเซ‡ เชคเชฐเซ€เช•เซ‡ เชตเชพเช‚เชšเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡. เช† เชฎเชนเชคเซเชตเชชเซ‚เชฐเซเชฃ เช›เซ‡ เช•เชพเชฐเชฃ เช•เซ‡ เชตเชงเซ เชชเชฐเช‚เชชเชฐเชพเช—เชค BMP เชนเซ‡เช•เซเชธ เช•เชฒเชฐ เช•เซ‹เชกเซเชธ เชธเชพเชฅเซ‡ เช•เชพเชšเชพ เชเชฐเซ‡เชฎเชพเช‚ เชตเชพเช‚เชšเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡.

เชšเชพเชฒเซ‹ เชชเชฐเชฟเชฃเชพเชฎเชจเซเช‚ เชชเชฐเซ€เช•เซเชทเชฃ เช•เชฐเซ€เช:

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))

เช•เซเชตเชฟเช• เชกเซเชฐเซ‹ เชกเซ‚เชกเชฒ เชฐเซ‡เช•เช—เซเชจเชฟเชถเชจ: R, C++ เช…เชจเซ‡ เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช• เชธเชพเชฅเซ‡ เชฎเชฟเชคเซเชฐเซ‹ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฌเชจเชพเชตเชตเซเช‚

เชฌเซ‡เชš เชชเซ‹เชคเซ‡ เชจเซ€เชšเซ‡ เชชเซเชฐเชฎเชพเชฃเซ‡ เชฐเชšเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡:

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

เช† เช…เชฎเชฒเซ€เช•เชฐเชฃ เช…เชฎเชจเซ‡ เช…เชฏเซ‹เช—เซเชฏ เชฒเชพเช—เชคเซเช‚ เชนเชคเซเช‚, เช•เชพเชฐเชฃ เช•เซ‡ เชฎเซ‹เชŸเซ€ เชฌเซ‡เชšเชจเซ€ เชฐเชšเชจเชพเชฎเชพเช‚ เช…เชฏเซ‹เช—เซเชฏ เชฐเซ€เชคเซ‡ เชฒเชพเช‚เชฌเซ‹ เชธเชฎเชฏ เชฒเชพเช—เซ‡ เช›เซ‡, เช…เชจเซ‡ เช…เชฎเซ‡ เชถเช•เซเชคเชฟเชถเชพเชณเซ€ เชชเซเชธเซเชคเช•เชพเชฒเชฏเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช…เชฎเชพเชฐเชพ เชธเชพเชฅเซ€เชฆเชพเชฐเซ‹เชจเชพ เช…เชจเซเชญเชตเชจเซ‹ เชฒเชพเชญ เชฒเซ‡เชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเชฏเซเช‚. เช“เชชเชจเชธเซ€เชตเซ€. เชคเซ‡ เชธเชฎเชฏเซ‡ R เชฎเชพเชŸเซ‡ เช•เซ‹เชˆ เชคเซˆเชฏเชพเชฐ เชชเซ‡เช•เซ‡เชœ เชจเชนเซ‹เชคเซเช‚ (เชนเชตเซ‡ เช•เซ‹เชˆ เชจเชฅเซ€), เชคเซ‡เชฅเซ€ เชœเชฐเซ‚เชฐเซ€ เช•เชพเชฐเซเชฏเช•เซเชทเชฎเชคเชพเชจเซเช‚ เชจเซเชฏเซ‚เชจเชคเชฎ เช…เชฎเชฒเซ€เช•เชฐเชฃ C++ เชฎเชพเช‚ R เช•เซ‹เชกเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชเช•เซ€เช•เชฐเชฃ เชธเชพเชฅเซ‡ เชฒเช–เชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซเช‚ เชนเชคเซเช‚. เช†เชฐเชธเซ€เชชเซ€เชชเซ€.

เชธเชฎเชธเซเชฏเชพ เชนเชฒ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เชจเซ€เชšเซ‡เชจเชพ เชชเซ‡เช•เซ‡เชœเซ‹ เช…เชจเซ‡ เชชเซเชธเซเชคเช•เชพเชฒเชฏเซ‹เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เชนเชคเซ‹:

  1. เช“เชชเชจเชธเซ€เชตเซ€ เช›เชฌเซ€เช“ เช…เชจเซ‡ เชฐเซ‡เช–เชพเช‚เช•เชจ เชฐเซ‡เช–เชพเช“ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡. เชชเซเชฐเซ€-เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเซ‡เชฒเซ€ เชธเชฟเชธเซเชŸเชฎ เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€เช“ เช…เชจเซ‡ เชนเซ‡เชกเชฐ เชซเชพเช‡เชฒเซ‹ เชคเซ‡เชฎเชœ เชกเชพเชฏเชจเซ‡เชฎเชฟเช• เชฒเชฟเช‚เช•เชฟเช‚เช—เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹.

  2. xtensor เชฌเชนเซเชชเชฐเซ€เชฎเชพเชฃเซ€เชฏ เชเชฐเซ‡ เช…เชจเซ‡ เชŸเซ‡เชจเซเชธเชฐเซเชธ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡. เช…เชฎเซ‡ เชธเชฎเชพเชจ เชจเชพเชฎเชจเชพ R เชชเซ‡เช•เซ‡เชœเชฎเชพเช‚ เชธเชฎเชพเชตเชฟเชทเซเชŸ เชนเซ‡เชกเชฐ เชซเชพเช‡เชฒเซ‹เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹ เช›เซ‡. เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€ เชคเชฎเชจเซ‡ เชฌเชนเซเชชเชฐเซ€เชฎเชพเชฃเซ€เชฏ เชเชฐเซ‡ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพเชจเซ€ เชชเชฐเชตเชพเชจเช—เซ€ เช†เชชเซ‡ เช›เซ‡, เชฌเช‚เชจเซ‡ เชชเช‚เช•เซเชคเชฟ เชฎเซเช–เซเชฏ เช…เชจเซ‡ เช•เซ‰เชฒเชฎ เชฎเซเช–เซเชฏ เช•เซเชฐเชฎเชฎเชพเช‚.

  3. ndjson JSON เชชเชฆเชšเซเช›เซ‡เชฆเชจ เชฎเชพเชŸเซ‡. เช† เชชเซเชธเซเชคเช•เชพเชฒเชฏเชจเซ‹ เช‰เชชเชฏเซ‹เช— เชฎเชพเช‚ เชฅเชพเชฏ เช›เซ‡ xtensor เชœเซ‹ เชคเซ‡ เชชเซเชฐเซ‹เชœเซ‡เช•เซเชŸเชฎเชพเช‚ เชนเชพเชœเชฐ เชนเซ‹เชฏ เชคเซ‹ เช†เชชเซ‹เช†เชช.

  4. RcppThread JSON เชคเชฐเชซเชฅเซ€ เชตเซ‡เช•เซเชŸเชฐเชจเซ€ เชฎเชฒเซเชŸเชฟ-เชฅเซเชฐเซ‡เชกเซ‡เชก เชชเซเชฐเซ‹เชธเซ‡เชธเชฟเช‚เช— เช—เซ‹เช เชตเชตเชพ เชฎเชพเชŸเซ‡. เช† เชชเซ‡เช•เซ‡เชœ เชฆเซเชตเชพเชฐเชพ เชชเซ‚เชฐเซ€ เชชเชพเชกเชตเชพเชฎเชพเช‚ เช†เชตเซ‡เชฒ เชนเซ‡เชกเชฐ เชซเชพเช‡เชฒเซ‹เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹. เชตเชงเซ เชฒเซ‹เช•เชชเซเชฐเชฟเชฏ เชฅเซ€ Rcpp เชธเชฎเชพเช‚เชคเชฐ เชชเซ‡เช•เซ‡เชœ, เช…เชจเซเชฏ เชตเชธเซเชคเซเช“เชจเซ€ เชธเชพเชฅเซ‡, เชฌเชฟเชฒเซเชŸ-เช‡เชจ เชฒเซ‚เชช เช‡เชจเซเชŸเชฐเชชเซเชŸ เชฎเชฟเช•เซ‡เชจเชฟเชเชฎ เชงเชฐเชพเชตเซ‡ เช›เซ‡.

เชคเซ‡ เชจเซ‹เช‚เชงเชตเซเช‚ เชตเชฐเซเชฅ เช›เซ‡ เช•เซ‡ xtensor เชเช• เช—เซ‹เชกเชธเซ‡เชจเซเชก เชนเซ‹เชตเชพเชจเซเช‚ เชฌเชนเชพเชฐ เช†เชตเซเชฏเซเช‚: เชนเช•เซ€เช•เชค เช เช›เซ‡ เช•เซ‡ เชคเซ‡เชจเซ€ เชชเชพเชธเซ‡ เชตเซเชฏเชพเชชเช• เช•เชพเชฐเซเชฏเช•เซเชทเชฎเชคเชพ เช…เชจเซ‡ เช‰เชšเซเชš เชชเซเชฐเชฆเชฐเซเชถเชจ เช›เซ‡, เชคเซ‡เชจเชพ เชตเชฟเช•เชพเชธเช•เชฐเซเชคเชพเช“ เชคเชฆเซเชฆเชจ เชชเซเชฐเชคเชฟเชญเชพเชตเชถเซ€เชฒ เชนเซ‹เชตเชพเชจเซเช‚ เชฌเชนเชพเชฐ เช†เชตเซเชฏเซเช‚ เช›เซ‡ เช…เชจเซ‡ เชชเซเชฐเชถเซเชจเซ‹เชจเชพ เชคเชฐเชค เช…เชจเซ‡ เชตเชฟเช—เชคเชตเชพเชฐ เชœเชตเชพเชฌเซ‹ เช†เชชเซเชฏเชพ เช›เซ‡. เชคเซ‡เชฎเชจเซ€ เชฎเชฆเชฆเชฅเซ€, เช“เชชเชจเชธเซ€เชตเซ€ เชฎเซ‡เชŸเซเชฐเชฟเชธเซ€เชธเชจเชพ เชเช•เซเชธเชŸเซ‡เชจเซเชธเชฐ เชŸเซ‡เชจเซเชธเชฐเชฎเชพเช‚ เชฐเซ‚เชชเชพเช‚เชคเชฐเชฃเชจเซ‡ เช…เชฎเชฒเชฎเชพเช‚ เชฎเซ‚เช•เชตเซเช‚ เชถเช•เซเชฏ เชนเชคเซเช‚, เชคเซ‡เชฎเชœ 3-เชชเชฐเชฟเชฎเชพเชฃเซ€เชฏ เช‡เชฎเซ‡เชœ เชŸเซ‡เชจเซเชธเชฐเชจเซ‡ เชฏเซ‹เช—เซเชฏ เชชเชฐเชฟเชฎเชพเชฃ (เชฌเซ‡เชš เชชเซ‹เชคเซ‡) เชจเชพ 4-เชชเชฐเชฟเชฎเชพเชฃเซ€เชฏ เชŸเซ‡เชจเซเชธเชฐเชฎเชพเช‚ เชœเซ‹เชกเชตเชพเชจเซ€ เชฐเซ€เชค.

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

เชธเชฟเชธเซเชŸเชฎ เชซเชพเช‡เชฒเซ‹ เช…เชจเซ‡ เชธเชฟเชธเซเชŸเชฎ เชชเชฐ เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเซ‡เชฒเซ€ เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€เช“ เชธเชพเชฅเซ‡ เชกเชพเชฏเชจเซ‡เชฎเชฟเช• เชฒเชฟเช‚เช•เชฟเช‚เช—เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชคเซ€ เชซเชพเช‡เชฒเซ‹เชจเซ‡ เช•เชฎเซเชชเชพเช‡เชฒ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เช…เชฎเซ‡ เชชเซ‡เช•เซ‡เชœเชฎเชพเช‚ เช…เชฎเชฒเชฎเชพเช‚ เชฎเซ‚เช•เชพเชฏเซ‡เชฒ เชชเซเชฒเช—เช‡เชจ เชฎเชฟเช•เซ‡เชจเชฟเชเชฎเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹. เช†เชฐเชธเซ€เชชเซ€เชชเซ€. เช†เชชเชฎเซ‡เชณเซ‡ เชชเชพเชฅ เช…เชจเซ‡ เชซเซเชฒเซ‡เช—เซเชธ เชถเซ‹เชงเชตเชพ เชฎเชพเชŸเซ‡, เช…เชฎเซ‡ เชเช• เชฒเซ‹เช•เชชเซเชฐเชฟเชฏ Linux เช‰เชชเชฏเซ‹เช—เชฟเชคเชพเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹ เช›เซ‡ pkg-config.

OpenCV เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ Rcpp เชชเซเชฒเช—เช‡เชจเชจเซเช‚ เช…เชฎเชฒเซ€เช•เชฐเชฃ

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)
  ))
})

เชชเซเชฒเช—เช‡เชจเชจเซ€ เช•เชพเชฎเช—เซ€เชฐเซ€เชจเชพ เชชเชฐเชฟเชฃเชพเชฎเซ‡, เชจเซ€เชšเซ‡เชจเชพ เชฎเซ‚เชฒเซเชฏเซ‹ เชธเช‚เช•เชฒเชจ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เชฆเชฐเชฎเชฟเชฏเชพเชจ เชฌเชฆเชฒเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡:

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 เชจเซ‡ เชชเชพเชฐเซเชธ เช•เชฐเชตเชพ เช…เชจเซ‡ เชฎเซ‹เชกเซ‡เชฒเชฎเชพเช‚ เชŸเซเชฐเชพเชจเซเชธเชฎเชฟเชถเชจ เชฎเชพเชŸเซ‡ เชฌเซ‡เชš เชœเชจเชฐเซ‡เชŸ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡เชจเซ‹ เช…เชฎเชฒเซ€เช•เชฐเชฃ เช•เซ‹เชก เชธเซเชชเซ‹เชˆเชฒเชฐ เชนเซ‡เช เชณ เช†เชชเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เช›เซ‡. เชชเซเชฐเชฅเชฎ, เชนเซ‡เชกเชฐ เชซเชพเช‡เชฒเซ‹ เชถเซ‹เชงเชตเชพ เชฎเชพเชŸเซ‡ เชธเซเชฅเชพเชจเชฟเช• เชชเซเชฐเซ‹เชœเซ‡เช•เซเชŸ เชกเชฟเชฐเซ‡เช•เซเชŸเชฐเซ€ เช‰เชฎเซ‡เชฐเซ‹ (ndjson เชฎเชพเชŸเซ‡ เชœเชฐเซ‚เชฐเซ€):

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

C++ เชฎเชพเช‚ เชŸเซ‡เชจเซเชธเชฐ เชฐเซ‚เชชเชพเช‚เชคเชฐเชฃ เชฎเชพเชŸเซ‡ JSON เชจเซ‹ เช…เชฎเชฒ

// [[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 - เช‡เชฎเซ‡เชœ เชฎเซ‡เชŸเซเชฐเชฟเช•เซเชธเชจเซ‡ เชฐเซ‚เชชเชพเช‚เชคเชฐเชฟเชค เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชเช• เชŸเซ‡เชฎเซเชชเชฒเซ‡เชŸเซ‡เชก เช•เชพเชฐเซเชฏ (cv::Mat) เชเช• เชŸเซ‡เชจเซเชธเชฐ เชฎเชพเชŸเซ‡ xt::xtensor;

  • parse_json โ€” เชซเช‚เช•เซเชถเชจ JSON เชธเซเชŸเซเชฐเชฟเช‚เช—เชจเซ‡ เชชเชพเชฐเซเชธ เช•เชฐเซ‡ เช›เซ‡, เชชเซ‹เชˆเชจเซเชŸเชจเชพ เช•เซ‹เช“เชฐเซเชกเชฟเชจเซ‡เชŸเซเชธเชจเซ‡ เชฌเชนเชพเชฐ เช•เชพเชขเซ‡ เช›เซ‡, เชคเซ‡เชฎเชจเซ‡ เชตเซ‡เช•เซเชŸเชฐเชฎเชพเช‚ เชชเซ‡เช• เช•เชฐเซ‡ เช›เซ‡;

  • ocv_draw_lines - เชฌเชฟเช‚เชฆเซเช“เชจเชพ เชชเชฐเชฟเชฃเชพเชฎเซ€ เชตเซ‡เช•เซเชŸเชฐเชฎเชพเช‚เชฅเซ€, เชฌเชนเซ เชฐเช‚เช—เซ€เชจ เชฐเซ‡เช–เชพเช“ เชฆเซ‹เชฐเซ‡ เช›เซ‡;

  • process โ€” เช‰เชชเชฐเซ‹เช•เซเชค เช•เชพเชฐเซเชฏเซ‹เชจเซ‡ เชœเซ‹เชกเซ‡ เช›เซ‡ เช…เชจเซ‡ เชชเชฐเชฟเชฃเชพเชฎเซ€ เช›เชฌเซ€เชจเซ‡ เชฎเชพเชชเชตเชพเชจเซ€ เช•เซเชทเชฎเชคเชพ เชชเชฃ เช‰เชฎเซ‡เชฐเซ‡ เช›เซ‡;

  • cpp_process_json_str - เช•เชพเชฐเซเชฏ เชชเชฐ เช†เชตเชฐเชฃ process, เชœเซ‡ เชชเชฐเชฟเชฃเชพเชฎเชจเซ‡ เช†เชฐ-เช“เชฌเซเชœเซ‡เช•เซเชŸ (เชฌเชนเซเชชเชฐเชฟเชฎเชพเชฃเซ€เชฏ เชเชฐเซ‡) เชชเชฐ เชจเชฟเช•เชพเชธ เช•เชฐเซ‡ เช›เซ‡;

  • cpp_process_json_vector - เช•เชพเชฐเซเชฏ เชชเชฐ เช†เชตเชฐเชฃ cpp_process_json_str, เชœเซ‡ เชคเชฎเชจเซ‡ เชฎเชฒเซเชŸเซ€-เชฅเซเชฐเซ‡เชกเซ‡เชก เชฎเซ‹เชกเชฎเชพเช‚ เชธเซเชŸเซเชฐเชฟเช‚เช— เชตเซ‡เช•เซเชŸเชฐ เชชเชฐ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡.

เชฌเชนเซ เชฐเช‚เช—เซ€เชจ เชฐเซ‡เช–เชพเช“ เชฆเซ‹เชฐเชตเชพ เชฎเชพเชŸเซ‡, HSV เชฐเช‚เช— เชฎเซ‹เชกเซ‡เชฒเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เชนเชคเซ‹, เชคเซเชฏเชพเชฐเชฌเชพเชฆ RGB เชฎเชพเช‚ เชฐเซ‚เชชเชพเช‚เชคเชฐ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซเช‚ เชนเชคเซเช‚. เชšเชพเชฒเซ‹ เชชเชฐเชฟเชฃเชพเชฎเชจเซเช‚ เชชเชฐเซ€เช•เซเชทเชฃ เช•เชฐเซ€เช:

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

เช•เซเชตเชฟเช• เชกเซเชฐเซ‹ เชกเซ‚เชกเชฒ เชฐเซ‡เช•เช—เซเชจเชฟเชถเชจ: R, C++ เช…เชจเซ‡ เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช• เชธเชพเชฅเซ‡ เชฎเชฟเชคเซเชฐเซ‹ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฌเชจเชพเชตเชตเซเช‚
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") 

เช•เซเชตเชฟเช• เชกเซเชฐเซ‹ เชกเซ‚เชกเชฒ เชฐเซ‡เช•เช—เซเชจเชฟเชถเชจ: R, C++ เช…เชจเซ‡ เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช• เชธเชพเชฅเซ‡ เชฎเชฟเชคเซเชฐเซ‹ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฌเชจเชพเชตเชตเซเช‚

เชœเซ‡เชฎ เชคเชฎเซ‡ เชœเซ‹เชˆ เชถเช•เซ‹ เช›เซ‹, เชเชกเชช เชตเชงเชพเชฐเซ‹ เช–เซ‚เชฌ เชœ เชจเซ‹เช‚เชงเชชเชพเชคเซเชฐ เชนเซ‹เชตเชพเชจเซเช‚ เชฌเชนเชพเชฐ เช†เชตเซเชฏเซเช‚ เช›เซ‡, เช…เชจเซ‡ R เช•เซ‹เชกเชจเซ‡ เชธเชฎเชพเช‚เชคเชฐ เช•เชฐเซ€เชจเซ‡ C++ เช•เซ‹เชก เชธเชพเชฅเซ‡ เชชเช•เชกเชตเซเช‚ เชถเช•เซเชฏ เชจเชฅเซ€.

3. เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚เชฅเซ€ เชฌเซ‡เชšเชจเซ‡ เช…เชจเชฒเซ‹เชก เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เช‡เชŸเชฐเซ‡เชŸเชฐเซเชธ

R เช RAM เชฎเชพเช‚ เชฌเช‚เชงเชฌเซ‡เชธเชคเชพ เชกเซ‡เชŸเชพเชจเซ€ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชธเชพเชฐเซ€ เชฐเซ€เชคเซ‡ เชฒเชพเชฏเช• เชชเซเชฐเชคเชฟเชทเซเช เชพ เชงเชฐเชพเชตเซ‡ เช›เซ‡, เชœเซเชฏเชพเชฐเซ‡ Python เช เชชเซเชจเชฐเชพเชตเชฐเซเชคเชฟเชค เชกเซ‡เชŸเชพ เชชเซเชฐเซ‹เชธเซ‡เชธเชฟเช‚เช— เชฆเซเชตเชพเชฐเชพ เชตเชงเซ เชฒเชพเช•เซเชทเชฃเชฟเช•เชคเชพ เชงเชฐเชพเชตเซ‡ เช›เซ‡, เชœเซ‡ เชคเชฎเชจเซ‡ เช†เช‰เชŸ-เช“เชซ-เช•เซ‹เชฐ เช—เชฃเชคเชฐเซ€เช“ (เชฌเชพเชนเซเชฏ เชฎเซ‡เชฎเชฐเซ€เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช—เชฃเชคเชฐเซ€เช“) เชธเชฐเชณเชคเชพเชฅเซ€ เช…เชจเซ‡ เช•เซเชฆเชฐเชคเซ€ เชฐเซ€เชคเซ‡ เช…เชฎเชฒเชฎเชพเช‚ เชฎเซ‚เช•เชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡. เชตเชฐเซเชฃเชตเซ‡เชฒ เชธเชฎเชธเซเชฏเชพเชจเชพ เชธเช‚เชฆเชฐเซเชญเชฎเชพเช‚ เช…เชฎเชพเชฐเชพ เชฎเชพเชŸเซ‡ เช•เซเชฒเชพเชธเชฟเช• เช…เชจเซ‡ เชธเซเชธเช‚เช—เชค เช‰เชฆเชพเชนเชฐเชฃ เช เชกเซ€เชช เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช•เซเชธ เช›เซ‡ เชœเซ‡ เช—เซเชฐเซ‡เชกเชฟเชฏเชจเซเชŸ เชกเชฟเชธเซ‡เชจเซเชŸ เชชเชฆเซเชงเชคเชฟ เชฆเซเชตเชพเชฐเชพ เชชเซเชฐเชถเชฟเช•เซเชทเชฟเชค เช›เซ‡ เช…เชจเซ‡ เชฆเชฐเซ‡เช• เชชเช—เชฒเชพ เชชเชฐ เช…เชตเชฒเซ‹เช•เชจเซ‹เชจเชพ เชจเชพเชจเชพ เชญเชพเช— เช…เชฅเชตเชพ เชฎเซ€เชจเซ€-เชฌเซ‡เชšเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช—เซเชฐเซ‡เชกเชฟเชฏเชจเซเชŸเชจเชพ เช…เช‚เชฆเชพเชœ เชธเชพเชฅเซ‡.

เชชเชพเชฏเชฅเซ‹เชจเชฎเชพเช‚ เชฒเช–เซ‡เชฒเชพ เชกเซ€เชช เชฒเชฐเซเชจเชฟเช‚เช— เชซเซเชฐเซ‡เชฎเชตเชฐเซเช•เชฎเชพเช‚ เชตเชฟเชถเชฟเชทเซเชŸ เชตเชฐเซเช—เซ‹ เชนเซ‹เชฏ เช›เซ‡ เชœเซ‡ เชกเซ‡เชŸเชพเชจเชพ เช†เชงเชพเชฐเซ‡ เชชเซเชจเชฐเชพเชตเชฐเซเชคเช•เซ‹เชจเซ‡ เช…เชฎเชฒเชฎเชพเช‚ เชฎเซ‚เช•เซ‡ เช›เซ‡: เช•เซ‹เชทเซเชŸเช•เซ‹, เชซเซ‹เชฒเซเชกเชฐเซเชธเชฎเชพเช‚ เชšเชฟเชคเซเชฐเซ‹, เชฌเชพเชˆเชจเชฐเซ€ เชซเซ‹เชฐเซเชฎเซ‡เชŸเซเชธ เชตเช—เซ‡เชฐเซ‡. เชคเชฎเซ‡ เชšเซ‹เช•เซเช•เชธ เช•เชพเชฐเซเชฏเซ‹ เชฎเชพเชŸเซ‡ เชคเซˆเชฏเชพเชฐ เชตเชฟเช•เชฒเซเชชเซ‹เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹ เช…เชฅเชตเชพ เชคเชฎเชพเชฐเชพ เชชเซ‹เชคเชพเชจเชพ เชฒเช–เซ€ เชถเช•เซ‹ เช›เซ‹. R เชฎเชพเช‚ เช†เชชเชฃเซ‡ Python เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€เชจเซ€ เชคเชฎเชพเชฎ เชธเซเชตเชฟเชงเชพเช“เชจเซ‹ เชฒเชพเชญ เชฒเชˆ เชถเช•เซ€เช เช›เซ€เช เช•เซ‡เชฐเชพ เชธเชฎเชพเชจ เชจเชพเชฎเชจเชพ เชชเซ‡เช•เซ‡เชœเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชคเซ‡เชจเชพ เชตเชฟเชตเชฟเชง เชฌเซ‡เช•เชเชจเซเชก เชธเชพเชฅเซ‡, เชœเซ‡ เชฌเชฆเชฒเชพเชฎเชพเช‚ เชชเซ‡เช•เซ‡เชœเชจเซ€ เชŸเซ‹เชš เชชเชฐ เช•เชพเชฎ เช•เชฐเซ‡ เช›เซ‡ เชœเชพเชณเซ€เชฆเชพเชฐ. เชฌเชพเชฆเชฎเชพเช‚ เชเช• เช…เชฒเช— เชฒเชพเช‚เชฌเชพ เชฒเซ‡เช–เชจเซ‡ เชชเชพเชคเซเชฐ เช›เซ‡; เชคเซ‡ เชฎเชพเชคเซเชฐ เชคเชฎเชจเซ‡ R เชฅเซ€ Python เช•เซ‹เชก เชšเชฒเชพเชตเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเชคเซเช‚ เชจเชฅเซ€, เชชเชฃ เชคเชฎเชจเซ‡ R เช…เชจเซ‡ Python เชธเชคเซเชฐเซ‹ เชตเชšเซเชšเซ‡ เช‘เชฌเซเชœเซ‡เช•เซเชŸเซเชธ เชธเซเชฅเชพเชจเชพเช‚เชคเชฐเชฟเชค เช•เชฐเชตเชพเชจเซ€ เชชเชฃ เชชเชฐเชตเชพเชจเช—เซ€ เช†เชชเซ‡ เช›เซ‡, เช†เชชเชฎเซ‡เชณเซ‡ เชคเชฎเชพเชฎ เชœเชฐเซ‚เชฐเซ€ เชชเซเชฐเช•เชพเชฐเชจเชพ เชฐเซ‚เชชเชพเช‚เชคเชฐเชฃเซ‹ เช•เชฐเซ‡ เช›เซ‡.

เช…เชฎเซ‡ MonetDBLite เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชคเชฎเชพเชฎ เชกเซ‡เชŸเชพเชจเซ‡ RAM เชฎเชพเช‚ เชธเช‚เช—เซเชฐเชนเชฟเชค เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐเชฟเชฏเชพเชคเชฎเชพเช‚เชฅเซ€ เช›เซเชŸเช•เชพเชฐเซ‹ เชฎเซ‡เชณเชตเซเชฏเซ‹, เชฌเชงเชพ "เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช•" เช•เชพเชฐเซเชฏ เชชเชพเชฏเชฅเซ‹เชจเชฎเชพเช‚ เชฎเซ‚เชณ เช•เซ‹เชก เชฆเซเชตเชพเชฐเชพ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡, เช…เชฎเชพเชฐเซ‡ เชซเช•เซเชค เชกเซ‡เชŸเชพ เชชเชฐ เชเช• เชชเซเชจเชฐเชพเชตเชฐเซเชคเชจ เชฒเช–เชตเชพเชจเซเช‚ เช›เซ‡, เช•เชพเชฐเชฃ เช•เซ‡ เชคเซเชฏเชพเช‚ เช•เช‚เชˆ เชคเซˆเชฏเชพเชฐ เชจเชฅเซ€. R เช…เชฅเชตเชพ Python เชฎเชพเช‚ เช†เชตเซ€ เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟ เชฎเชพเชŸเซ‡. เชคเซ‡เชจเชพ เชฎเชพเชŸเซ‡ เช…เชจเชฟเชตเชพเชฐเซเชฏเชชเชฃเซ‡ เชฎเชพเชคเซเชฐ เชฌเซ‡ เช†เชตเชถเซเชฏเช•เชคเชพเช“ เช›เซ‡: เชคเซ‡เชฃเซ‡ เช…เชจเช‚เชค เชฒเซ‚เชชเชฎเชพเช‚ เชฌเซ‡เชš เชชเชฐเชค เช•เชฐเชตเชพ เชœเซ‹เชˆเช เช…เชจเซ‡ เชคเซ‡เชจเซ€ เชธเซเชฅเชฟเชคเชฟเชจเซ‡ เชชเซเชจเชฐเชพเชตเซƒเชคเซเชคเชฟเช“ เชตเชšเซเชšเซ‡ เชธเชพเชšเชตเชตเซ€ เชœเซ‹เชˆเช (R เชฎเชพเช‚ เชฌเชพเชฆเชฎเชพเช‚ เชฌเช‚เชงเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชธเชฐเชณ เชฐเซ€เชคเซ‡ เช…เชฎเชฒเชฎเชพเช‚ เชฎเซ‚เช•เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡). เช…เช—เชพเช‰, เช†เชฐ เชเชฐเซ‡เชจเซ‡ เชชเซเชจเชฐเชพเชตเชฐเซเชคเช•เชจเซ€ เช…เช‚เชฆเชฐ เชจเชฎเซเชชเซ€ เชเชฐเซ‡เชฎเชพเช‚ เชธเซเชชเชทเซเชŸเชชเชฃเซ‡ เชฐเซ‚เชชเชพเช‚เชคเชฐเชฟเชค เช•เชฐเชตเซเช‚ เชœเชฐเซ‚เชฐเซ€ เชนเชคเซเช‚, เชชเชฐเช‚เชคเซ เชชเซ‡เช•เซ‡เชœเชจเซเช‚ เชตเชฐเซเชคเชฎเชพเชจ เชธเช‚เชธเซเช•เชฐเชฃ เช•เซ‡เชฐเชพ เชคเซ‡ เชชเซ‹เชคเซ‡ เช•เชฐเซ‡ เช›เซ‡.

เชคเชพเชฒเซ€เชฎ เช…เชจเซ‡ เชฎเชพเชจเซเชฏเชคเชพ เชกเซ‡เชŸเชพ เชฎเชพเชŸเซ‡ เชชเซเชจเชฐเชพเชตเชฐเซเชคเช• เชจเซ€เชšเซ‡ เชฎเซเชœเชฌ เชฌเชนเชพเชฐ เช†เชตเซเชฏเซเช‚:

เชคเชพเชฒเซ€เชฎ เช…เชจเซ‡ เชฎเชพเชจเซเชฏเชคเชพ เชกเซ‡เชŸเชพ เชฎเชพเชŸเซ‡ เช‡เชŸเชฐเชฐเซ‡เชŸเชฐ

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)
  }
}

เชซเช‚เช•เซเชถเชจ เชกเซ‡เชŸเชพเชฌเซ‡เช เชธเชพเชฅเซ‡ เช•เชจเซ‡เช•เซเชถเชจ เชธเชพเชฅเซ‡ เชšเชฒเชจเซ‡ เช‡เชจเชชเซเชŸ เชคเชฐเซ€เช•เซ‡ เชฒเซ‡ เช›เซ‡, เชตเชชเชฐเชพเชฏเซ‡เชฒเซ€ เชฐเซ‡เช–เชพเช“เชจเซ€ เชธเช‚เช–เซเชฏเชพ, เชตเชฐเซเช—เซ‹เชจเซ€ เชธเช‚เช–เซเชฏเชพ, เชฌเซ‡เชšเชจเซเช‚ เช•เชฆ, เชธเซเช•เซ‡เชฒ (scale = 1 256x256 เชชเชฟเช•เซเชธเซ‡เชฒเชจเซ€ เชฐเซ‡เชจเซเชกเชฐเซ€เช‚เช— เชˆเชฎเซ‡เชœเซ‹เชจเซ‡ เช…เชจเซเชฐเซ‚เชช เช›เซ‡, scale = 0.5 โ€” 128x128 เชชเชฟเช•เซเชธเซ‡เชฒเซเชธ), เชฐเช‚เช— เชธเซ‚เชšเช• (color = FALSE เชœเซเชฏเชพเชฐเซ‡ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เชคเซเชฏเชพเชฐเซ‡ เช—เซเชฐเซ‡เชธเซเช•เซ‡เชฒเชฎเชพเช‚ เชฐเซ‡เชจเซเชกเชฐเซ€เช‚เช—เชจเซ‹ เช‰เชฒเซเชฒเซ‡เช– เช•เชฐเซ‡ เช›เซ‡ color = TRUE เชฆเชฐเซ‡เช• เชธเซเชŸเซเชฐเซ‹เช• เชจเชตเชพ เชฐเช‚เช—เชฎเชพเช‚ เชฆเซ‹เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡) เช…เชจเซ‡ เช‡เชฎเซ‡เชœเชจเซ‡เชŸ เชชเชฐ เชชเซ‚เชฐเซเชต เชชเซเชฐเชถเชฟเช•เซเชทเชฟเชค เชจเซ‡เชŸเชตเชฐเซเช•เซเชธ เชฎเชพเชŸเซ‡ เชชเซเชฐเซ€-เชชเซเชฐเซ‹เชธเซ‡เชธเชฟเช‚เช— เชธเซ‚เชšเช•. เช…เช‚เชคเชฐเชพเชฒ [0, 1] เชฅเซ€ เช…เช‚เชคเชฐเชพเชฒ [-1, 1] เชธเซเชงเซ€ เชชเชฟเช•เซเชธเซ‡เชฒ เชฎเซ‚เชฒเซเชฏเซ‹เชจเซ‡ เชธเซเช•เซ‡เชฒ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชฌเชพเชฆเชฎเชพเช‚ เชœเชฐเซ‚เชฐเซ€ เช›เซ‡, เชœเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เชธเชชเซเชฒเชพเชฏ เช•เชฐเซ‡เชฒเชจเซ‡ เชคเชพเชฒเซ€เชฎ เช†เชชเชคเซ€ เชตเช–เชคเซ‡ เชฅเชคเซ‹ เชนเชคเซ‹. เช•เซ‡เชฐเชพ เชฎเซ‹เชกเซ‡เชฒเซ‹

เชฌเชพเชนเซเชฏ เช•เชพเชฐเซเชฏเชฎเชพเช‚ เชฆเชฒเซ€เชฒ เชชเซเชฐเช•เชพเชฐ เชšเช•เชพเชธเชฃเซ€, เชเช• เชŸเซ‡เชฌเชฒ เช›เซ‡ data.table เชฅเซ€ เชฐเซ‡เชจเซเชกเชฎเชฒเซ€ เชฎเชฟเชถเซเชฐเชฟเชค เชฐเซ‡เช–เชพ เชจเช‚เชฌเชฐเซ‹ เชธเชพเชฅเซ‡ samples_index เช…เชจเซ‡ เชฌเซ‡เชš เชจเช‚เชฌเชฐเซ‹, เช•เชพเช‰เชจเซเชŸเชฐ เช…เชจเซ‡ เชฌเซ‡เชšเชจเซ€ เชฎเชนเชคเซเชคเชฎ เชธเช‚เช–เซเชฏเชพ, เชคเซ‡เชฎเชœ เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚เชฅเซ€ เชกเซ‡เชŸเชพ เช…เชจเชฒเซ‹เชก เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชเชธเช•เซเชฏเซเชเชฒ เชเช•เซเชธเชชเซเชฐเซ‡เชถเชจ. เชตเชงเซเชฎเชพเช‚, เช…เชฎเซ‡ เช…เช‚เชฆเชฐเชจเชพ เช•เชพเชฐเซเชฏเชจเซเช‚ เชเชกเชชเซ€ เชเชจเชพเชฒเซ‹เช— เชตเซเชฏเชพเช–เซเชฏเชพเชฏเชฟเชค เช•เชฐเซเชฏเซเช‚ เช›เซ‡ keras::to_categorical(). เช…เชฎเซ‡ เชคเชพเชฒเซ€เชฎ เชฎเชพเชŸเซ‡ เชฒเช—เชญเช— เชคเชฎเชพเชฎ เชกเซ‡เชŸเชพเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹, เชฎเชพเชจเซเชฏเชคเชพ เชฎเชพเชŸเซ‡ เช…เชกเชงเซ‹ เชŸเช•เชพ เช›เซ‹เชกเซ€ เชฆเซ€เชงเซ‹, เชคเซ‡เชฅเซ€ เชฏเซเช—เชจเซเช‚ เช•เชฆ เชชเชฐเชฟเชฎเชพเชฃ เชฆเซเชตเชพเชฐเชพ เชฎเชฐเซเชฏเชพเชฆเชฟเชค เชนเชคเซเช‚ steps_per_epoch เชœเซเชฏเชพเชฐเซ‡ เชฌเซ‹เชฒเชพเชตเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ keras::fit_generator(), เช…เชจเซ‡ เชธเซเชฅเชฟเชคเชฟ if (i > max_i) เชฎเชพเชคเซเชฐ เชฎเชพเชจเซเชฏเชคเชพ เชชเซเชจเชฐเชพเชตเชฐเซเชคเช• เชฎเชพเชŸเซ‡ เช•เชพเชฎ เช•เชฐเซเชฏเซเช‚.

เช†เช‚เชคเชฐเชฟเช• เช•เชพเชฐเซเชฏเชฎเชพเช‚, เช†เช—เชพเชฎเซ€ เชฌเซ‡เชš เชฎเชพเชŸเซ‡ เชชเช‚เช•เซเชคเชฟ เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพเช“ เชชเซเชจเชƒเชชเซเชฐเชพเชชเซเชค เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เชฌเซ‡เชš เช•เชพเช‰เชจเซเชŸเชฐ เชตเชงเชตเชพ เชธเชพเชฅเซ‡ เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚เชฅเซ€ เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธ เช…เชจเชฒเซ‹เชก เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, JSON เชชเชพเชฐเซเชธเชฟเช‚เช— (เช•เชพเชฐเซเชฏ cpp_process_json_vector(), C++) เชฎเชพเช‚ เชฒเช–เชพเชฏเซ‡เชฒ เช›เซ‡ เช…เชจเซ‡ เชšเชฟเชคเซเชฐเซ‹เชจเซ‡ เช…เชจเซเชฐเซ‚เชช เชเชฐเซ‡ เชฌเชจเชพเชตเซ‡ เช›เซ‡. เชชเช›เซ€ เชตเชฐเซเช— เชฒเซ‡เชฌเชฒเซเชธ เชธเชพเชฅเซ‡ เชตเชจ-เชนเซ‹เชŸ เชตเซ‡เช•เซเชŸเชฐ เชฌเชจเชพเชตเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เชชเชฟเช•เซเชธเซ‡เชฒ เชฎเซ‚เชฒเซเชฏเซ‹ เช…เชจเซ‡ เชฒเซ‡เชฌเชฒเซเชธ เชธเชพเชฅเซ‡เชจเชพ เชเชฐเซ‡เชจเซ‡ เชธเซ‚เชšเชฟเชฎเชพเช‚ เชœเซ‹เชกเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เชœเซ‡ เชตเชณเชคเชฐ เชฎเซ‚เชฒเซเชฏ เช›เซ‡. เช•เชพเชฐเซเชฏเชจเซ‡ เชเชกเชชเซ€ เชฌเชจเชพเชตเชตเชพ เชฎเชพเชŸเซ‡, เช…เชฎเซ‡ เช•เซ‹เชทเซเชŸเช•เซ‹เชฎเชพเช‚ เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพเช“เชจเซ€ เชฐเชšเชจเชพเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹ data.table เช…เชจเซ‡ เชฒเชฟเช‚เช• เชฆเซเชตเชพเชฐเชพ เชซเซ‡เชฐเชซเชพเชฐ - เช† เชชเซ‡เช•เซ‡เชœ เชตเชฟเชจเชพ "เชšเชฟเชชเซเชธ" เชกเซ‡เชŸเชพ.เชŸเซ‡เชฌเชฒ R เชฎเชพเช‚ เช•เซ‹เชˆเชชเชฃ เชจเซ‹เช‚เชงเชชเชพเชคเซเชฐ เชชเซเชฐเชฎเชพเชฃเชฎเชพเช‚ เชกเซ‡เชŸเชพ เชธเชพเชฅเซ‡ เช…เชธเชฐเช•เชพเชฐเช• เชฐเซ€เชคเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพเชจเซ€ เช•เชฒเซเชชเชจเชพ เช•เชฐเชตเซ€ เช–เซ‚เชฌ เชฎเซเชถเซเช•เซ‡เชฒ เช›เซ‡.

เช•เซ‹เชฐ i5 เชฒเซ‡เชชเชŸเซ‹เชช เชชเชฐ เชเชกเชช เชฎเชพเชชเชจเชจเชพ เชชเชฐเชฟเชฃเชพเชฎเซ‹ เชจเซ€เชšเซ‡ เชฎเซเชœเชฌ เช›เซ‡:

เช‡เชŸเชฐเชฐเซ‡เชŸเชฐ เชฌเซ‡เชจเซเชšเชฎเชพเชฐเซเช•

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)

เช•เซเชตเชฟเช• เชกเซเชฐเซ‹ เชกเซ‚เชกเชฒ เชฐเซ‡เช•เช—เซเชจเชฟเชถเชจ: R, C++ เช…เชจเซ‡ เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช• เชธเชพเชฅเซ‡ เชฎเชฟเชคเซเชฐเซ‹ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฌเชจเชพเชตเชตเซเช‚

เชœเซ‹ เชคเชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เชชเซ‚เชฐเชคเซ€ เชฎเชพเชคเซเชฐเชพเชฎเชพเช‚ RAM เชนเซ‹เชฏ, เชคเซ‹ เชคเชฎเซ‡ เชกเซ‡เชŸเชพเชฌเซ‡เชเชจเซ‡ เช† เชœ RAM เชชเชฐ เชธเซเชฅเชพเชจเชพเช‚เชคเชฐเชฟเชค เช•เชฐเซ€เชจเซ‡ เช—เช‚เชญเซ€เชฐเชคเชพเชฅเซ€ เชคเซ‡เชจเซ‡ เชเชกเชชเซ€ เชฌเชจเชพเชตเซ€ เชถเช•เซ‹ เช›เซ‹ (32 GB เช…เชฎเชพเชฐเชพ เช•เชพเชฐเซเชฏ เชฎเชพเชŸเซ‡ เชชเซ‚เชฐเชคเซเช‚ เช›เซ‡). Linux เชฎเชพเช‚, เชชเชพเชฐเซเชŸเซ€เชถเชจ เชฎเซ‚เชณเชญเซ‚เชค เชฐเซ€เชคเซ‡ เชฎเชพเช‰เชจเซเชŸ เชฅเชฏเซ‡เชฒ เช›เซ‡ /dev/shm, RAM เชจเซ€ เช…เชกเชงเชพ เชœเซ‡เชŸเชฒเซ€ เช•เซเชทเชฎเชคเชพ เชงเชฐเชพเชตเซ‡ เช›เซ‡. เชคเชฎเซ‡ เชธเช‚เชชเชพเชฆเชจ เช•เชฐเซ€เชจเซ‡ เชตเชงเซ เชชเซเชฐเช•เชพเชถเชฟเชค เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹ /etc/fstabเชœเซ‡เชตเชพ เชฐเซ‡เช•เซ‹เชฐเซเชก เชฎเซ‡เชณเชตเชตเชพ เชฎเชพเชŸเซ‡ tmpfs /dev/shm tmpfs defaults,size=25g 0 0. เชฐเซ€เชฌเซ‚เชŸ เช•เชฐเชตเชพเชจเซ€ เช–เชพเชคเชฐเซ€ เช•เชฐเซ‹ เช…เชจเซ‡ เช†เชฆเซ‡เชถ เชšเชฒเชพเชตเซ€เชจเซ‡ เชชเชฐเชฟเชฃเชพเชฎ เชคเชชเชพเชธเซ‹ df -h.

เชŸเซ‡เชธเซเชŸ เชกเซ‡เชŸเชพ เชฎเชพเชŸเซ‡ เชชเซเชจเชฐเชพเชตเชฐเซเชคเช• เช–เซ‚เชฌ เชธเชฐเชณ เชฒเชพเช—เซ‡ เช›เซ‡, เช•เชพเชฐเชฃ เช•เซ‡ เชŸเซ‡เชธเซเชŸ เชกเซ‡เชŸเชพเชธเซ‡เชŸ เชธเช‚เชชเซ‚เชฐเซเชฃเชชเชฃเซ‡ RAM เชฎเชพเช‚ เชฌเช‚เชงเชฌเซ‡เชธเซ‡ เช›เซ‡:

เชŸเซ‡เชธเซเชŸ เชกเซ‡เชŸเชพ เชฎเชพเชŸเซ‡ เช‡เชŸเชฐเชฐเซ‡เชŸเชฐ

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. เชฎเซ‹เชกเซ‡เชฒ เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐเชจเซ€ เชชเชธเช‚เชฆเช—เซ€

เชชเซเชฐเชฅเชฎ เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เชนเชคเซ‹ เชฎเซ‹เชฌเชพเช‡เชฒเชจเซ‡เชŸ v1, เชœเซ‡เชจเชพเช‚ เชฒเช•เซเชทเชฃเซ‹เชจเซ€ เชšเชฐเซเชšเชพ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ€ เช›เซ‡ เช† เชธเช‚เชฆเซ‡เชถ เชคเซ‡ เชงเซ‹เชฐเชฃ เชคเชฐเซ€เช•เซ‡ เชธเชฎเชพเชตเชตเชพเชฎเชพเช‚ เช†เชตเซ‡เชฒ เช›เซ‡ เช•เซ‡เชฐเชพ เช…เชจเซ‡, เชคเซ‡ เชฎเซเชœเชฌ, R เชฎเชพเชŸเซ‡ เชธเชฎเชพเชจ เชจเชพเชฎเชจเชพ เชชเซ‡เช•เซ‡เชœเชฎเชพเช‚ เช‰เชชเชฒเชฌเซเชง เช›เซ‡. เชชเชฐเช‚เชคเซ เชœเซเชฏเชพเชฐเซ‡ เชคเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เชธเชฟเช‚เช—เชฒ-เชšเซ‡เชจเชฒ เชˆเชฎเซ‡เชœเซ‹ เชธเชพเชฅเซ‡ เช•เชฐเชตเชพเชจเซ‹ เชชเซเชฐเชฏเชพเชธ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เชเช• เชตเชฟเชšเชฟเชคเซเชฐ เชฌเชพเชฌเชค เชฌเชนเชพเชฐ เช†เชตเซ€ เช›เซ‡: เช‡เชจเชชเซเชŸ เชŸเซ‡เชจเซเชธเชฐเชจเซเช‚ เชชเชฐเชฟเชฎเชพเชฃ เชนเช‚เชฎเซ‡เชถเชพ เชนเซ‹เชตเซเช‚ เชœเซ‹เชˆเช. (batch, height, width, 3), เชเชŸเชฒเซ‡ เช•เซ‡, เชšเซ‡เชจเชฒเซ‹เชจเซ€ เชธเช‚เช–เซเชฏเชพ เชฌเชฆเชฒเซ€ เชถเช•เชพเชคเซ€ เชจเชฅเซ€. เชชเชพเชฏเชฅเซ‹เชจเชฎเชพเช‚ เช†เชตเซ€ เช•เซ‹เชˆ เชฎเชฐเซเชฏเชพเชฆเชพ เชจเชฅเซ€, เชคเซ‡เชฅเซ€ เช…เชฎเซ‡ เชฎเซ‚เชณ เชฒเซ‡เช–เชจเซ‡ เช…เชจเซเชธเชฐเซ€เชจเซ‡ เช† เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐเชจเชพ เช…เชฎเชพเชฐเชพ เชชเซ‹เชคเชพเชจเชพ เช…เชฎเชฒเซ€เช•เชฐเชฃ เชฎเชพเชŸเซ‡ เชฆเซ‹เชกเซ€ เช—เชฏเชพ เช…เชจเซ‡ เชฒเช–เซเชฏเซเช‚ (เช•เซ‡เชฐเชพเชธ เชธเช‚เชธเซเช•เชฐเชฃเชฎเชพเช‚ เชกเซเชฐเซ‹เชชเช†เช‰เชŸ เชตเชฟเชจเชพ):

เชฎเซ‹เชฌเชพเช‡เชฒเชจเซ‡เชŸ 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)
}

เช† เช…เชญเชฟเช—เชฎเชจเชพ เช—เซ‡เชฐเชซเชพเชฏเชฆเชพ เชธเซเชชเชทเซเชŸ เช›เซ‡. เชนเซเช‚ เช˜เชฃเชพ เชฌเชงเชพ เชฎเซ‹เชกเชฒเซเชธเชจเซเช‚ เชชเชฐเซ€เช•เซเชทเชฃ เช•เชฐเชตเชพ เชฎเชพเช‚เช—เซ เช›เซเช‚, เชชเชฐเช‚เชคเซ เชคเซ‡เชจเชพเชฅเซ€ เชตเชฟเชชเชฐเซ€เชค, เชนเซเช‚ เชฆเชฐเซ‡เช• เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐเชจเซ‡ เชฎเซ‡เชจเซเชฏเซเช…เชฒเซ€ เชซเชฐเซ€เชฅเซ€ เชฒเช–เชตเชพ เชฎเชพเช‚เช—เชคเซ‹ เชจเชฅเซ€. เช…เชฎเซ‡ เช‡เชฎเซ‡เชœเชจเซ‡เชŸ เชชเชฐ เชชเซ‚เชฐเซเชต เชชเซเชฐเชถเชฟเช•เซเชทเชฟเชค เชฎเซ‹เชกเซ‡เชฒเซ‹เชจเชพ เชตเชœเชจเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชจเซ€ เชคเช•เชฅเซ€ เชชเชฃ เชตเช‚เชšเชฟเชค เชนเชคเชพ. เชนเช‚เชฎเซ‡เชถเชจเซ€ เชœเซ‡เชฎ, เชฆเชธเซเชคเชพเชตเซ‡เชœเซ‹เชจเซ‹ เช…เชญเซเชฏเชพเชธ เช•เชฐเชตเชพเชฎเชพเช‚ เชฎเชฆเชฆ เชฎเชณเซ€. เช•เชพเชฐเซเชฏ get_config() เชคเชฎเชจเซ‡ เชธเช‚เชชเชพเชฆเชจ เชฎเชพเชŸเซ‡ เชฏเซ‹เช—เซเชฏ เชซเซ‹เชฐเซเชฎเชฎเชพเช‚ เชฎเซ‹เชกเซ‡เชฒเชจเซเช‚ เชตเชฐเซเชฃเชจ เชฎเซ‡เชณเชตเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡ (base_model_conf$layers - เชจเชฟเชฏเชฎเชฟเชค เช†เชฐ เชฏเชพเชฆเซ€), เช…เชจเซ‡ เช•เชพเชฐเซเชฏ 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)

เชนเชตเซ‡ เช†เชชเซ‡เชฒ เช•เซ‹เชˆเชชเชฃ เชฎเซ‡เชณเชตเชตเชพ เชฎเชพเชŸเซ‡ เชธเชพเชฐเซเชตเชคเซเชฐเชฟเช• เช•เชพเชฐเซเชฏ เชฒเช–เชตเซเช‚ เชฎเซเชถเซเช•เซ‡เชฒ เชจเชฅเซ€ เช•เซ‡เชฐเชพ เช‡เชฎเซ‡เชœเชจเซ‡เชŸ เชชเชฐ เชชเซเชฐเชถเชฟเช•เซเชทเชฟเชค เชตเชœเชจ เชธเชพเชฅเซ‡ เช…เชฅเชตเชพ เชตเช—เชฐเชจเชพ เชฎเซ‹เชกเซ‡เชฒเซ‹:

เชคเซˆเชฏเชพเชฐ เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐ เชฒเซ‹เชก เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡เชจเซเช‚ เช•เชพเชฐเซเชฏ

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 เชเชฐเซ‡เชจเซ€ เชธเซ‚เชšเชฟเชจเชพ เชฐเซ‚เชชเชฎเชพเช‚ เชฎเซ‹เชกเซ‡เชฒเชจเซเช‚ เชตเชœเชจ เชฎเซ‡เชณเชตเซ‹, เช† เชธเซ‚เชšเชฟเชจเชพ เชชเซเชฐเชฅเชฎ เช˜เชŸเช•เชจเซเช‚ เชชเชฐเชฟเชฎเชพเชฃ เชฌเชฆเชฒเซ‹ (เชเช• เชฐเช‚เช— เชšเซ‡เชจเชฒ เชฒเชˆเชจเซ‡ เช…เชฅเชตเชพ เชคเซเชฐเชฃเซ‡เชฏเชจเซ€ เชธเชฐเซ‡เชฐเชพเชถ เช•เชฐเซ€เชจเซ‡), เช…เชจเซ‡ เชชเช›เซ€ เชซเช‚เช•เซเชถเชจ เชธเชพเชฅเซ‡ เชฎเซ‹เชกเซ‡เชฒเชฎเชพเช‚ เชตเชœเชจ เชชเชพเช›เชพ เชฒเซ‹เชก เช•เชฐเซ‹. set_weights(). เช…เชฎเซ‡ เช† เช•เชพเชฐเซเชฏเช•เซเชทเชฎเชคเชพเชจเซ‡ เช•เซเชฏเชพเชฐเซ‡เชฏ เช‰เชฎเซ‡เชฐเซเชฏเซเช‚ เชจเชฅเซ€, เช•เชพเชฐเชฃ เช•เซ‡ เช† เชคเชฌเช•เซเช•เซ‡ เชคเซ‡ เชชเชนเซ‡เชฒเซ‡เชฅเซ€ เชœ เชธเซเชชเชทเซเชŸ เชนเชคเซเช‚ เช•เซ‡ เชฐเช‚เช—เซ€เชจ เชšเชฟเชคเซเชฐเซ‹ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชตเซเช‚ เชตเชงเซ เช‰เชคเซเชชเชพเชฆเช• เช›เซ‡.

เช…เชฎเซ‡ เชฎเซ‹เชฌเชพเชˆเชฒเชจเซ‡เชŸ เชตเชฐเซเชเชจ 1 เช…เชจเซ‡ 2, เชคเซ‡เชฎเชœ resnet34 เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชฎเซ‹เชŸเชพเชญเชพเช—เชจเชพ เชชเซเชฐเชฏเซ‹เช—เซ‹ เช•เชฐเซเชฏเชพ เช›เซ‡. SE-ResNeXt เชœเซ‡เชตเชพ เชตเชงเซ เช†เชงเซเชจเชฟเช• เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐเซ‹เช เช† เชธเซเชชเชฐเซเชงเชพเชฎเชพเช‚ เชธเชพเชฐเซเช‚ เชชเซเชฐเชฆเชฐเซเชถเชจ เช•เชฐเซเชฏเซเช‚. เช•เชฎเชจเชธเซ€เชฌเซ‡, เช…เชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เช…เชฎเชพเชฐเชพ เชจเชฟเช•เชพเชฒ เชชเชฐ เชคเซˆเชฏเชพเชฐ เช…เชฎเชฒเซ€เช•เชฐเชฃเซ‹ เชจเชนเซ‹เชคเชพ, เช…เชจเซ‡ เช…เชฎเซ‡ เช…เชฎเชพเชฐเชพ เชชเซ‹เชคเชพเชจเชพ เชฒเช–เซเชฏเชพ เชจเชฅเซ€ (เชชเชฐเช‚เชคเซ เช…เชฎเซ‡ เชšเซ‹เช•เซเช•เชธเชชเชฃเซ‡ เชฒเช–เซ€เชถเซเช‚).

5. เชธเซเช•เซเชฐเชฟเชชเซเชŸเซเชธเชจเซเช‚ เชชเซ‡เชฐเชพเชฎเซ€เชŸเชฐเชพเช‡เชเซ‡เชถเชจ

เชธเช—เชตเชก เชฎเชพเชŸเซ‡, เชคเชพเชฒเซ€เชฎ เชถเชฐเซ‚ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡เชจเชพ เชคเชฎเชพเชฎ เช•เซ‹เชก เชธเชฟเช‚เช—เชฒ เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชคเชฐเซ€เช•เซ‡ เชกเชฟเชเชพเช‡เชจ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเชพ เชนเชคเชพ, เชœเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชชเซ‡เชฐเชพเชฎเซ€เชŸเชฐเชพเช‡เชเซเชก เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเชพ เชนเชคเชพ เชฆเชธเซเชคเชพเชตเซ‡เชœ เชจเซ€เชšเซ‡ เชชเซเชฐเชฎเชพเชฃเซ‡ เช›เซ‡:

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)

เชชเซ‡เช•เซ‡เชœ เชฆเชธเซเชคเชพเชตเซ‡เชœ เช…เชฎเชฒเซ€เช•เชฐเชฃ เชฐเชœเซ‚ เช•เชฐเซ‡ เช›เซ‡ http://docopt.org/ R เชฎเชพเชŸเซ‡. เชคเซ‡เชจเซ€ เชฎเชฆเชฆ เชธเชพเชฅเซ‡, เชธเซเช•เซเชฐเชฟเชชเซเชŸเซ‹ เชœเซ‡เชตเชพ เชธเชฐเชณ เช†เชฆเซ‡เชถเซ‹ เชธเชพเชฅเซ‡ เชฒเซ‹เชจเซเชš เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ 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 เชชเชฟเช•เซเชธเซ‡เชฒเชจเซ€ เชคเซเชฐเชฃ-เชฐเช‚เช—เชจเซ€ เช›เชฌเซ€เช“ เชชเชฐ, เชกเซ‡เชŸเชพเชฌเซ‡เช เชซเซ‹เชฒเซเชกเชฐเชฎเชพเช‚ เชธเซเชฅเชฟเชค เชนเซ‹เชตเซ‹ เชœเซ‹เชˆเช /home/andrey/doodle_db). เชคเชฎเซ‡ เชธเซ‚เชšเชฟเชฎเชพเช‚ เชถเซ€เช–เชตเชพเชจเซ€ เชเชกเชช, เช‘เชชเซเชŸเชฟเชฎเชพเช‡เชเชฐ เชชเซเชฐเช•เชพเชฐ เช…เชจเซ‡ เช•เซ‹เชˆเชชเชฃ เช…เชจเซเชฏ เช•เชธเซเชŸเชฎเชพเช‡เช เช•เชฐเชตเชพ เชฏเซ‹เช—เซเชฏ เชชเชฐเชฟเชฎเชพเชฃเซ‹ เช‰เชฎเซ‡เชฐเซ€ เชถเช•เซ‹ เช›เซ‹. เชชเซเชฐเช•เชพเชถเชจ เชคเซˆเชฏเชพเชฐ เช•เชฐเชตเชพเชจเซ€ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพเชฎเชพเช‚, เชคเซ‡ เชฌเชนเชพเชฐ เช†เชตเซเชฏเซเช‚ เช•เซ‡ เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐ mobilenet_v2 เชตเชฐเซเชคเชฎเชพเชจ เชธเช‚เชธเซเช•เชฐเชฃเชฎเชพเช‚เชฅเซ€ เช•เซ‡เชฐเชพ เช†เชฐ เช‰เชชเชฏเซ‹เช—เชฎเชพเช‚ เชจ เช•เชฐเซ€ เชถเช•เซ‹ เช†เชฐ เชชเซ‡เช•เซ‡เชœเชฎเชพเช‚ เชงเซเชฏเชพเชจเชฎเชพเช‚ เชฒเซ‡เชตเชพเชฎเชพเช‚ เชจ เช†เชตเชคเชพ เชซเซ‡เชฐเชซเชพเชฐเซ‹เชจเซ‡ เช•เชพเชฐเชฃเซ‡, เช…เชฎเซ‡ เชคเซ‡เชจเซ‡ เช เซ€เช• เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชฐเชพเชน เชœเซ‹เชˆ เชฐเชนเซเชฏเชพ เช›เซ€เช.

เช† เช…เชญเชฟเช—เชฎเชจเซ‡ เช•เชพเชฐเชฃเซ‡ RStudio เชฎเชพเช‚ เชธเซเช•เซเชฐเชฟเชชเซเชŸเชจเชพ เชตเชงเซ เชชเชฐเช‚เชชเชฐเชพเช—เชค เชฒเซ‹เช‚เชšเชจเซ€ เชคเซเชฒเชจเชพเชฎเชพเช‚ เชตเชฟเชตเชฟเชง เชฎเซ‹เชกเซ‡เชฒเซ‹ เชธเชพเชฅเซ‡เชจเชพ เชชเซเชฐเชฏเซ‹เช—เซ‹เชจเซ‡ เชจเซ‹เช‚เชงเชชเชพเชคเซเชฐ เชฐเซ€เชคเซ‡ เชเชกเชชเซ€ เชฌเชจเชพเชตเชตเชพเชจเซเช‚ เชถเช•เซเชฏ เชฌเชจเซเชฏเซเช‚ (เช…เชฎเซ‡ เชชเซ‡เช•เซ‡เชœเชจเซ‡ เชธเช‚เชญเชตเชฟเชค เชตเชฟเช•เชฒเซเชช เชคเชฐเซ€เช•เซ‡ เชจเซ‹เช‚เชงเซ€เช เช›เซ€เช. tfruns). เชชเชฐเช‚เชคเซ เชฎเซเช–เซเชฏ เชซเชพเชฏเชฆเซ‹ เช เช›เซ‡ เช•เซ‡ เช† เชฎเชพเชŸเซ‡ เช†เชฐเชธเซเชŸเซเชกเชฟเชฏเซ‹ เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเซเชฏเชพ เชตเชฟเชจเชพ, เชกเซ‹เช•เชฐเชฎเชพเช‚ เช…เชฅเชตเชพ เชซเช•เซเชค เชธเชฐเซเชตเชฐ เชชเชฐ เชธเซเช•เซเชฐเชฟเชชเซเชŸเชจเชพ เชฒเซ‹เชจเซเชšเชจเซ‡ เชธเชฐเชณเชคเชพเชฅเซ€ เชธเช‚เชšเชพเชฒเชฟเชค เช•เชฐเชตเชพเชจเซ€ เช•เซเชทเชฎเชคเชพ เช›เซ‡.

6. เชธเซเช•เซเชฐเชฟเชชเซเชŸเซ‹เชจเซเช‚ เชกเซ‹เช•เชฐเชพเช‡เชเซ‡เชถเชจ

เช…เชฎเซ‡ เชŸเซ€เชฎเชจเชพ เชธเชญเซเชฏเซ‹ เชตเชšเซเชšเซ‡เชจเชพ เชชเซเชฐเชถเชฟเช•เซเชทเชฃ เชฎเซ‹เชกเชฒเซเชธ เชฎเชพเชŸเซ‡ เช…เชจเซ‡ เช•เซเชฒเชพเช‰เชกเชฎเชพเช‚ เชเชกเชชเซ€ เชœเชฎเชพเชตเชŸ เชฎเชพเชŸเซ‡ เชชเชฐเซเชฏเชพเชตเชฐเชฃเชจเซ€ เชชเซ‹เชฐเซเชŸเซ‡เชฌเชฟเชฒเชฟเชŸเซ€ เชธเซเชจเชฟเชถเซเชšเชฟเชค เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชกเซ‹เช•เชฐเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹. เชคเชฎเซ‡ เช† เชธเชพเชงเชจ เชธเชพเชฅเซ‡ เชชเชฐเชฟเชšเชฟเชค เชฅเชตเชพเชจเซเช‚ เชถเชฐเซ‚ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹, เชœเซ‡ เช†เชฐ เชชเซเชฐเซ‹เช—เซเชฐเชพเชฎเชฐ เชฎเชพเชŸเซ‡ เชชเซเชฐเชฎเชพเชฃเชฎเชพเช‚ เช…เชธเชพเชฎเชพเชจเซเชฏ เช›เซ‡, เชธเชพเชฅเซ‡ เช† เชชเซเชฐเช•เชพเชถเชจเซ‹เชจเซ€ เชถเซเชฐเซ‡เชฃเซ€ เช…เชฅเชตเชพ เชตเชฟเชกเชฟเช“ เช•เซ‹เชฐเซเชธ.

เชกเซ‹เช•เชฐ เชคเชฎเชจเซ‡ เชถเชฐเซ‚เช†เชคเชฅเซ€ เชคเชฎเชพเชฐเซ€ เชชเซ‹เชคเชพเชจเซ€ เช›เชฌเซ€เช“ เชฌเชจเชพเชตเชตเชพ เช…เชจเซ‡ เชคเชฎเชพเชฐเซ€ เชชเซ‹เชคเชพเชจเซ€ เชฌเชจเชพเชตเชตเชพ เชฎเชพเชŸเซ‡เชจเชพ เช†เชงเชพเชฐ เชคเชฐเซ€เช•เซ‡ เช…เชจเซเชฏ เช›เชฌเซ€เช“เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡. เช‰เชชเชฒเชฌเซเชง เชตเชฟเช•เชฒเซเชชเซ‹เชจเซเช‚ เชตเชฟเชถเซเชฒเซ‡เชทเชฃ เช•เชฐเชคเซ€ เชตเช–เชคเซ‡, เช…เชฎเซ‡ เชจเชฟเชทเซเช•เชฐเซเชท เชชเชฐ เช†เชตเซเชฏเชพ เช•เซ‡ NVIDIA, CUDA+cuDNN เชกเซเชฐเชพเช‡เชตเชฐเซ‹ เช…เชจเซ‡ Python เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€เช“ เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเชตเซ€ เช เช‡เชฎเซ‡เชœเชจเซ‹ เชเช•เชฆเชฎ เชฎเซ‹เชŸเซ‹ เชญเชพเช— เช›เซ‡, เช…เชจเซ‡ เช…เชฎเซ‡ เชธเชคเซเชคเชพเชตเชพเชฐ เช›เชฌเซ€เชจเซ‡ เช†เชงเชพเชฐ เชคเชฐเซ€เช•เซ‡ เชฒเซ‡เชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเชฏเซเช‚. tensorflow/tensorflow:1.12.0-gpu, เชคเซเชฏเชพเช‚ เชœเชฐเซ‚เชฐเซ€ R เชชเซ‡เช•เซ‡เชœเซ‹ เช‰เชฎเซ‡เชฐเซ€ เชฐเชนเซเชฏเชพ เช›เซ‡.

เช…เช‚เชคเชฟเชฎ เชกเซ‹เช•เชฐ เชซเชพเช‡เชฒ เช†เชจเชพ เชœเซ‡เชตเซ€ เชฆเซ‡เช–เชพเชคเซ€ เชนเชคเซ€:

เชกเซ‹เช•เชฐเชซเชพเช‡เชฒ

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

เช…เชจเซเช•เซ‚เชณเชคเชพ เชฎเชพเชŸเซ‡, เช‰เชชเชฏเซ‹เช—เชฎเชพเช‚ เชฒเซ‡เชตเชพเชคเชพ เชชเซ‡เช•เซ‡เชœเซ‹เชจเซ‡ เชšเชฒเซ‹เชฎเชพเช‚ เชฎเซ‚เช•เชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเชพ เชนเชคเชพ; เชเชธเซ‡เชฎเซเชฌเชฒเซ€ เชฆเชฐเชฎเชฟเชฏเชพเชจ เชฎเซ‹เชŸเชพเชญเชพเช—เชจเซ€ เชฒเซ‡เช–เชฟเชค เชธเซเช•เซเชฐเชฟเชชเซเชŸ เช•เชจเซเชŸเซ‡เชจเชฐเชจเซ€ เช…เช‚เชฆเชฐ เชจเช•เชฒ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡. เช…เชฎเซ‡ เช†เชฆเซ‡เชถ เชถเซ‡เชฒ เชชเชฃ เชฌเชฆเชฒเซเชฏเซ‹ เช›เซ‡ /bin/bash เชธเชพเชฎเช—เซเชฐเซ€เชจเชพ เช‰เชชเชฏเซ‹เช—เชฎเชพเช‚ เชธเชฐเชณเชคเชพ เชฎเชพเชŸเซ‡ /etc/os-release. เช†เชจเชพเชฅเซ€ เช•เซ‹เชกเชฎเชพเช‚ OS เชธเช‚เชธเซเช•เชฐเชฃเชจเซ‹ เช‰เชฒเซเชฒเซ‡เช– เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐเชฟเชฏเชพเชค เชŸเชพเชณเซ€ เชถเช•เชพเชฏ เช›เซ‡.

เชตเชงเซเชฎเชพเช‚, เชเช• เชจเชพเชจเซ€ เชฌเซ‡เชถ เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชฒเช–เชตเชพเชฎเชพเช‚ เช†เชตเซ€ เชนเชคเซ€ เชœเซ‡ เชคเชฎเชจเซ‡ เชตเชฟเชตเชฟเชง เช†เชฆเซ‡เชถเซ‹ เชธเชพเชฅเซ‡ เช•เชจเซเชŸเซ‡เชจเชฐ เชถเชฐเซ‚ เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡. เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เช† เช…เช—เชพเช‰ เช•เชจเซเชŸเซ‡เชจเชฐเชจเซ€ เช…เช‚เชฆเชฐ เชฎเซ‚เช•เชตเชพเชฎเชพเช‚ เช†เชตเซ‡เชฒเชพ เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช•เชจเซ‡ เชคเชพเชฒเซ€เชฎ เช†เชชเชตเชพ เชฎเชพเชŸเซ‡เชจเซ€ เชธเซเช•เซเชฐเชฟเชชเซเชŸเซ‹ เช…เชฅเชตเชพ เช•เชจเซเชŸเซ‡เชจเชฐเชจเซ€ เช•เชพเชฎเช—เซ€เชฐเซ€เชจเซ‡ เชกเชฟเชฌเช—เซ€เช‚เช— เช…เชจเซ‡ เชฎเซ‹เชจเชฟเชŸเชฐ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เช•เชฎเชพเชจเซเชก เชถเซ‡เชฒ เชนเซ‹เชˆ เชถเช•เซ‡ เช›เซ‡:

เช•เชจเซเชŸเซ‡เชจเชฐ เชฒเซ‹เช‚เชš เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡เชจเซ€ เชธเซเช•เซเชฐเชฟเชชเซเชŸ

#!/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}

เชœเซ‹ เช† เชฌเซ‡เชถ เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชชเชฐเชฟเชฎเชพเชฃเซ‹ เชตเชฟเชจเชพ เชšเชฒเชพเชตเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เชคเซ‹ เชธเซเช•เซเชฐเชฟเชชเซเชŸเชจเซ‡ เช•เชจเซเชŸเซ‡เชจเชฐเชจเซ€ เช…เช‚เชฆเชฐ เชฌเซ‹เชฒเชพเชตเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡ train_nn.R เชกเชฟเชซเซ‰เชฒเซเชŸ เชฎเซ‚เชฒเซเชฏเซ‹ เชธเชพเชฅเซ‡; เชœเซ‹ เชชเซเชฐเชฅเชฎ เชธเซเชฅเชพเชจเซ€เชฏ เชฆเชฒเซ€เชฒ "bash" เชนเซ‹เชฏ, เชคเซ‹ เช•เชจเซเชŸเซ‡เชจเชฐ เช•เชฎเชพเชจเซเชก เชถเซ‡เชฒ เชธเชพเชฅเซ‡ เช‡เชจเซเชŸเชฐเซ‡เช•เซเชŸเชฟเชต เชฐเซ€เชคเซ‡ เชถเชฐเซ‚ เชฅเชถเซ‡. เช…เชจเซเชฏ เชคเชฎเชพเชฎ เช•เซ‡เชธเซ‹เชฎเชพเช‚, เชธเซเชฅเชฟเชคเชฟเช•เซ€เชฏ เชฆเชฒเซ€เชฒเซ‹เชจเชพ เชฎเซ‚เชฒเซเชฏเซ‹ เชฌเชฆเชฒเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡: CMD="Rscript /app/train_nn.R $@".

เชคเซ‡ เชจเซ‹เช‚เชงเชตเซเช‚ เชฏเซ‹เช—เซเชฏ เช›เซ‡ เช•เซ‡ เชธเซเชฐเซ‹เชค เชกเซ‡เชŸเชพ เช…เชจเซ‡ เชกเซ‡เชŸเชพเชฌเซ‡เช เชธเชพเชฅเซ‡เชจเซ€ เชกเชฟเชฐเซ‡เช•เซเชŸเชฐเซ€เช“, เชคเซ‡เชฎเชœ เชชเซเชฐเชถเชฟเช•เซเชทเชฟเชค เชฎเซ‹เชกเชฒเซเชธเชจเซ‡ เชธเชพเชšเชตเชตเชพ เชฎเชพเชŸเซ‡เชจเซ€ เชกเชฟเชฐเซ‡เช•เซเชŸเชฐเซ€, เชนเซ‹เชธเซเชŸ เชธเชฟเชธเซเชŸเชฎเชฎเชพเช‚เชฅเซ€ เช•เชจเซเชŸเซ‡เชจเชฐเชจเซ€ เช…เช‚เชฆเชฐ เชฎเชพเช‰เชจเซเชŸ เชฅเชฏเซ‡เชฒ เช›เซ‡, เชœเซ‡ เชคเชฎเชจเซ‡ เชฌเชฟเชจเชœเชฐเซ‚เชฐเซ€ เชฎเซ‡เชจเซ€เชชเซเชฏเซเชฒเซ‡เชถเชจเซเชธ เชตเชฟเชจเชพ เชธเซเช•เซเชฐเชฟเชชเซเชŸเซเชธเชจเชพ เชชเชฐเชฟเชฃเชพเชฎเซ‹เชจเซ‡ เชเช•เซเชธเซ‡เชธ เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡.

7. Google Cloud เชชเชฐ เชฌเชนเซเชตเชฟเชง GPU เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเซ‹

เชธเซเชชเชฐเซเชงเชพเชจเซ€ เชตเชฟเชถเซ‡เชทเชคเชพเช“เชฎเชพเช‚เชจเซ€ เชเช• เช–เซ‚เชฌ เชœ เช˜เซ‹เช‚เช˜เชพเชŸเชตเชพเชณเซ‹ เชกเซ‡เชŸเชพ เชนเชคเซ‹ (เชถเซ€เชฐเซเชทเช•เชจเซเช‚ เชšเชฟเชคเซเชฐ เชœเซเช“, ODS เชธเซเชฒเซ‡เช•เชฎเชพเช‚เชฅเซ€ @Leigh.plt เชชเชฐเชฅเซ€ เช‰เชงเชพเชฐ เชฒเซ€เชงเซ‡เชฒ). เชฎเซ‹เชŸเชพ เชฌเซ…เชšเซ‡เชธ เช†เชจเซ‹ เชธเชพเชฎเชจเซ‹ เช•เชฐเชตเชพเชฎเชพเช‚ เชฎเชฆเชฆ เช•เชฐเซ‡ เช›เซ‡, เช…เชจเซ‡ 1 GPU เชธเชพเชฅเซ‡ เชชเซ€เชธเซ€ เชชเชฐ เชชเซเชฐเชฏเซ‹เช—เซ‹ เชชเช›เซ€, เช…เชฎเซ‡ เช•เซเชฒเชพเช‰เชกเชฎเชพเช‚ เช˜เชฃเชพ GPUs เชชเชฐ เชคเชพเชฒเซ€เชฎ เชฎเซ‹เชกเชฒเซเชธเชจเซ‡ เชฎเชพเชธเซเชŸเชฐ เช•เชฐเชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเชฏเซเช‚. เชตเชชเชฐเชพเชฏเซ‡เชฒ GoogleCloud (เชฎเซ‚เชณเชญเซ‚เชค เชฎเชพเชŸเซ‡ เชธเชพเชฐเซ€ เชฎเชพเชฐเซเช—เชฆเชฐเซเชถเชฟเช•เชพ) เช‰เชชเชฒเชฌเซเชง เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชจเซ‹เชจเซ€ เชฎเซ‹เชŸเซ€ เชชเชธเช‚เชฆเช—เซ€, เชตเชพเชœเชฌเซ€ เช•เชฟเช‚เชฎเชคเซ‹ เช…เชจเซ‡ $300 เชฌเซ‹เชจเชธเชจเซ‡ เช•เชพเชฐเชฃเซ‡. เชฒเซ‹เชญเชฅเซ€, เชฎเซ‡เช‚ SSD เช…เชจเซ‡ เชเช• เชŸเชจ RAM เชธเชพเชฅเซ‡ 4xV100 เชฆเชพเช–เชฒเชพเชจเซ‹ เช“เชฐเซเชกเชฐ เช†เชชเซเชฏเซ‹, เช…เชจเซ‡ เชคเซ‡ เชเช• เชฎเซ‹เชŸเซ€ เชญเซ‚เชฒ เชนเชคเซ€. เช†เชตเซ€ เชฎเชถเซ€เชจ เชเชกเชชเชฅเซ€ เชชเซˆเชธเชพ เช–เชพเชˆ เชœเชพเชฏ เช›เซ‡; เชคเชฎเซ‡ เชธเชพเชฌเชฟเชค เชชเชพเช‡เชชเชฒเชพเช‡เชจ เชตเชฟเชจเชพ เช…เช–เชคเชฐเชพ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹. เชถเซˆเช•เซเชทเชฃเชฟเช• เชนเซ‡เชคเซเช“ เชฎเชพเชŸเซ‡, K80 เชฒเซ‡เชตเชพเชจเซเช‚ เชตเชงเซ เชธเชพเชฐเซเช‚ เช›เซ‡. เชชเชฐเช‚เชคเซ เชฎเซ‹เชŸเซ€ เชฎเชพเชคเซเชฐเชพเชฎเชพเช‚ เชฐเซ‡เชฎ เชนเชพเชฅเชฎเชพเช‚ เช†เชตเซ€ - เช•เซเชฒเชพเช‰เชก เชเชธเชเชธเชกเซ€ เชคเซ‡เชจเชพ เชชเซเชฐเชฆเชฐเซเชถเชจเชฅเซ€ เชชเซเชฐเชญเชพเชตเชฟเชค เชฅเชˆ เชถเช•เซเชฏเซเช‚ เชจเชนเซ€เช‚, เชคเซ‡เชฅเซ€ เชกเซ‡เชŸเชพเชฌเซ‡เชเชจเซ‡ เชŸเซเชฐเชพเชจเซเชธเชซเชฐ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ dev/shm.

เชฌเชนเซเชตเชฟเชง GPU เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชœเชตเชพเชฌเชฆเชพเชฐ เช•เซ‹เชก เชซเซเชฐเซ‡เช—เชฎเซ‡เชจเซเชŸ เชธเซŒเชฅเซ€ เชตเชงเซ เชฐเชธเชชเซเชฐเชฆ เช›เซ‡. เชชเซเชฐเชฅเชฎ, เชชเชพเชฏเชฅเซ‹เชจเชจเซ€ เชœเซ‡เชฎ, เชธเช‚เชฆเชฐเซเชญ เชฎเซ‡เชจเซ‡เชœเชฐเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ CPU เชชเชฐ เชฎเซ‹เชกเซ‡เชฒ เชฌเชจเชพเชตเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡:

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
  )
})

เชชเช›เซ€ เช…เชจเช•เชฎเซเชชเชพเช‡เชฒ เช•เชฐเซ‡เชฒ (เช† เช…เช—เชคเซเชฏเชจเซเช‚ เช›เซ‡) เชฎเซ‹เชกเซ‡เชฒ เช†เชชเซ‡เชฒ เช‰เชชเชฒเชฌเซเชง GPU เชจเซ€ เชธเช‚เช–เซเชฏเชพ เชชเชฐ เช•เซ‰เชชเชฟ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เช…เชจเซ‡ เชคเซ‡ เชชเช›เซ€ เชœ เชคเซ‡ เชธเช‚เช•เชฒเชฟเชค เชฅเชพเชฏ เช›เซ‡:

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 เชฎเชพเชŸเซ‡ เชธเช‚เชชเซ‚เชฐเซเชฃ เชฎเซ‹เชกเชฒเชจเซ‡ เช…เชจเชซเซเชฐเซ€เช เช•เชฐเชตเชพเชจเซ€ เช…เชจเซ‡ เชซเชฐเซ€เชฅเซ€ เชคเชพเชฒเซ€เชฎ เช†เชชเชตเชพเชจเซ€ เช•เซเชฒเชพเชธเชฟเช• เชคเช•เชจเซ€เช• เช…เชฎเชฒเชฎเชพเช‚ เชฎเซ‚เช•เซ€ เชถเช•เชพเชˆ เชจเชฅเซ€.

เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเชพ เชตเชฟเชจเชพ เชคเชพเชฒเซ€เชฎเชจเซเช‚ เชจเชฟเชฐเซ€เช•เซเชทเชฃ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซเช‚ เชนเชคเซเช‚. เชŸเซ‡เชจเซเชธเชฐเชฌเซ‹เชฐเซเชก, เชฆเชฐเซ‡เช• เชฏเซเช— เชชเช›เซ€ เชฎเชพเชนเชฟเชคเซ€เชชเซเชฐเชฆ เชจเชพเชฎเซ‹ เชธเชพเชฅเซ‡ เชฒเซ‰เช—เซเชธ เชฐเซ‡เช•เซ‹เชฐเซเชก เช•เชฐเชตเชพ เช…เชจเซ‡ เชฎเซ‹เชกเชฒเชจเซ‡ เชธเชพเชšเชตเชตเชพ เชฎเชพเชŸเซ‡ เชœเชพเชคเชจเซ‡ เชฎเชฐเซเชฏเชพเชฆเชฟเชค เช•เชฐเซ€เช เช›เซ€เช:

เช•เซ‰เชฒเชฌเซ…เช•เซเชธ

# ะจะฐะฑะปะพะฝ ะธะผะตะฝะธ ั„ะฐะนะปะฐ ะปะพะณะฐ
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. เชจเชฟเชทเซเช•เชฐเซเชทเชจเซ‡ เชฌเชฆเชฒเซ‡

เช…เชธเช‚เช–เซเชฏ เชธเชฎเชธเซเชฏเชพเช“ เช•เซ‡ เชœเซ‡เชจเซ‹ เช…เชฎเซ‡ เชธเชพเชฎเชจเซ‹ เช•เชฐเซเชฏเซ‹ เช›เซ‡ เชคเซ‡ เชนเชœเซ เชธเซเชงเซ€ เชฆเซ‚เชฐ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ€ เชจเชฅเซ€:

  • ะฒ เช•เซ‡เชฐเชพ เชถเซเชฐเซ‡เชทเซเช  เชถเชฟเช•เซเชทเชฃ เชฆเชฐ (เชเชจเชพเชฒเซ‹เช— lr_finder เชชเซเชธเซเชคเช•เชพเชฒเชฏเชฎเชพเช‚ เชเชกเชชเซ€.เช.เช†เชˆ); เช•เซ‡เชŸเชฒเชพเช• เชชเซเชฐเชฏเชคเซเชจเซ‹ เชธเชพเชฅเซ‡, เชคเซƒเชคเซ€เชฏ-เชชเช•เซเชท เช…เชฎเชฒเซ€เช•เชฐเชฃเซ‹เชจเซ‡ R เชชเชฐ เชชเซ‹เชฐเซเชŸ เช•เชฐเชตเชพเชจเซเช‚ เชถเช•เซเชฏ เช›เซ‡, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เช†;
  • เช…เช—เชพเช‰เชจเชพ เชฎเซเชฆเซเชฆเชพเชจเชพ เชชเชฐเชฟเชฃเชพเชฎเซ‡, เช˜เชฃเชพ GPU เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชคเซ€ เชตเช–เชคเซ‡ เชฏเซ‹เช—เซเชฏ เชคเชพเชฒเซ€เชฎ เชเชกเชช เชชเชธเช‚เชฆ เช•เชฐเชตเชพเชจเซเช‚ เชถเช•เซเชฏ เชจ เชนเชคเซเช‚;
  • เช†เชงเซเชจเชฟเช• เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช• เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐเชจเซ‹ เช…เชญเชพเชต เช›เซ‡, เช–เชพเชธ เช•เชฐเซ€เชจเซ‡ เช‡เชฎเซ‡เชœเชจเซ‡เชŸ เชชเชฐ เชชเซ‚เชฐเซเชต เชชเซเชฐเชถเชฟเช•เซเชทเชฟเชค;
  • เช•เซ‹เชˆ เชเช• เชšเช•เซเชฐ เชจเซ€เชคเชฟ เช…เชจเซ‡ เชญเซ‡เชฆเชญเชพเชตเชชเซ‚เชฐเซเชฃ เชถเชฟเช•เซเชทเชฃ เชฆเชฐ (เช•เซ‹เชธเชพเชˆเชจ เชเชจเชฟเชฒเชฟเช‚เช— เช…เชฎเชพเชฐเซ€ เชตเชฟเชจเช‚เชคเซ€ เชชเชฐ เชนเชคเซเช‚ เช…เชฎเชฒเชฎเชพเช‚ เชฎเซ‚เช•เซเชฏเซ‹, เช†เชญเชพเชฐ เชธเซเช•เชพเชฏเชกเซ‡เชจ).

เช† เชธเซเชชเชฐเซเชงเชพเชฎเชพเช‚เชฅเซ€ เช•เชˆ เช‰เชชเชฏเซ‹เช—เซ€ เชฌเชพเชฌเชคเซ‹ เชถเซ€เช–เชตเชพ เชฎเชณเซ€:

  • เชชเซเชฐเชฎเชพเชฃเชฎเชพเช‚ เช“เช›เชพ-เชชเชพเชตเชฐ เชนเชพเชฐเซเชกเชตเซ‡เชฐ เชชเชฐ, เชคเชฎเซ‡ เชชเซ€เชกเชพ เชตเชฟเชจเชพ เชฏเซ‹เช—เซเชฏ (RAM เชจเชพ เช•เชฆ เช•เชฐเชคเชพเช‚ เช˜เชฃเซ€ เชตเช–เชค) เชกเซ‡เชŸเชพเชจเชพ เชตเซ‹เชฒเซเชฏเซเชฎเซ‹ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹. เชชเซเชฒเชพเชธเซเชŸเชฟเช•เชจเซ€ เชฅเซ‡เชฒเซ€ เชกเซ‡เชŸเชพ.เชŸเซ‡เชฌเชฒ เช•เซ‹เชทเซเชŸเช•เซ‹เชจเชพ เช‡เชจ-เชชเซเชฒเซ‡เชธ เชซเซ‡เชฐเชซเชพเชฐเชจเซ‡ เช•เชพเชฐเชฃเซ‡ เชฎเซ‡เชฎเชฐเซ€เชจเซ‡ เชฌเชšเชพเชตเซ‡ เช›เซ‡, เชœเซ‡ เชคเซ‡เชฎเชจเซ€ เชจเช•เชฒ เช•เชฐเชตเชพเชจเซเช‚ เชŸเชพเชณเซ‡ เช›เซ‡, เช…เชจเซ‡ เชœเซเชฏเชพเชฐเซ‡ เชฏเซ‹เช—เซเชฏ เชฐเซ€เชคเซ‡ เช‰เชชเชฏเซ‹เช—เชฎเชพเช‚ เชฒเซ‡เชตเชพเชฏ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เชคเซ‡เชจเซ€ เช•เซเชทเชฎเชคเชพเช“ เชฒเช—เชญเช— เชนเช‚เชฎเซ‡เชถเชพ เชธเซเช•เซเชฐเชฟเชชเซเชŸเซ€เช‚เช— เชญเชพเชทเชพเช“ เชฎเชพเชŸเซ‡ เช…เชฎเชจเซ‡ เชœเชพเชฃเซ€เชคเชพ เชคเชฎเชพเชฎ เชธเชพเชงเชจเซ‹เชฎเชพเช‚ เชธเซŒเชฅเซ€ เชตเชงเซ เชเชกเชช เชฆเชฐเซเชถเชพเชตเซ‡ เช›เซ‡. เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชกเซ‡เชŸเชพ เชธเชพเชšเชตเชตเชพเชฅเซ€ เชคเชฎเซ‡, เช˜เชฃเชพ เช•เชฟเชธเซเชธเชพเช“เชฎเชพเช‚, เชธเชฎเช—เซเชฐ เชกเซ‡เชŸเชพเชธเซ‡เชŸเชจเซ‡ RAM เชฎเชพเช‚ เชธเซเช•เซเชตเชฟเช เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐเชฟเชฏเชพเชค เชตเชฟเชถเซ‡ เชฌเชฟเชฒเช•เซเชฒ เชตเชฟเชšเชพเชฐเชคเชพ เชจเชฅเซ€.
  • R เชฎเชพเช‚ เชงเซ€เชฎเชพ เช•เชพเชฐเซเชฏเซ‹เชจเซ‡ เชชเซ‡เช•เซ‡เชœเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ C++ เชฎเชพเช‚ เชเชกเชชเซ€ เช•เชพเชฐเซเชฏเซ‹ เชธเชพเชฅเซ‡ เชฌเชฆเชฒเซ€ เชถเช•เชพเชฏ เช›เซ‡ เช†เชฐเชธเซ€เชชเซ€เชชเซ€. เชœเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพ เช‰เชชเชฐเชพเช‚เชค RcppThread เช…เชฅเชตเชพ Rcpp เชธเชฎเชพเช‚เชคเชฐ, เช…เชฎเชจเซ‡ เช•เซเชฐเซ‹เชธ-เชชเซเชฒเซ‡เชŸเชซเซ‹เชฐเซเชฎ เชฎเชฒเซเชŸเซ€-เชฅเซเชฐเซ‡เชกเซ‡เชก เช…เชฎเชฒเซ€เช•เชฐเชฃ เชฎเชณเซ‡ เช›เซ‡, เชคเซ‡เชฅเซ€ R เชธเซเชคเชฐ เชชเชฐ เช•เซ‹เชกเชจเซ‡ เชธเชฎเชพเช‚เชคเชฐ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เชจเชฅเซ€.
  • เชชเซ‡เช•เซ‡เชœ เช†เชฐเชธเซ€เชชเซ€เชชเซ€ C++ เชจเชพ เช—เช‚เชญเซ€เชฐ เชœเซเชžเชพเชจ เชตเชฟเชจเชพ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€ เชถเช•เชพเชฏ เช›เซ‡, เชœเชฐเซ‚เชฐเซ€ เชจเซเชฏเซ‚เชจเชคเชฎ เชฆเชฐเซเชถเชพเชตเซ‡เชฒ เช›เซ‡ เช…เชนเซ€เช‚. เชœเซ‡เชตเซ€ เช…เชธเช‚เช–เซเชฏ เช เช‚เชกเซ€ เชธเซ€-เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€เช“ เชฎเชพเชŸเซ‡ เชนเซ‡เชกเชฐ เชซเชพเช‡เชฒเซ‹ xtensor CRAN เชชเชฐ เช‰เชชเชฒเชฌเซเชง เช›เซ‡, เชเชŸเชฒเซ‡ เช•เซ‡ เชชเซเชฐเซ‹เชœเซ‡เช•เซเชŸเชจเชพ เช…เชฎเชฒเซ€เช•เชฐเชฃ เชฎเชพเชŸเซ‡ เชเช• เช‡เชจเซเชซเซเชฐเชพเชธเซเชŸเซเชฐเช•เซเชšเชฐเชจเซ€ เชฐเชšเชจเชพ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ€ เชฐเชนเซ€ เช›เซ‡ เชœเซ‡ เชคเซˆเชฏเชพเชฐ เช‰เชšเซเชš-เชชเซเชฐเชฆเชฐเซเชถเชจ C++ เช•เซ‹เชกเชจเซ‡ R เชฎเชพเช‚ เชธเช‚เช•เชฒเชฟเชค เช•เชฐเซ‡ เช›เซ‡. เชตเชงเชพเชฐเชพเชจเซ€ เชธเช—เชตเชก เชธเชฟเชจเซเชŸเซ‡เช•เซเชธ เชนเชพเช‡เชฒเชพเช‡เชŸเชฟเช‚เช— เช…เชจเซ‡ RStudio เชฎเชพเช‚ เชธเซเชฅเชฟเชฐ C++ เช•เซ‹เชก เชตเชฟเชถเซเชฒเซ‡เชทเช• เช›เซ‡.
  • เชฆเชธเซเชคเชพเชตเซ‡เชœ เชคเชฎเชจเซ‡ เชชเชฐเชฟเชฎเชพเชฃเซ‹ เชธเชพเชฅเซ‡ เชธเซเชต-เชธเชฎเชพเชฏเซ‡เชฒ เชธเซเช•เซเชฐเชฟเชชเซเชŸเซ‹ เชšเชฒเชพเชตเชตเชพ เชฎเชพเชŸเซ‡ เชชเชฐเชตเชพเชจเช—เซ€ เช†เชชเซ‡ เช›เซ‡. เช† เชฐเชฟเชฎเซ‹เชŸ เชธเชฐเซเชตเชฐ เชชเชฐ เชตเชพเชชเชฐเชตเชพ เชฎเชพเชŸเซ‡ เช…เชจเซเช•เซ‚เชณ เช›เซ‡, เชธเชนเชฟเชค. เชกเซ‹เช•เชฐ เชนเซ‡เช เชณ. เช†เชฐเชธเซเชŸเซเชกเชฟเชฏเซ‹เชฎเชพเช‚, เชจเซเชฏเซเชฐเชฒ เชจเซ‡เชŸเชตเชฐเซเช•เชจเซ‡ เชคเชพเชฒเซ€เชฎ เช†เชชเชตเชพ เชธเชพเชฅเซ‡ เช˜เชฃเชพ เช•เชฒเชพเช•เซ‹ เชชเซเชฐเชฏเซ‹เช—เซ‹ เช•เชฐเชตเชพ เช…เชธเซเชตเชฟเชงเชพเชœเชจเช• เช›เซ‡, เช…เชจเซ‡ เชธเชฐเซเชตเชฐ เชชเชฐ IDE เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเชตเซเช‚ เชนเช‚เชฎเซ‡เชถเชพ เชจเซเชฏเชพเชฏเซ€ เชจเชฅเซ€.
  • เชกเซ‹เช•เชฐ เช•เซ‹เชก เชชเซ‹เชฐเซเชŸเซ‡เชฌเชฟเชฒเชฟเชŸเซ€ เช…เชจเซ‡ OS เช…เชจเซ‡ เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€เช“เชจเชพ เชตเชฟเชตเชฟเชง เชธเช‚เชธเซเช•เชฐเชฃเซ‹ เชงเชฐเชพเชตเชคเชพ เชตเชฟเช•เชพเชธเช•เชฐเซเชคเชพเช“ เชตเชšเซเชšเซ‡ เชชเชฐเชฟเชฃเชพเชฎเซ‹เชจเซ€ เชชเซเชจเชƒเช‰เชคเซเชชเชพเชฆเชจเช•เซเชทเชฎเชคเชพ เชคเซ‡เชฎเชœ เชธเชฐเซเชตเชฐ เชชเชฐ เช…เชฎเชฒเชฎเชพเช‚ เชธเชฐเชณเชคเชพเชจเซ€ เช–เชพเชคเชฐเซ€ เช•เชฐเซ‡ เช›เซ‡. เชคเชฎเซ‡ เชฎเชพเชคเซเชฐ เชเช• เช†เชฆเซ‡เชถ เชตเชกเซ‡ เชธเชฎเช—เซเชฐ เชคเชพเชฒเซ€เชฎ เชชเชพเช‡เชชเชฒเชพเช‡เชจ เชถเชฐเซ‚ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹.
  • Google Cloud เช เช–เชฐเซเชšเชพเชณ เชนเชพเชฐเซเชกเชตเซ‡เชฐ เชชเชฐ เชชเซเชฐเชฏเซ‹เช— เช•เชฐเชตเชพเชจเซ€ เชฌเชœเซ‡เชŸ-เชซเซเชฐเซ‡เช‚เชกเชฒเซ€ เชฐเซ€เชค เช›เซ‡, เชชเชฐเช‚เชคเซ เชคเชฎเชพเชฐเซ‡ เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชจเซ‹ เช•เชพเชณเชœเซ€เชชเซ‚เชฐเซเชตเช• เชชเชธเช‚เชฆ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡.
  • เชตเซเชฏเช•เซเชคเชฟเช—เชค เช•เซ‹เชกเชจเชพ เชŸเซเช•เชกเชพเช“เชจเซ€ เชเชกเชช เชฎเชพเชชเชตเซ€ เช เช–เซ‚เชฌ เชœ เช‰เชชเชฏเซ‹เช—เซ€ เช›เซ‡, เช–เชพเชธ เช•เชฐเซ€เชจเซ‡ เชœเซเชฏเชพเชฐเซ‡ R เช…เชจเซ‡ C++เชจเซเช‚ เชธเช‚เชฏเซ‹เชœเชจ เช…เชจเซ‡ เชชเซ‡เช•เซ‡เชœ เชธเชพเชฅเซ‡ เชฌเซ‡เชจเซเชš - เชชเชฃ เช–เซ‚เชฌ เชœ เชธเชฐเชณ.

เชเช•เช‚เชฆเชฐเซ‡ เช† เช…เชจเซเชญเชต เช–เซ‚เชฌ เชœ เชฒเชพเชญเชฆเชพเชฏเซ€ เชนเชคเซ‹ เช…เชจเซ‡ เช…เชฎเซ‡ เชŠเชญเชพ เชฅเชฏเซ‡เชฒเชพ เช•เซ‡เชŸเชฒเชพเช• เชฎเซเชฆเซเชฆเชพเช“เชจเซ‡ เช‰เช•เซ‡เชฒเชตเชพ เชฎเชพเชŸเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพเชจเซเช‚ เชšเชพเชฒเซ เชฐเชพเช–เซ€เช เช›เซ€เช.

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹