ΠΡΠΈΠ²Π΅Ρ, Π₯Π°Π±Ρ!
ΠΡΠ΅Π½ΡΡ ΠΏΡΠΎΡΠ»ΠΎΠ³ΠΎ Π³ΠΎΠ΄Π° Π½Π° Kaggle ΠΏΡΠΎΡ
ΠΎΠ΄ΠΈΠ» ΠΊΠΎΠ½ΠΊΡΡΡ ΠΏΠΎ ΠΊΠ»Π°ΡΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ Π½Π°ΡΠΈΡΠΎΠ²Π°Π½Π½ΡΡ
ΠΎΡ ΡΡΠΊΠΈ ΠΊΠ°ΡΡΠΈΠ½ΠΎΠΊ Quick Draw Doodle Recognition, Π² ΠΊΠΎΡΠΎΡΠΎΠΌ ΡΡΠ΅Π΄ΠΈ ΠΏΡΠΎΡΠΈΡ
ΠΏΠΎΡΡΠ°ΡΡΠ²ΠΎΠ²Π°Π»Π° ΠΊΠΎΠΌΠ°Π½Π΄Π° R-ΡΠΈΠΊΠΎΠ² Π² ΡΠΎΡΡΠ°Π²Π΅
Π‘ ΡΠ°ΡΠΌΠΎΠΌ ΠΌΠ΅Π΄Π°Π»Π΅ΠΊ Π² ΡΡΠΎΡ ΡΠ°Π· Π½Π΅ ΡΠ»ΠΎΠΆΠΈΠ»ΠΎΡΡ, Π½ΠΎ Π±ΡΠ»ΠΎ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ ΡΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΎΠΏΡΡΠ°, ΠΏΠΎΡΡΠΎΠΌΡ ΠΎ ΡΡΠ΄Π΅ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΡΡ
ΠΈ ΠΏΠΎΠ»Π΅Π·Π½ΡΡ
Π½Π° ΠΠ°Π³Π»Π΅ ΠΈ Π² ΠΏΠΎΠ²ΡΠ΅Π΄Π½Π΅Π²Π½ΠΎΠΉ ΡΠ°Π±ΠΎΡΠ΅ Π²Π΅ΡΠ΅ΠΉ Ρ
ΠΎΡΠ΅Π»ΠΎΡΡ Π±Ρ ΡΠ°ΡΡΠΊΠ°Π·Π°ΡΡ ΡΠΎΠΎΠ±ΡΠ΅ΡΡΠ²Ρ. Π‘ΡΠ΅Π΄ΠΈ ΡΠ°ΡΡΠΌΠΎΡΡΠ΅Π½Π½ΡΡ
ΡΠ΅ΠΌ: Π½Π΅Π»Π΅Π³ΠΊΠ°Ρ ΠΆΠΈΠ·Π½Ρ Π±Π΅Π· OpenCV, ΠΏΠ°ΡΡΠΈΠ½Π³ JSON-ΠΎΠ² (Π½Π° ΡΡΠΈΡ
ΠΏΡΠΈΠΌΠ΅ΡΠ°Ρ
ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°Π΅ΡΡΡ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ ΠΊΠΎΠ΄Π° Π½Π° Π‘++ Π² ΡΠΊΡΠΈΠΏΡΡ ΠΈΠ»ΠΈ ΠΏΠ°ΠΊΠ΅ΡΡ Π½Π° R ΠΏΠΎΡΡΠ΅Π΄ΡΡΠ²ΠΎΠΌ Rcpp), ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈΠ·Π°ΡΠΈΡ ΡΠΊΡΠΈΠΏΡΠΎΠ² ΠΈ Π΄ΠΎΠΊΠ΅ΡΠΈΠ·Π°ΡΠΈΡ ΠΈΡΠΎΠ³ΠΎΠ²ΠΎΠ³ΠΎ ΡΠ΅ΡΠ΅Π½ΠΈΡ. ΠΠ΅ΡΡ ΠΊΠΎΠ΄ ΠΈΠ· ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ Π² ΠΏΡΠΈΠ³ΠΎΠ΄Π½ΠΎΠΌ Π΄Π»Ρ Π·Π°ΠΏΡΡΠΊΠ° Π²ΠΈΠ΄Π΅ Π΄ΠΎΡΡΡΠΏΠ΅Π½ Π²
Π‘ΠΎΠ΄Π΅ΡΠΆΠ°Π½ΠΈΠ΅:
ΠΡΡΠ΅ΠΊΡΠΈΠ²Π½Π°Ρ Π·Π°Π³ΡΡΠ·ΠΊΠ° Π΄Π°Π½Π½ΡΡ ΠΈΠ· CSV Π² Π±Π°Π·Ρ MonetDB ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° Π±Π°ΡΡΠ΅ΠΉ ΠΡΠ΅ΡΠ°ΡΠΎΡΡ Π΄Π»Ρ Π²ΡΠ³ΡΡΠ·ΠΊΠΈ Π±Π°ΡΡΠ΅ΠΉ ΠΈΠ· ΠΠ ΠΡΠ±ΠΎΡ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈΠ·Π°ΡΠΈΡ ΡΠΊΡΠΈΠΏΡΠΎΠ² ΠΠΎΠΊΠ΅ΡΠΈΠ·Π°ΡΠΈΡ ΡΠΊΡΠΈΠΏΡΠΎΠ² ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ GPU Π² ΠΎΠ±Π»Π°ΠΊΠ΅ Google Cloud ΠΠΌΠ΅ΡΡΠΎ Π·Π°ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ
1. ΠΡΡΠ΅ΠΊΡΠΈΠ²Π½Π°Ρ Π·Π°Π³ΡΡΠ·ΠΊΠ° Π΄Π°Π½Π½ΡΡ ΠΈΠ· CSV Π² Π±Π°Π·Ρ MonetDB
ΠΠ°Π½Π½ΡΠ΅ Π² ΡΡΠΎΠΌ ΡΠΎΡΠ΅Π²Π½ΠΎΠ²Π°Π½ΠΈΠΈ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡΡΡ Π½Π΅ Π² Π²ΠΈΠ΄Π΅ Π³ΠΎΡΠΎΠ²ΡΡ ΠΊΠ°ΡΡΠΈΠ½ΠΎΠΊ, Π° Π² Π²ΠΈΠ΄Π΅ 340 CSV-ΡΠ°ΠΉΠ»ΠΎΠ² (ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡ ΡΠ°ΠΉΠ»Ρ Π½Π° ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΊΠ»Π°ΡΡ), ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΡ JSON-Ρ Ρ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ°ΠΌΠΈ ΡΠΎΡΠ΅ΠΊ. Π‘ΠΎΠ΅Π΄ΠΈΠ½ΠΈΠ² ΡΡΠΈ ΡΠΎΡΠΊΠΈ Π»ΠΈΠ½ΠΈΡΠΌΠΈ, ΠΌΡ ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΠΈΡΠΎΠ³ΠΎΠ²ΠΎΠ΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠΌ 256Ρ 256 ΠΏΠΈΠΊΡΠ΅Π»Π΅ΠΉ. Π’Π°ΠΊΠΆΠ΅ Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π·Π°ΠΏΠΈΡΠΈ ΠΏΡΠΈΠ²ΠΎΠ΄ΠΈΡΡΡ ΠΌΠ΅ΡΠΊΠ°, Π±ΡΠ»Π° Π»ΠΈ ΠΊΠ°ΡΡΠΈΠ½ΠΊΠ° ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π½Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΠΌ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ ΡΠ±ΠΎΡΠ° Π΄Π°ΡΠ°ΡΠ΅ΡΠ° ΠΊΠ»Π°ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΎΠΌ, Π΄Π²ΡΡ Π±ΡΠΊΠ²Π΅Π½Π½ΡΠΉ ΠΊΠΎΠ΄ ΡΡΡΠ°Π½Ρ ΠΏΡΠΎΠΆΠΈΠ²Π°Π½ΠΈΡ Π°Π²ΡΠΎΡΠ° ΡΠΈΡΡΠ½ΠΊΠ°, ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠΉ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ, ΠΌΠ΅ΡΠΊΠ° Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ ΠΈ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΊΠ»Π°ΡΡΠ°, ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡΡΠ΅Π΅ Ρ ΠΈΠΌΠ΅Π½Π΅ΠΌ ΡΠ°ΠΉΠ»Π°. Π£ΠΏΡΠΎΡΠ΅Π½Π½Π°Ρ Π²Π΅ΡΡΠΈΡ ΠΈΡΡ ΠΎΠ΄Π½ΡΡ Π΄Π°Π½Π½ΡΡ Π²Π΅ΡΠΈΡ 7.4 ΠΠ± Π² Π°ΡΡ ΠΈΠ²Π΅ ΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ 20 ΠΠ± ΠΏΠΎΡΠ»Π΅ ΡΠ°ΡΠΏΠ°ΠΊΠΎΠ²ΠΊΠΈ, ΠΏΠΎΠ»Π½ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ ΠΏΠΎΡΠ»Π΅ ΡΠ°ΡΠΏΠ°ΠΊΠΎΠ²ΠΊΠΈ Π·Π°Π½ΠΈΠΌΠ°ΡΡ 240 ΠΠ±. ΠΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΎΡΡ Π³Π°ΡΠ°Π½ΡΠΈΡΠΎΠ²Π°Π»ΠΈ, ΡΡΠΎ ΠΎΠ±Π΅ Π²Π΅ΡΡΠΈΠΈ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΡΡ ΠΎΠ΄Π½ΠΈ ΠΈ ΡΠ΅ ΠΆΠ΅ ΡΠΈΡΡΠ½ΠΊΠΈ, ΡΠΎ Π΅ΡΡΡ ΠΏΠΎΠ»Π½Π°Ρ Π²Π΅ΡΡΠΈΡ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΈΠ·Π±ΡΡΠΎΡΠ½ΠΎΠΉ. Π Π»ΡΠ±ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅, Ρ ΡΠ°Π½Π΅Π½ΠΈΠ΅ 50 ΠΌΠ»Π½. ΠΊΠ°ΡΡΠΈΠ½ΠΎΠΊ Π² Π³ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΡ ΡΠ°ΠΉΠ»Π°Ρ ΠΈΠ»ΠΈ Π² Π²ΠΈΠ΄Π΅ ΠΌΠ°ΡΡΠΈΠ²ΠΎΠ² ΡΡΠ°Π·Ρ Π±ΡΠ»ΠΎ ΠΏΡΠΈΠ·Π½Π°Π½ΠΎ Π½Π΅ΡΠ΅Π½ΡΠ°Π±Π΅Π»ΡΠ½ΡΠΌ, ΠΈ ΠΌΡ ΡΠ΅ΡΠΈΠ»ΠΈ ΡΠ»ΠΈΡΡ Π²ΡΠ΅ CSV-ΡΠ°ΠΉΠ»Ρ ΠΈΠ· Π°ΡΡ ΠΈΠ²Π° train_simplified.zip Π² Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ Ρ ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠ΅ΠΉ ΠΊΠ°ΡΡΠΈΠ½ΠΎΠΊ Π½ΡΠΆΠ½ΠΎΠ³ΠΎ ΡΠ°Π·ΠΌΠ΅ΡΠ° «Π½Π° Π»Π΅ΡΡ» Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π±Π°ΡΡΠ°.
Π ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ Π‘Π£ΠΠ Π±ΡΠ»Π° Π²ΡΠ±ΡΠ°Π½Π° Ρ
ΠΎΡΠΎΡΠΎ ΡΠ΅Π±Ρ Π·Π°ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΠΎΠ²Π°Π²ΡΠ°Ρ MonetDB, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π΄Π»Ρ 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 ΠΈΠ»ΠΈ Ρ ΡΠ»Π΅ΡΠΊΠΈ (ΠΈΡΡ ΠΎΠ΄Π½ΡΠΉ ΡΠ°ΠΉΠ») Π½Π° SSD (ΠΠ) Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ ΠΌΠ΅Π½Π΅Π΅ 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 ΠΠ± ΠΠΠ£. Π’ΠΎ Π΅ΡΡΡ ΠΎΠΏΠΈΡΠ°Π½Π½ΡΠΉ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π²ΠΎΡΠΎΡΠ°ΡΡ Π΄Π°ΡΠ°ΡΠ΅ΡΡ Π²Π΅ΡΠΎΠΌ Π² Π΄Π΅ΡΡΡΠΊΠΈ Π³ΠΈΠ³Π°Π±Π°ΠΉΡ ΠΏΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ Π½Π° Π»ΡΠ±ΠΎΠΌ Π±ΡΠ΄ΠΆΠ΅ΡΠ½ΠΎΠΌ ΠΆΠ΅Π»Π΅Π·Π΅, Π²ΠΊΠ»ΡΡΠ°Ρ Π½Π΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΎΠ΄Π½ΠΎΠΏΠ»Π°ΡΠ½ΠΈΠΊΠΈ, ΡΡΠΎ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΠΊΡΡΡΠΎ.
ΠΡΡΠ°Π΅ΡΡΡ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ Π·Π°ΠΌΠ΅ΡΡ ΡΠΊΠΎΡΠΎΡΡΠΈ ΠΈΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΡ (ΡΠ»ΡΡΠ°ΠΉΠ½ΡΡ ) Π΄Π°Π½Π½ΡΡ ΠΈ ΠΎΡΠ΅Π½ΠΈΡΡ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡΠΈ Π²ΡΠ±ΠΎΡΠΊΠ΅ Π±Π°ΡΡΠ΅ΠΉ ΡΠ°Π·Π½ΠΎΠ³ΠΎ ΡΠ°Π·ΠΌΠ΅ΡΠ°:
ΠΠ΅Π½ΡΠΌΠ°ΡΠΊ Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ
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)
2. ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° Π±Π°ΡΡΠ΅ΠΉ
ΠΠ΅ΡΡ ΠΏΡΠΎΡΠ΅ΡΡ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠΈ Π±Π°ΡΡΠ΅ΠΉ ΡΠΎΡΡΠΎΠΈΡ ΠΈΠ· ΡΠ»Π΅Π΄ΡΡΡΠΈΡ ΡΡΠ°ΠΏΠΎΠ²:
- ΠΠ°ΡΡΠΈΠ½Π³ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ JSON-ΠΎΠ², ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΡ Π²Π΅ΠΊΡΠΎΡΡ ΡΡΡΠΎΠΊ Ρ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ°ΠΌΠΈ ΡΠΎΡΠ΅ΠΊ.
- ΠΡΡΠΈΡΠΎΠ²ΠΊΠ° ΡΠ²Π΅ΡΠ½ΡΡ Π»ΠΈΠ½ΠΈΠΉ ΠΏΠΎ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ°ΠΌ ΡΠΎΡΠ΅ΠΊ Π½Π° ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΈ Π½ΡΠΆΠ½ΠΎΠ³ΠΎ ΡΠ°Π·ΠΌΠ΅ΡΠ° (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, 256×256 ΠΈΠ»ΠΈ 128×128).
- ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΡ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ Π² ΡΠ΅Π½Π·ΠΎΡ.
Π ΡΠ°ΠΌΠΊΠ°Ρ ΡΠΎΡΠ΅Π²Π½ΠΎΠ²Π°Π½ΠΈΡ ΡΡΠ΅Π΄ΠΈ kernel-ΠΎΠ² Π½Π° Python Π·Π°Π΄Π°ΡΠ° ΡΠ΅ΡΠ°Π»Π°ΡΡ ΠΏΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΠΎ ΡΡΠ΅Π΄ΡΡΠ²Π°ΠΌΠΈ OpenCV. ΠΠ΄ΠΈΠ½ ΠΈΠ· Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ ΠΏΡΠΎΡΡΡΡ ΠΈ ΠΎΡΠ΅Π²ΠΈΠ΄Π½ΡΡ Π°Π½Π°Π»ΠΎΠ³ΠΎΠ² Π½Π° R Π±ΡΠ΄Π΅Ρ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ:
Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΡ JSON Π² ΡΠ΅Π½Π·ΠΎΡ Π½Π° 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, Ρ
ΡΠ°Π½ΡΡΠΈΠΉΡΡ Π² ΠΠΠ£ (Π² Linux Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΠΈ R Π½Π°Ρ
ΠΎΠ΄ΡΡΡΡ Π² ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π΅ /tmp
, ΡΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΌ Π² ΠΠΠ£). ΠΠ°ΡΠ΅ΠΌ ΡΡΠΎΡ ΡΠ°ΠΉΠ» ΡΡΠΈΡΡΠ²Π°Π΅ΡΡΡ Π² Π²ΠΈΠ΄Π΅ ΡΡΡΡ
ΠΌΠ΅ΡΠ½ΠΎΠ³ΠΎ ΠΌΠ°ΡΡΠΈΠ²Π° Ρ ΡΠΈΡΠ»Π°ΠΌΠΈ Π² Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅ ΠΎΡ 0 Π΄ΠΎ 1. ΠΡΠΎ Π²Π°ΠΆΠ½ΠΎ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π±ΠΎΠ»Π΅Π΅ ΠΎΠ±ΡΠ΅ΠΏΡΠΈΠ½ΡΡΡΠΉ BMP Π±ΡΠ» Π±Ρ ΠΏΡΠΎΡΠΈΡΠ°Π½ Π² raw-ΠΌΠ°ΡΡΠΈΠ² Ρ 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))
Π‘Π°ΠΌ Π±Π°ΡΡ Π±ΡΠ΄Π΅Ρ ΡΠΎΡΠΌΠΈΡΠΎΠ²Π°ΡΡΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ:
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.
ΠΠ»Ρ ΡΠ΅ΡΠ΅Π½ΠΈΡ Π·Π°Π΄Π°ΡΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈΡΡ ΡΠ»Π΅Π΄ΡΡΠΈΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ:
-
OpenCV Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡΠΌΠΈ ΠΈ ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π»ΠΈΠ½ΠΈΠΉ. ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½Π½ΡΠ΅ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ ΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡΠ½ΡΠ΅ ΡΠ°ΠΉΠ»Ρ, Π° ΡΠ°ΠΊΠΆΠ΅ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΡΡ Π»ΠΈΠ½ΠΊΠΎΠ²ΠΊΡ.
-
xtensor Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΌΠ½ΠΎΠ³ΠΎΠΌΠ΅ΡΠ½ΡΠΌΠΈ ΠΌΠ°ΡΡΠΈΠ²Π°ΠΌΠΈ ΠΈ ΡΠ΅Π½Π·ΠΎΡΠ°ΠΌΠΈ. ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡΠ½ΡΠ΅ ΡΠ°ΠΉΠ»Ρ, Π²ΠΊΠ»ΡΡΡΠ½Π½ΡΠ΅ Π² ΠΎΠ΄Π½ΠΎΠΈΠΌΡΠ½Π½ΡΠΉ R-ΠΏΠ°ΠΊΠ΅Ρ. ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ ΠΌΠ½ΠΎΠ³ΠΎΠΌΠ΅ΡΠ½ΡΠΌΠΈ ΠΌΠ°ΡΡΠΈΠ²Π°ΠΌΠΈ, ΠΏΡΠΈΡΡΠΌ ΠΊΠ°ΠΊ Π² row major, ΡΠ°ΠΊ ΠΈ Π² column major ΠΏΠΎΡΡΠ΄ΠΊΠ΅.
-
ndjson Π΄Π»Ρ ΠΏΠ°ΡΡΠΈΠ½Π³Π° JSON. ΠΠ°Π½Π½Π°Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π² xtensor Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΏΡΠΈ Π΅Ρ Π½Π°Π»ΠΈΡΠΈΠΈ Π² ΠΏΡΠΎΠ΅ΠΊΡΠ΅.
-
RcppThread Π΄Π»Ρ ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡΠΎΡΠ½ΠΎΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π²Π΅ΠΊΡΠΎΡΠ° ΠΈΠ· JSON-ΠΎΠ². ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡΠ½ΡΠ΅ ΡΠ°ΠΉΠ»Ρ, ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅ΠΌΡΠ΅ ΡΡΠΈΠΌ ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ. ΠΡ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠΏΡΠ»ΡΡΠ½ΠΎΠ³ΠΎ RcppParallel ΠΏΠ°ΠΊΠ΅Ρ ΡΡΠ΅Π΄ΠΈ ΠΏΡΠΎΡΠ΅Π³ΠΎ ΠΎΡΠ»ΠΈΡΠ°Π΅ΡΡΡ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠΌ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌΠΎΠΌ ΠΏΡΠ΅ΡΡΠ²Π°Π½ΠΈΡ ΡΠΈΠΊΠ»Π° (interrupt).
Π‘ΡΠΎΠΈΡ ΠΎΡΠΌΠ΅ΡΠΈΡΡ, ΡΡΠΎ xtensor ΠΎΠΊΠ°Π·Π°Π»ΡΡ ΠΏΡΠΎΡΡΠΎ Π½Π°Ρ ΠΎΠ΄ΠΊΠΎΠΉ: ΠΊΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, ΡΡΠΎ ΠΎΠ½ ΠΎΠ±Π»Π°Π΄Π°Π΅Ρ ΠΎΠ±ΡΠΈΡΠ½ΡΠΌ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»ΠΎΠΌ ΠΈ Π²ΡΡΠΎΠΊΠΎΠΉ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡΡ, Π΅Π³ΠΎ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΠΎΠΊΠ°Π·Π°Π»ΠΈΡΡ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΠΎΡΠ·ΡΠ²ΡΠΈΠ²ΡΠΌΠΈ ΠΈ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²Π½ΠΎ ΠΈ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ ΠΎΡΠ²Π΅ΡΠ°Π»ΠΈ Π½Π° Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡΡΠΈΠ΅ Π²ΠΎΠΏΡΠΎΡΡ. Π‘ ΠΈΡ ΠΏΠΎΠΌΠΎΡΡΡ ΡΠ΄Π°Π»ΠΎΡΡ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΡ ΠΌΠ°ΡΡΠΈΡ OpenCV Π² ΡΠ΅Π½Π·ΠΎΡΡ xtensor, Π° ΡΠ°ΠΊΠΆΠ΅ ΡΠΏΠΎΡΠΎΠ± ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ 3-Ρ ΠΌΠ΅ΡΠ½ΡΡ ΡΠ΅Π½Π·ΠΎΡΠΎΠ² ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ Π² 4-Ρ ΠΌΠ΅ΡΠ½ΡΠΉ ΡΠ΅Π½Π·ΠΎΡ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎΠΉ ΡΠ°Π·ΠΌΠ΅ΡΠ½ΠΎΡΡΠΈ (ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ Π±Π°ΡΡ).
ΠΠ°ΡΠ΅ΡΠΈΠ°Π»Ρ Π΄Π»Ρ ΠΈΠ·ΡΡΠ΅Π½ΠΈΡ Rcpp, xtensor ΠΈ RcppThread
ΠΠ»Ρ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ ΡΠ°ΠΉΠ»ΠΎΠ², ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΠΈΡ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΠ΅ ΡΠ°ΠΉΠ»Ρ ΠΈ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΡΡ Π»ΠΈΠ½ΠΊΠΎΠ²ΠΊΡ Ρ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½Π½ΡΠΌΠΈ Π² ΡΠΈΡΡΠ΅ΠΌΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΠΌΠΈ, ΠΌΡ Π²ΠΎΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈΡΡ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌΠΎΠΌ ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠ², ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΡΠΌ Π² ΠΏΠ°ΠΊΠ΅ΡΠ΅ Rcpp. ΠΠ»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ Π½Π°Ρ ΠΎΠΆΠ΄Π΅Π½ΠΈΡ ΠΏΡΡΠ΅ΠΉ ΠΈ ΡΠ»Π°Π³ΠΎΠ² ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈ ΠΏΠΎΠΏΡΠ»ΡΡΠ½ΡΡ linux-ΡΡΠΈΠ»ΠΈΡΡ pkg-config.
Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ 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)
))
})
Π ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ΅ ΡΠ°Π±ΠΎΡΡ ΠΏΠ»Π°Π³ΠΈΠ½Π° Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ Π±ΡΠ΄ΡΡ ΠΏΠΎΠ΄ΡΡΠ°Π²Π»Π΅Π½Ρ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ:
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"))))
Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΡ 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
, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΠΊΡΠΏΠΎΡΡΠΈΡΡΠ΅Ρ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ Π² R-ΠΎΠ±ΡΠ΅ΠΊΡ (ΠΌΠ½ΠΎΠ³ΠΎΠΌΠ΅ΡΠ½ΡΠΉ ΠΌΠ°ΡΡΠΈΠ²); -
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 ΠΈ Π‘++
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")
ΠΠ°ΠΊ Π²ΠΈΠ΄ΠΈΠΌ, ΠΏΡΠΈΡΠΎΡΡ ΡΠΊΠΎΡΠΎΡΡΠΈ ΠΎΠΊΠ°Π·Π°Π»ΡΡ ΠΎΡΠ΅Π½Ρ Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΡΠΌ, ΠΈ Π΄ΠΎΠ³Π½Π°ΡΡ ΠΊΠΎΠ΄ Π½Π° C++ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΊΠΎΠ΄Π° Π½Π° R Π½Π΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΠΌ.
3. ΠΡΠ΅ΡΠ°ΡΠΎΡΡ Π΄Π»Ρ Π²ΡΠ³ΡΡΠ·ΠΊΠΈ Π±Π°ΡΡΠ΅ΠΉ ΠΈΠ· ΠΠ
R ΠΈΠΌΠ΅Π΅Ρ Π·Π°ΡΠ»ΡΠΆΠ΅Π½Π½ΡΡ ΡΠ΅ΠΏΡΡΠ°ΡΠΈΡ ΡΠ·ΡΠΊΠ° Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π΄Π°Π½Π½ΡΡ , ΠΏΠΎΠΌΠ΅ΡΠ°ΡΡΠΈΡ ΡΡ Π² ΠΠΠ£, Π² ΡΠΎ Π²ΡΠ΅ΠΌΡ ΠΊΠ°ΠΊ Π΄Π»Ρ ΠΠΈΡΠΎΠ½Π° Π±ΠΎΠ»Π΅Π΅ Ρ Π°ΡΠ°ΠΊΡΠ΅ΡΠ½Π° ΠΈΡΠ΅ΡΠ°ΡΠΈΠ²Π½Π°Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° Π΄Π°Π½Π½ΡΡ , ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡΠ°Ρ Π»Π΅Π³ΠΊΠΎ ΠΈ Π½Π΅ΠΏΡΠΈΠ½ΡΠΆΠ΄Π΅Π½Π½ΠΎ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²ΡΠ²Π°ΡΡ out-of-core Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ (Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Π²Π½Π΅ΡΠ½Π΅ΠΉ ΠΏΠ°ΠΌΡΡΠΈ). ΠΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΈΠΌ ΠΈ Π°ΠΊΡΡΠ°Π»ΡΠ½ΡΠΌ Π΄Π»Ρ Π½Π°Ρ Π² ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ΅ ΠΎΠΏΠΈΡΡΠ²Π°Π΅ΠΌΠΎΠΉ Π·Π°Π΄Π°ΡΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠΌ ΡΠ°ΠΊΠΈΡ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΠΉ ΡΠ²Π»ΡΡΡΡΡ Π³Π»ΡΠ±ΠΎΠΊΠΈΠ΅ Π½Π΅ΠΉΡΠΎΠ½Π½ΡΠ΅ ΡΠ΅ΡΠΈ, ΠΎΠ±ΡΡΠ°Π΅ΠΌΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠΌ Π³ΡΠ°Π΄ΠΈΠ΅Π½ΡΠ½ΠΎΠ³ΠΎ ΡΠΏΡΡΠΊΠ° Ρ Π°ΠΏΠΏΡΠΎΠΊΡΠΈΠΌΠ°ΡΠΈΠ΅ΠΉ Π³ΡΠ°Π΄ΠΈΠ΅Π½ΡΠ° Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΡΠ°Π³Π΅ ΠΏΠΎ Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΉ ΠΏΠΎΡΡΠΈΠΈ Π½Π°Π±Π»ΡΠ΄Π΅Π½ΠΈΠΉ, ΠΈΠ»ΠΈ ΠΌΠΈΠ½ΠΈ-Π±Π°ΡΡΡ.
Π€ΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠΈ Π΄Π»Ρ Π³Π»ΡΠ±ΠΎΠΊΠΎΠ³ΠΎ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ, Π½Π°ΠΏΠΈΡΠ°Π½Π½ΡΠ΅ Π½Π° Python, ΠΈΠΌΠ΅ΡΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΠ΅ ΠΊΠ»Π°ΡΡΡ, ΡΠ΅Π°Π»ΠΈΠ·ΡΡΡΠΈΠ΅ ΠΈΡΠ΅ΡΠ°ΡΠΎΡΡ ΠΏΠΎ Π΄Π°Π½Π½ΡΠΌ: ΡΠ°Π±Π»ΠΈΡΠ°ΠΌΠΈ, ΠΊΠ°ΡΡΠΈΠ½ΠΊΠ°ΠΌ Π² ΠΏΠ°ΠΏΠΊΠ°Ρ , Π±ΠΈΠ½Π°ΡΠ½ΡΠΌ ΡΠΎΡΠΌΠ°ΡΠ°ΠΌ ΠΈ ΠΏΡ. ΠΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π³ΠΎΡΠΎΠ²ΡΠ΅ Π²Π°ΡΠΈΠ°Π½ΡΡ ΠΈΠ»ΠΈ ΠΆΠ΅ ΠΏΠΈΡΠ°ΡΡ ΡΠ²ΠΎΠΈ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ Π΄Π»Ρ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈΡ Π·Π°Π΄Π°Ρ. Π R ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ Π²ΠΎΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡΡΡ Π²ΡΠ΅ΠΌΠΈ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡΠΌΠΈ ΠΏΠΈΡΠΎΠ½ΠΎΠ²ΡΠΊΠΎΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ keras Ρ Π΅Π³ΠΎ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠΌΠΈ Π±Π΅ΠΊΠ΅Π½Π΄Π°ΠΌΠΈ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΠΎΠ΄Π½ΠΎΠΈΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠ°, Π² ΡΠ²ΠΎΡ ΠΎΡΠ΅ΡΠ΅Π΄Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡΠ΅Π³ΠΎ ΠΏΠΎΠ²Π΅ΡΡ ΠΏΠ°ΠΊΠ΅ΡΠ° reticulate. ΠΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ Π·Π°ΡΠ»ΡΠΆΠΈΠ²Π°Π΅Ρ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎΠΉ Π±ΠΎΠ»ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠΈ; ΠΎΠ½ Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ ΠΊΠΎΠ΄ Π½Π° Python ΠΈΠ· R, Π½ΠΎ ΠΈ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Π΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΠΌΠ΅ΠΆΠ΄Ρ R- ΠΈ Python-ΡΠ΅ΡΡΠΈΡΠΌΠΈ, Π°Π²ΡΠΎΠΌΠ°Π³ΠΈΡΠ΅ΡΠΊΠΈ Π²ΡΠΏΠΎΠ»Π½ΡΡ Π²ΡΠ΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΡΠ΅ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΡ ΡΠΈΠΏΠΎΠ².
ΠΡ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ Ρ ΡΠ°Π½ΠΈΡΡ Π²ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ Π² ΠΠΠ£ ΠΌΡ ΠΈΠ·Π±Π°Π²ΠΈΠ»ΠΈΡΡ Π·Π° ΡΡΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ MonetDBLite, Π²ΡΡ «Π½Π΅ΠΉΡΠΎΡΠ΅ΡΠ΅Π²ΡΡ» ΡΠ°Π±ΠΎΡΡ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»ΡΠ½ΡΠΉ ΠΊΠΎΠ΄ Π½Π° Python, Π½Π°ΠΌ ΠΎΡΡΠ°Π΅ΡΡΡ Π»ΠΈΡΡ Π½Π°ΠΏΠΈΡΠ°ΡΡ ΠΈΡΠ΅ΡΠ°ΡΠΎΡ ΠΏΠΎ Π΄Π°Π½Π½ΡΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π³ΠΎΡΠΎΠ²ΠΎΠ³ΠΎ Π΄Π»Ρ ΡΠ°ΠΊΠΎΠΉ ΡΠΈΡΡΠ°ΡΠΈΠΈ Π½Π΅Ρ Π½ΠΈ Π½Π° R, Π½ΠΈ Π½Π° Python. Π’ΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΠΉ ΠΊ Π½Π΅ΠΌΡ ΠΏΠΎ ΡΡΡΠΈ Π²ΡΠ΅Π³ΠΎ Π΄Π²Π°: ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ Π±Π°ΡΡΠΈ Π² Π±Π΅ΡΠΊΠΎΠ½Π΅ΡΠ½ΠΎΠΌ ΡΠΈΠΊΠ»Π΅ ΠΈ ΡΠΎΡ ΡΠ°Π½ΡΡΡ ΡΠ²ΠΎΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρ ΠΈΡΠ΅ΡΠ°ΡΠΈΡΠΌΠΈ (ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π΅ Π² R ΠΏΡΠΎΡΡΠ΅ΠΉΡΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ ΡΠ΅Π°Π»ΠΈΠ·ΡΠ΅ΡΡΡ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ Π·Π°ΠΌΡΠΊΠ°Π½ΠΈΠΉ). Π Π°Π½Π΅Π΅ ΡΡΠ΅Π±ΠΎΠ²Π°Π»ΠΎΡΡ Π²Π½ΡΡΡΠΈ ΠΈΡΠ΅ΡΠ°ΡΠΎΡΠ° ΡΠ²Π½ΡΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²ΡΠ²Π°ΡΡ ΠΌΠ°ΡΡΠΈΠ²Ρ R Π² numpy-ΠΌΠ°ΡΡΠΈΠ²Ρ, Π½ΠΎ Π°ΠΊΡΡΠ°Π»ΡΠ½Π°Ρ Π²Π΅ΡΡΠΈΡ ΠΏΠ°ΠΊΠ΅ΡΠ° keras Π΄Π΅Π»Π°Π΅Ρ ΡΡΠΎ ΡΠ°ΠΌΠ°.
ΠΡΠ΅ΡΠ°ΡΠΎΡ Π΄Π»Ρ ΠΎΠ±ΡΡΠ°ΡΡΠΈΡ ΠΈ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΎΠ½Π½ΡΡ Π΄Π°Π½Π½ΡΡ ΠΏΠΎΠ»ΡΡΠΈΠ»ΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΌ:
ΠΡΠ΅ΡΠ°ΡΠΎΡ Π΄Π»Ρ ΠΎΠ±ΡΡΠ°ΡΡΠΈΡ ΠΈ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΎΠ½Π½ΡΡ Π΄Π°Π½Π½ΡΡ
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
ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΠ΅Ρ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠ΅ ΠΊΠ°ΡΡΠΈΠ½ΠΎΠΊ 256Ρ
256 ΠΏΠΈΠΊΡΠ΅Π»Π΅ΠΉ, scale = 0.5
β 128Ρ
128 ΠΏΠΈΠΊΡΠ΅Π»Π΅ΠΉ), ΠΈΠ½Π΄ΠΈΠΊΠ°ΡΠΎΡ ΡΠ²Π΅ΡΠ½ΠΎΡΡΠΈ (color = FALSE
Π·Π°Π΄Π°Π΅Ρ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΡ Π² ΠΎΡΡΠ΅Π½ΠΊΠ°Ρ
ΡΠ΅ΡΠΎΠ³ΠΎ, ΠΏΡΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠΈ color = TRUE
ΠΊΠ°ΠΆΠ΄ΡΠΉ ΡΡΡΠΈΡ
ΡΠΈΡΡΠ΅ΡΡΡ Π½ΠΎΠ²ΡΠΌ ΡΠ²Π΅ΡΠΎΠΌ) ΠΈ ΠΈΠ½Π΄ΠΈΠΊΠ°ΡΠΎΡ ΠΏΡΠ΅ΠΏΡΠΎΡΠ΅ΡΡΠΈΠ½Π³Π° Π΄Π»Ρ ΡΠ΅ΡΠ΅ΠΉ, ΠΏΡΠ΅Π΄ΠΎΠ±ΡΡΠ΅Π½Π½ΡΡ
Π½Π° imagenet-Π΅. ΠΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ Π½ΡΠΆΠ΅Π½ Π΄Π»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΠΎΡΡΠΊΠ°Π»ΠΈΡΠΎΠ²Π°ΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠΈΠΊΡΠ΅Π»Π΅ΠΉ Ρ ΠΈΠ½ΡΠ΅ΡΠ²Π°Π»Π° [0, 1] Π½Π° ΠΈΠ½ΡΠ΅ΡΠ²Π°Π» [-1, 1], ΠΊΠΎΡΠΎΡΡΠΉ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΡΡ ΠΏΡΠΈ ΠΎΠ±ΡΡΠ΅Π½ΠΈΠΈ ΠΏΠΎΡΡΠ°Π²Π»ΡΠ΅ΠΌΡΡ
Π² ΡΠΎΡΡΠ°Π²Π΅ keras ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ.
ΠΠ½Π΅ΡΠ½ΡΡ ΡΡΠ½ΠΊΡΠΈΡ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΏΡΠΎΠ²Π΅ΡΠΊΡ ΡΠΈΠΏΠΎΠ² Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠΎΠ², ΡΠ°Π±Π»ΠΈΡΡ data.table
ΡΠΎ ΡΠ»ΡΡΠ°ΠΉΠ½ΡΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ ΠΏΠ΅ΡΠ΅ΠΌΠ΅ΡΠ°Π½Π½ΡΠΌΠΈ Π½ΠΎΠΌΠ΅ΡΠ°ΠΌΠΈ ΡΡΡΠΎΠΊ ΠΈΠ· samples_index
ΠΈ Π½ΠΎΠΌΠ΅ΡΠ°ΠΌΠΈ Π±Π°ΡΡΠ΅ΠΉ, ΡΡΠ΅ΡΡΠΈΠΊ ΠΈ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΡΠΈΡΠ»ΠΎ Π±Π°ΡΡΠ΅ΠΉ, Π° ΡΠ°ΠΊΠΆΠ΅ SQL-Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ Π΄Π»Ρ Π²ΡΠ³ΡΡΠ·ΠΊΠΈ Π΄Π°Π½Π½ΡΡ
ΠΈΠ· ΠΠ. ΠΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΌΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΠ»ΠΈ Π²Π½ΡΡΡΠΈ Π±ΡΡΡΡΡΠΉ Π°Π½Π°Π»ΠΎΠ³ ΡΡΠ½ΠΊΡΠΈΠΈ keras::to_categorical()
. ΠΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈ Π΄Π»Ρ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ ΠΏΠΎΡΡΠΈ Π²ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅, ΠΎΡΡΠ°Π²ΠΈΠ² ΠΏΠΎΠ»ΠΏΡΠΎΡΠ΅Π½ΡΠ° Π΄Π»Ρ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΈ, ΠΏΠΎΡΡΠΎΠΌΡ ΡΠ°Π·ΠΌΠ΅Ρ ΡΠΏΠΎΡ
ΠΈ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΠ²Π°Π»ΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠΌ steps_per_epoch
ΠΏΡΠΈ Π²ΡΠ·ΠΎΠ²Π΅ keras::fit_generator()
, ΠΈ ΡΡΠ»ΠΎΠ²ΠΈΠ΅ if (i > max_i)
ΡΡΠ°Π±Π°ΡΡΠ²Π°Π»ΠΎ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΎΠ½Π½ΠΎΠ³ΠΎ ΠΈΡΠ΅ΡΠ°ΡΠΎΡΠ°.
ΠΠΎ Π²Π½ΡΡΡΠ΅Π½Π½Π΅ΠΉ ΡΡΠ½ΠΊΡΠΈΠΈ ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ Π²ΡΠ±ΠΎΡΠΊΠ° ΠΈΠ½Π΄Π΅ΠΊΡΠΎΠ² ΡΡΡΠΎΠΊ Π΄Π»Ρ ΠΎΡΠ΅ΡΠ΅Π΄Π½ΠΎΠ³ΠΎ Π±Π°ΡΡΠ°, Π²ΡΠ³ΡΡΠ·ΠΊΠ° Π·Π°ΠΏΠΈΡΠ΅ΠΉ ΠΈΠ· ΠΠ Ρ ΡΠ²Π΅Π»ΠΈΡΠ΅Π½ΠΈΠ΅ΠΌ ΡΡΠ΅ΡΡΠΈΠΊΠ° Π±Π°ΡΡΠ΅ΠΉ, ΠΏΠ°ΡΡΠΈΠ½Π³ JSON-ΠΎΠ² (ΡΡΠ½ΠΊΡΠΈΡ cpp_process_json_vector()
, Π½Π°ΠΏΠΈΡΠ°Π½Π½Π°Ρ Π½Π° C++) ΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΌΠ°ΡΡΠΈΠ²ΠΎΠ², ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΡ
ΠΊΠ°ΡΡΠΈΠ½ΠΊΠ°ΠΌ. ΠΠ°ΡΠ΅ΠΌ ΡΠΎΠ·Π΄Π°ΡΡΡΡ one-hot Π²Π΅ΠΊΡΠΎΡΡ Ρ ΠΌΠ΅ΡΠΊΠ°ΠΌΠΈ ΠΊΠ»Π°ΡΡΠΎΠ², ΠΌΠ°ΡΡΠΈΠ²Ρ ΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΡΠΌΠΈ ΠΏΠΈΠΊΡΠ΅Π»Π΅ΠΉ ΠΈ Ρ ΠΌΠ΅ΡΠΊΠ°ΠΌΠΈ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½ΡΡΡΡΡ Π² ΡΠΏΠΈΡΠΎΠΊ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΈ ΡΠ²Π»ΡΠ΅ΡΡΡ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΡΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ. ΠΠ»Ρ ΡΡΠΊΠΎΡΠ΅Π½ΠΈΡ ΡΠ°Π±ΠΎΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΎΡΡ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈΠ½Π΄Π΅ΠΊΡΠΎΠ² Π² ΡΠ°Π±Π»ΠΈΡΠ°Ρ
data.table
ΠΈ ΠΌΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΠΏΠΎ ΡΡΡΠ»ΠΊΠ΅ β Π±Π΅Π· ΡΡΠΈΡ
«ΡΠΈΡΠ΅ΠΊ» ΠΏΠ°ΠΊΠ΅ΡΠ° data.table Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΡΡΡΠ΄Π½ΠΎ ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΠΈΡΡ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΡΡ ΡΠ°Π±ΠΎΡΡ ΡΠΎ ΡΠΊΠΎΠ»ΡΠΊΠΎ-Π½ΠΈΠ±ΡΠ΄Ρ Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΡΠΌΠΈ ΠΎΠ±ΡΠ΅ΠΌΠ°ΠΌΠΈ Π΄Π°Π½Π½ΡΡ
Π² R.
Π Π΅Π·ΡΠ»ΡΡΠ°ΡΡ Π·Π°ΠΌΠ΅ΡΠΎΠ² ΡΠΊΠΎΡΠΎΡΡΠΈ ΡΠ°Π±ΠΎΡΡ Π½Π° Π½ΠΎΡΡΠ±ΡΡΠ½ΠΎΠΌ Core 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)
ΠΡΠ»ΠΈ ΠΈΠΌΠ΅Π΅ΡΡΡ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΌ ΠΠΠ£, ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΅ΡΡΠ΅Π·Π½ΠΎ ΡΡΠΊΠΎΡΠΈΡΡ ΡΠ°Π±ΠΎΡΡ Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ
ΠΏΡΡΠ΅ΠΌ Π΅Π΅ ΠΏΠ΅ΡΠ΅Π½ΠΎΡΠ° Π² ΡΡΡ ΡΠ°ΠΌΡΡ ΠΠΠ£ (Π΄Π»Ρ Π½Π°ΡΠ΅ΠΉ Π·Π°Π΄Π°ΡΠΈ Ρ
Π²Π°ΡΠ°Π΅Ρ 32 ΠΠ±). Π Π»ΠΈΠ½ΡΠΊΡΠ΅ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ΠΌΠΎΠ½ΡΠΈΡΡΠ΅ΡΡΡ ΡΠ°Π·Π΄Π΅Π» /dev/shm
, Π·Π°Π½ΠΈΠΌΠ°ΡΡΠΈΠΉ Π΄ΠΎ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Ρ ΠΎΠ±ΡΠ΅ΠΌΠ° ΠΠΠ£. ΠΠΎΠΆΠ½ΠΎ Π²ΡΠ΄Π΅Π»ΠΈΡΡ ΠΈ Π±ΠΎΠ»ΡΡΠ΅, ΠΎΡΡΠ΅Π΄Π°ΠΊΡΠΈΡΠΎΠ²Π°Π² /etc/fstab
, ΡΡΠΎΠ±Ρ ΠΏΠΎΠ»ΡΡΠΈΠ»Π°ΡΡ Π·Π°ΠΏΠΈΡΡ Π²ΠΈΠ΄Π° tmpfs /dev/shm tmpfs defaults,size=25g 0 0
. ΠΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π·Π°Π³ΡΡΠΆΠ°Π΅ΠΌΡΡ ΠΈ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ, Π²ΡΠΏΠΎΠ»Π½ΠΈΠ² ΠΊΠΎΠΌΠ°Π½Π΄Ρ df -h
.
ΠΡΠ΅ΡΠ°ΡΠΎΡ Π΄Π»Ρ ΡΠ΅ΡΡΠΎΠ²ΡΡ Π΄Π°Π½Π½ΡΡ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ Π³ΠΎΡΠ°Π·Π΄ΠΎ ΠΏΡΠΎΡΠ΅, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΡΠ΅ΡΡΠΎΠ²ΡΠΉ Π΄Π°ΡΠ°ΡΠ΅Ρ ΡΠ΅Π»ΠΈΠΊΠΎΠΌ ΠΏΠΎΠΌΠ΅ΡΠ°Π΅ΡΡΡ Π² ΠΠΠ£:
ΠΡΠ΅ΡΠ°ΡΠΎΡ Π΄Π»Ρ ΡΠ΅ΡΡΠΎΠ²ΡΡ Π΄Π°Π½Π½ΡΡ
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. ΠΡΠ±ΠΎΡ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ ΠΌΠΎΠ΄Π΅Π»ΠΈ
ΠΠ΅ΡΠ²ΠΎΠΉ ΠΈΠ· ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½Π½ΡΡ
Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡ Π±ΡΠ»Π° (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-ΠΎΠ²ΡΠΊΠΈΡ
ΠΌΠ°ΡΡΠΈΠ²ΠΎΠ², ΠΈΠ·ΠΌΠ΅Π½ΠΈΡΡ ΡΠ°Π·ΠΌΠ΅ΡΠ½ΠΎΡΡΡ ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ° ΡΡΠΎΠ³ΠΎ ΡΠΏΠΈΡΠΊΠ° (Π²Π·ΡΠ² ΠΊΠ°ΠΊΠΎΠΉ-ΡΠΎ ΠΎΠ΄ΠΈΠ½ ΡΠ²Π΅ΡΠΎΠ²ΠΎΠΉ ΠΊΠ°Π½Π°Π» ΠΈΠ»ΠΈ ΡΡΡΠ΅Π΄Π½ΠΈΠ² Π²ΡΠ΅ ΡΡΠΈ), Π° Π·Π°ΡΠ΅ΠΌ Π·Π°Π³ΡΡΠ·ΠΈΡΡ Π²Π΅ΡΠ° ΠΎΠ±ΡΠ°ΡΠ½ΠΎ Π² ΠΌΠΎΠ΄Π΅Π»Ρ ΡΡΠ½ΠΊΡΠΈΠ΅ΠΉ set_weights()
. ΠΡ ΡΡΠΎΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π» ΡΠ°ΠΊ ΠΈ Π½Π΅ Π΄ΠΎΠ±Π°Π²ΠΈΠ»ΠΈ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π½Π° ΡΡΠΎΠΌ ΡΡΠ°ΠΏΠ΅ ΡΠΆΠ΅ Π±ΡΠ»ΠΎ ΠΏΠΎΠ½ΡΡΠ½ΠΎ, ΡΡΠΎ ΠΏΡΠΎΠ΄ΡΠΊΡΠΈΠ²Π½Π΅Π΅ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ ΡΠ²Π΅ΡΠ½ΡΠΌΠΈ ΠΊΠ°ΡΡΠΈΠ½ΠΊΠ°ΠΌΠΈ.
ΠΡΠ½ΠΎΠ²Π½ΡΡ ΠΌΠ°ΡΡΡ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΠΎΠ² ΠΌΡ ΠΏΡΠΎΠ΄Π΅Π»Π°Π»ΠΈ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ mobilenet Π²Π΅ΡΡΠΈΠΈ 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)
ΠΠ°ΠΊΠ΅Ρ docopt ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠΎΠ±ΠΎΠΉ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ 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
Π½Π° ΡΡΠ΅Ρ
ΡΠ²Π΅ΡΠ½ΡΡ
ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡΡ
ΡΠ°Π·ΠΌΠ΅ΡΠΎΠ² 128Ρ
128 ΠΏΠΈΠΊΡΠ΅Π»Π΅ΠΉ, Π±Π°Π·Π° Π΄Π°Π½Π½ΡΡ
Π΄ΠΎΠ»ΠΆΠ½Π° Π½Π°Ρ
ΠΎΠ΄ΠΈΡΡΡΡ Π² ΠΏΠ°ΠΏΠΊΠ΅ /home/andrey/doodle_db
). Π ΡΠΏΠΈΡΠΎΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΡΠΊΠΎΡΠΎΡΡΡ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ, Π²ΠΈΠ΄ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΎΡΠ° ΠΈ Π»ΡΠ±ΡΠ΅ Π΄ΡΡΠ³ΠΈΠ΅ Π½Π°ΡΡΡΠ°ΠΈΠ²Π°Π΅ΠΌΡΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ. Π ΠΏΡΠΎΡΠ΅ΡΡΠ΅ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠΈ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ Π²ΡΡΡΠ½ΠΈΠ»ΠΎΡΡ, ΡΡΠΎ Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΡ mobilenet_v2
ΠΈΠ· Π°ΠΊΡΡΠ°Π»ΡΠ½ΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ keras Π² R ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ
ΠΡΠΎΡ ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΠ» Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΡΡΠΊΠΎΡΠΈΡΡ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΡ Ρ ΡΠ°Π·Π½ΡΠΌΠΈ ΠΌΠΎΠ΄Π΅Π»ΡΠΌΠΈ ΠΏΠΎ ΡΡΠ°Π²Π½Π΅Π½ΠΈΡ Ρ Π±ΠΎΠ»Π΅Π΅ ΡΡΠ°Π΄ΠΈΡΠΈΠΎΠ½Π½ΡΠΌ Π·Π°ΠΏΡΡΠΊΠΎΠΌ ΡΠΊΡΠΈΠΏΡΠΎΠ² Π² RStudio (Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ Π°Π»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²Ρ ΠΎΡΠΌΠ΅ΡΠΈΠΌ ΠΏΠ°ΠΊΠ΅Ρ
6. ΠΠΎΠΊΠ΅ΡΠΈΠ·Π°ΡΠΈΡ ΡΠΊΡΠΈΠΏΡΠΎΠ²
ΠΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈ Π΄ΠΎΠΊΠ΅Ρ Ρ ΡΠ΅Π»ΡΡ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΡ ΠΏΠ΅ΡΠ΅Π½ΠΎΡΠΈΠΌΠΎΡΡΠΈ ΡΡΠ΅Π΄Ρ Π΄Π»Ρ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ ΠΌΠ΅ΠΆΠ΄Ρ ΡΠ»Π΅Π½Π°ΠΌΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Ρ ΠΈ Π΄Π»Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΡΠ°Π·Π²ΡΡΡΡΠ²Π°Π½ΠΈΡ Π² ΠΎΠ±Π»Π°ΠΊΠ΅. ΠΠ°ΡΠ°ΡΡ Π·Π½Π°ΠΊΠΎΠΌΡΡΠ²ΠΎ Ρ ΡΡΠΈΠΌ ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ Π½Π΅ΠΏΡΠΈΠ²ΡΡΠ½ΡΠΌ Π΄Π»Ρ R-ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΡΠ° ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠΌ ΠΌΠΎΠΆΠ½ΠΎ Ρ
ΠΠΎΠΊΠ΅Ρ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΊΠ°ΠΊ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΠΎΠ±ΡΠ°Π·Ρ Β«Ρ Π½ΡΠ»ΡΒ», ΡΠ°ΠΊ ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π΄ΡΡΠ³ΠΈΠ΅ ΠΎΠ±ΡΠ°Π·Ρ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΎΡΠ½ΠΎΠ²Ρ Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΡ
. ΠΡΠΈ Π°Π½Π°Π»ΠΈΠ·Π΅ ΠΈΠΌΠ΅ΡΡΠΈΡ
ΡΡ Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ² ΠΌΡ ΠΏΡΠΈΡΠ»ΠΈ ΠΊ Π²ΡΠ²ΠΎΠ΄Ρ, ΡΡΠΎ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ° Π΄ΡΠ°ΠΉΠ²Π΅ΡΠΎΠ² NVIDIA, CUDA+cuDNN ΠΈ ΠΏΠΈΡΠΎΠ½ΠΎΠ²ΡΠΊΠΈΡ
Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊ β Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΠΎΠ±ΡΡΠΌΠ½Π°Ρ ΡΠ°ΡΡΡ ΠΎΠ±ΡΠ°Π·Π°, ΠΈ ΡΠ΅ΡΠΈΠ»ΠΈ Π²Π·ΡΡΡ Π·Π° ΠΎΡΠ½ΠΎΠ²Ρ ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½ΡΠΉ ΠΎΠ±ΡΠ°Π· tensorflow/tensorflow:1.12.0-gpu
, Π΄ΠΎΠ±Π°Π²ΠΈΠ² ΡΡΠ΄Π° Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡΠ΅ R-ΠΏΠ°ΠΊΠ΅ΡΡ.
ΠΡΠΎΠ³ΠΎΠ²ΡΠΉ Π΄ΠΎΠΊΠ΅Ρ-ΡΠ°ΠΉΠ» ΠΏΠΎΠ»ΡΡΠΈΠ»ΡΡ ΡΠ°ΠΊΠΈΠΌ:
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
ΠΠ»Ρ ΡΠ΄ΠΎΠ±ΡΡΠ²Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ Π±ΡΠ»ΠΈ Π²ΡΠ½Π΅ΡΠ΅Π½Ρ Π² ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅; ΠΎΡΠ½ΠΎΠ²Π½Π°Ρ ΡΠ°ΡΡΡ Π½Π°ΠΏΠΈΡΠ°Π½Π½ΡΡ
ΡΠΊΡΠΈΠΏΡΠΎΠ² ΠΊΠΎΠΏΠΈΡΡΠ΅ΡΡΡ Π²Π½ΡΡΡΡ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠΎΠ² ΠΏΡΠΈ ΡΠ±ΠΎΡΠΊΠ΅. Π’Π°ΠΊΠΆΠ΅ ΠΌΡ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ»ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΡΡ ΠΎΠ±ΠΎΠ»ΠΎΡΠΊΡ Π½Π° /bin/bash
Π΄Π»Ρ ΡΠ΄ΠΎΠ±ΡΡΠ²Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ³ΠΎ /etc/os-release
. ΠΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΠ»ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°ΡΡ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ ΡΠΊΠ°Π·ΡΠ²Π°ΡΡ Π²Π΅ΡΡΠΈΡ ΠΠ‘ Π² ΠΊΠΎΠ΄Π΅.
ΠΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π±ΡΠ» Π½Π°ΠΏΠΈΡΠ°Π½ Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΉ Π±Π°Ρ-ΡΠΊΡΠΈΠΏΡ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡΠΈΠΉ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ Ρ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠΌΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π°ΠΌΠΈ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΡΠΎ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΡΠΊΡΠΈΠΏΡΡ Π΄Π»Ρ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ Π½Π΅ΠΉΡΠΎΡΠ΅ΡΠ΅ΠΉ, ΡΠ°Π½Π΅Π΅ ΠΏΠΎΠΌΠ΅ΡΠ΅Π½Π½ΡΠ΅ Π²Π½ΡΡΡΡ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ°, ΠΈΠ»ΠΈ ΠΆΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Π½Π°Ρ ΠΎΠ±ΠΎΠ»ΠΎΡΠΊΠ° Π΄Π»Ρ ΠΎΡΠ»Π°Π΄ΠΊΠΈ ΠΈ ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³Π° ΡΠ°Π±ΠΎΡΡ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ°:
Π‘ΠΊΡΠΈΠΏΡ Π΄Π»Ρ Π·Π°ΠΏΡΡΠΊΠ° ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ°
#!/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. ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ GPU Π² ΠΎΠ±Π»Π°ΠΊΠ΅ Google Cloud
ΠΠ΄Π½ΠΎΠΉ ΠΈΠ· ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡΠ΅ΠΉ ΡΠΎΡΠ΅Π²Π½ΠΎΠ²Π°Π½ΠΈΡ Π±ΡΠ»ΠΈ Π²Π΅ΡΡΠΌΠ° ΡΡΠΌΠ½ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ (ΡΠΌ. Π·Π°Π³Π»Π°Π²Π½ΡΡ ΠΊΠ°ΡΡΠΈΠ½ΠΊΡ, ΠΏΠΎΠ·Π°ΠΈΠΌΡΡΠ²ΠΎΠ²Π°Π½Π½ΡΡ Ρ @Leigh.plt ΠΈΠ· ODS-ΡΠ»Π°ΠΊΠ°). ΠΠΎΡΠΎΡΡΡΡ Ρ ΡΡΠΈΠΌ ΠΏΠΎΠΌΠΎΠ³Π°ΡΡ Π±Π°ΡΡΠΈ Π±ΠΎΠ»ΡΡΠΎΠ³ΠΎ ΡΠ°Π·ΠΌΠ΅ΡΠ°, ΠΈ ΠΌΡ ΠΏΠΎΡΠ»Π΅ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΠΎΠ² Π½Π° ΠΠ Ρ 1 GPU ΡΠ΅ΡΠΈΠ»ΠΈ ΠΎΡΠ²ΠΎΠΈΡΡ ΠΎΠ±ΡΡΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ
GPU Π² ΠΎΠ±Π»Π°ΠΊΠ΅. ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈ GoogleCloud (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 ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ Π½Π΅ ΡΠ΄Π°Π»ΠΎΡΡ.
ΠΠ° ΠΎΠ±ΡΡΠ΅Π½ΠΈΠ΅ΠΌ ΡΠ»Π΅Π΄ΠΈΠ»ΠΈ Π±Π΅Π· ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ 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 Π½Π΅Ρ Π³ΠΎΡΠΎΠ²ΠΎΠΉ ΡΡΠ½ΠΊΡΠΈΠΈ Π΄Π»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΏΠΎΠΈΡΠΊΠ° ΠΎΠΏΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠΉ ΡΠΊΠΎΡΠΎΡΡΠΈ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ (Π°Π½Π°Π»ΠΎΠ³Π°
lr_finder
Π² Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅ fast.ai); ΠΏΡΠΈΠ»ΠΎΠΆΠΈΠ² Π½Π΅ΠΊΠΎΡΠΎΡΡΠ΅ ΡΡΠΈΠ»ΠΈΡ, ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡ Π½Π° R ΡΡΠΎΡΠΎΠ½Π½ΠΈΠ΅ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ,ΡΡΡ ; - ΠΊΠ°ΠΊ ΡΠ»Π΅Π΄ΡΡΠ²ΠΈΠ΅ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅Π³ΠΎ ΠΏΡΠ½ΠΊΡΠ°, Π½Π΅ ΠΏΠΎΠ»ΡΡΠΈΠ»ΠΎΡΡ ΠΏΠΎΠ΄ΠΎΠ±ΡΠ°ΡΡ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΡΡ ΡΠΊΠΎΡΠΎΡΡΡ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ ΠΏΡΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ GPU;
- Π½Π΅ Ρ Π²Π°ΡΠ°Π΅Ρ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡ Π½Π΅ΠΉΡΠΎΡΠ΅ΡΠ΅ΠΉ, ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎ ΠΏΡΠ΅Π΄ΠΎΠ±ΡΡΠ΅Π½Π½ΡΡ Π½Π° imagenet-Π΅;
- Π½Π΅Ρ one cycle policy ΠΈ discriminative learning rates (Ρosine annealing ΠΏΠΎ Π½Π°ΡΠ΅ΠΉ ΠΏΡΠΎΡΡΠ±Π΅ Π±ΡΠ»
ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ , ΡΠΏΠ°ΡΠΈΠ±ΠΎskeydan ).
Π§ΡΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠ³ΠΎ ΡΠ΄Π°Π»ΠΎΡΡ Π²ΡΠ½Π΅ΡΡΠΈ ΠΈΠ· ΡΡΠΎΠ³ΠΎ ΡΠΎΡΠ΅Π²Π½ΠΎΠ²Π°Π½ΠΈΡ:
- ΠΠ° ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΌΠ°Π»ΠΎΠΌΠΎΡΠ½ΠΎΠΌ ΠΆΠ΅Π»Π΅Π·Π΅ ΠΌΠΎΠΆΠ½ΠΎ Π±Π΅Π· Π±ΠΎΠ»ΠΈ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ ΠΏΡΠΈΠ»ΠΈΡΠ½ΡΠΌΠΈ (ΠΊΡΠ°ΡΠ½ΠΎ ΠΏΡΠ΅Π²ΡΡΠ°ΡΡΠΈΠΌΠΈ ΡΠ°Π·ΠΌΠ΅Ρ ΠΠΠ£) ΠΎΠ±ΡΠ΅ΠΌΠ°ΠΌΠΈ Π΄Π°Π½Π½ΡΡ . ΠΠ°ΠΊΠ΅Ρ data.table ΡΠΊΠΎΠ½ΠΎΠΌΠΈΡ ΠΏΠ°ΠΌΡΡΡ Π·Π° ΡΡΠ΅Ρ in-place ΠΌΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ ΡΠ°Π±Π»ΠΈΡ, ΡΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΈΠ·Π±Π΅ΠΆΠ°ΡΡ ΠΈΡ ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°Π½ΠΈΡ, ΠΈ ΠΏΡΠΈ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠΈ Π΅Π³ΠΎ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠ΅ΠΉ ΠΏΠΎΡΡΠΈ Π²ΡΠ΅Π³Π΄Π° Π΄Π΅ΠΌΠΎΠ½ΡΡΡΠΈΡΡΠ΅Ρ Π½Π°ΠΈΠ±ΠΎΠ»ΡΡΡΡ ΡΠΊΠΎΡΠΎΡΡΡ ΡΡΠ΅Π΄ΠΈ Π²ΡΠ΅Ρ ΠΈΠ·Π²Π΅ΡΡΠ½ΡΡ Π½Π°ΠΌ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠ² Π΄Π»Ρ ΡΠΊΡΠΈΠΏΡΠΎΠ²ΡΡ ΡΠ·ΡΠΊΠΎΠ². Π‘ΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½ΡΡ Π² ΠΠ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ ΡΠ»ΡΡΠ°ΡΡ Π²ΠΎΠΎΠ±ΡΠ΅ Π½Π΅ Π΄ΡΠΌΠ°ΡΡ ΠΎ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ Π²ΡΠΈΡΠΊΠΈΠ²Π°ΡΡ Π²Π΅ΡΡ Π΄Π°ΡΠ°ΡΠ΅Ρ Π² ΠΠΠ£.
- ΠΠ΅Π΄Π»Π΅Π½Π½ΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ Π½Π° R ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΌΠ΅Π½ΠΈΡΡ Π±ΡΡΡΡΡΠΌΠΈ Π½Π° C++ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΠΏΠ°ΠΊΠ΅ΡΠ° Rcpp. ΠΡΠ»ΠΈ Π²Π΄ΠΎΠ±Π°Π²ΠΎΠΊ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ RcppThread ΠΈΠ»ΠΈ RcppParallel, ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΠΊΡΠΎΡΡΠΏΠ»Π°ΡΡΠΎΡΠΌΠ΅Π½Π½ΡΠ΅ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡΠΎΡΠ½ΡΠ΅ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ, ΠΏΠΎΡΡΠΎΠΌΡ ΠΊΠΎΠ΄ Π½Π° ΡΡΠΎΠ²Π½Π΅ R ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΠΈΡΡ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ.
- ΠΠ°ΠΊΠ΅ΡΠΎΠΌ Rcpp ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡΡΡ Π±Π΅Π· ΡΠ΅ΡΡΠ΅Π·Π½ΡΡ
Π·Π½Π°Π½ΠΈΠΉ C++, Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡΠΉ ΠΌΠΈΠ½ΠΈΠΌΡΠΌ ΠΈΠ·Π»ΠΎΠΆΠ΅Π½
Π·Π΄Π΅ΡΡ . ΠΠ°Π³ΠΎΠ»ΠΎΠ²ΠΎΡΠ½ΡΠ΅ ΡΠ°ΠΉΠ»Ρ Π΄Π»Ρ ΡΡΠ΄Π° ΠΊΡΡΡΡΡ ΡΠΈΡΠ½ΡΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊ ΡΠΈΠΏΠ° xtensor Π΄ΠΎΡΡΡΠΏΠ½Ρ Π½Π° CRAN, ΡΠΎ Π΅ΡΡΡ ΡΠΎΡΠΌΠΈΡΡΠ΅ΡΡΡ ΠΈΠ½ΡΡΠ°ΡΡΡΡΠΊΡΡΡΠ° Π΄Π»Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΏΡΠΎΠ΅ΠΊΡΠΎΠ², ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΡΡΡΠΈΡ Π² R Π³ΠΎΡΠΎΠ²ΡΠΉ Π²ΡΡΠΎΠΊΠΎΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΡΠΉ ΠΊΠΎΠ΄ Π½Π° C++. ΠΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎΠ΅ ΡΠ΄ΠΎΠ±ΡΡΠ²ΠΎ β ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΊΠ° ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ° ΠΈ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π°Π½Π°Π»ΠΈΠ·Π°ΡΠΎΡ ΠΊΠΎΠ΄Π° Π½Π° Π‘++ Π² RStudio. - docopt ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ ΡΠ°ΠΌΠΎΠ΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΡΠ΅ ΡΠΊΡΠΈΠΏΡΡ Ρ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°ΠΌΠΈ. ΠΡΠΎ ΡΠ΄ΠΎΠ±Π½ΠΎ Π΄Π»Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΠΎΠΌ ΡΠ΅ΡΠ²Π΅ΡΠ΅, Π² Ρ.Ρ. ΠΏΠΎΠ΄ Π΄ΠΎΠΊΠ΅ΡΠΎΠΌ. Π RStudio ΠΏΡΠΎΠ²ΠΎΠ΄ΠΈΡΡ ΠΌΠ½ΠΎΠ³ΠΎΡΠ°ΡΠΎΠ²ΡΠ΅ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΡ Ρ ΠΎΠ±ΡΡΠ΅Π½ΠΈΠ΅ΠΌ Π½Π΅ΠΉΡΠΎΡΠ΅ΡΠ΅ΠΉ Π½Π΅ΡΠ΄ΠΎΠ±Π½ΠΎ, Π΄Π° ΠΈ ΡΠ°ΠΌΠ° ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ° IDE Π½Π° ΡΠ΅ΡΠ²Π΅ΡΠ΅ Π½Π΅ Π²ΡΠ΅Π³Π΄Π° ΠΎΠΏΡΠ°Π²Π΄Π°Π½Π°.
- ΠΠΎΠΊΠ΅Ρ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Π΅Ρ ΠΏΠ΅ΡΠ΅Π½ΠΎΡΠΈΠΌΠΎΡΡΡ ΠΊΠΎΠ΄Π° ΠΈ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΠΌΠΎΡΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ² ΠΌΠ΅ΠΆΠ΄Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌΠΈ Ρ ΡΠ°Π·Π½ΡΠΌΠΈ Π²Π΅ΡΡΠΈΡΠΌΠΈ ΠΠ‘ ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊ, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΏΡΠΎΡΡΠΎΡΡ Π·Π°ΠΏΡΡΠΊΠ° Π½Π° ΡΠ΅ΡΠ²Π΅ΡΠ°Ρ . ΠΠ°ΠΏΡΡΡΠΈΡΡ Π²Π΅ΡΡ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½ Π΄Π»Ρ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ Π²ΡΠ΅Π³ΠΎ ΠΎΠ΄Π½ΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ.
- Google Cloud β Π±ΡΠ΄ΠΆΠ΅ΡΠ½ΡΠΉ ΡΠΏΠΎΡΠΎΠ± ΠΏΠΎΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΠΈΡΠΎΠ²Π°ΡΡ Π½Π° Π΄ΠΎΡΠΎΠ³ΠΎΠΌ ΠΆΠ΅Π»Π΅Π·Π΅, Π½ΠΎ Π½ΡΠΆΠ½ΠΎ Π²Π΄ΡΠΌΡΠΈΠ²ΠΎ Π²ΡΠ±ΠΈΡΠ°ΡΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ.
- ΠΠ°ΠΌΠ΅ΡΡΡΡ ΡΠΊΠΎΡΠΎΡΡΡ ΡΠ°Π±ΠΎΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΡ ΡΡΠ°Π³ΠΌΠ΅Π½ΡΠΎΠ² ΠΊΠΎΠ΄Π° ΠΎΡΠ΅Π½Ρ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎ ΠΏΡΠΈ ΡΠΎΡΠ΅ΡΠ°Π½ΠΈΠΈ R ΠΈ C++, Π° Ρ ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ bench β Π΅ΡΠ΅ ΠΈ ΠΎΡΠ΅Π½Ρ Π»Π΅Π³ΠΊΠΎ.
Π ΡΠ΅Π»ΠΎΠΌ ΡΡΠΎΡ ΠΎΠΏΡΡ Π±ΡΠ» ΠΎΡΠ΅Π½Ρ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΌ, ΠΈ ΠΌΡ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅ΠΌ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π½Π°Π΄ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ΠΌ Π½Π΅ΠΊΠΎΡΠΎΡΡΡ ΠΈΠ· ΠΎΠ·Π²ΡΡΠ΅Π½Π½ΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌ.
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com