Π₯Π΅Ρ Π₯Π°Π±Ρ!
ΠΡΠΎΡΠ»Π΅ ΡΠ΅ΡΠ΅Π½ΠΈ, ΠΠ°Π³Π³Π»Π΅ ΡΠ΅ Π±ΠΈΠΎ Π΄ΠΎΠΌΠ°ΡΠΈΠ½ ΡΠ°ΠΊΠΌΠΈΡΠ΅ΡΠ° Π·Π° ΠΊΠ»Π°ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡΡ ΡΡΡΠ½ΠΎ Π½Π°ΡΡΡΠ°Π½ΠΈΡ
ΡΠ»ΠΈΠΊΠ°, ΠΡΠΈΡΠΊ ΠΡΠ°Π² ΠΠΎΠΎΠ΄Π»Π΅ Π Π΅ΡΠΎΠ³Π½ΠΈΡΠΈΠΎΠ½, Ρ ΠΊΠΎΡΠ΅ΠΌ ΡΠ΅, ΠΈΠ·ΠΌΠ΅ΡΡ ΠΎΡΡΠ°Π»ΠΈΡ
, ΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°ΠΎ ΠΈ ΡΠΈΠΌ Π -Π½Π°ΡΡΠ½ΠΈΠΊΠ°:
ΠΠ²ΠΎΠ³Π° ΠΏΡΡΠ° Π½ΠΈΡΠ΅ ΠΈΡΠ»ΠΎ ΡΠ° ΡΠ·Π³ΠΎΡΠ΅ΠΌ ΠΌΠ΅Π΄Π°ΡΠ°, Π°Π»ΠΈ ΡΠ΅ ΡΡΠ΅ΡΠ΅Π½ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ Π΄ΡΠ°Π³ΠΎΡΠ΅Π½ΠΎΠ³ ΠΈΡΠΊΡΡΡΠ²Π°, ΠΏΠ° Π±ΠΈΡ
ΠΆΠ΅Π»Π΅ΠΎ Π΄Π° ΠΈΡΠΏΡΠΈΡΠ°ΠΌ Π·Π°ΡΠ΅Π΄Π½ΠΈΡΠΈ Π½Π΅ΠΊΠΎΠ»ΠΈΠΊΠΎ Π½Π°ΡΠ·Π°Π½ΠΈΠΌΡΠΈΠ²ΠΈΡΠΈΡ
ΠΈ Π½Π°ΡΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΈΡ
ΡΡΠ²Π°ΡΠΈ Π½Π° ΠΠ°Π³Π»Π΅Ρ ΠΈ Ρ ΡΠ²Π°ΠΊΠΎΠ΄Π½Π΅Π²Π½ΠΎΠΌ ΡΠ°Π΄Ρ. ΠΠ΅ΡΡ ΡΠ΅ΠΌΠ°ΠΌΠ° ΠΎ ΠΊΠΎΡΠΈΠΌΠ° ΡΠ΅ ΡΠ°Π·Π³ΠΎΠ²Π°ΡΠ°Π»ΠΎ: ΡΠ΅ΠΆΠ°ΠΊ ΠΆΠΈΠ²ΠΎΡ Π±Π΅Π· ΠΠΏΠ΅Π½Π¦Π, ΠΠ‘ΠΠ ΡΠ°ΡΡΠ»Π°ΡΠΈΠ²Π°ΡΠ΅ (ΠΎΠ²ΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠΈ ΠΈΡΠΏΠΈΡΡΡΡ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡΡ Π¦++ ΠΊΠΎΠ΄Π° Ρ ΡΠΊΡΠΈΠΏΡΠ΅ ΠΈΠ»ΠΈ ΠΏΠ°ΠΊΠ΅ΡΠ΅ Ρ Π ΠΊΠΎΡΠΈΡΡΠ΅ΡΠΈ Π ΡΠΏΠΏ), ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈΠ·Π°ΡΠΈΡΠ° ΡΠΊΡΠΈΠΏΡΠΈ ΠΈ Π΄ΠΎΠΊΠ΅ΡΠΈΠ·Π°ΡΠΈΡΠ° ΠΊΠΎΠ½Π°ΡΠ½ΠΎΠ³ ΡΠ΅ΡΠ΅ΡΠ°. Π‘Π°Π² ΠΊΠΎΠ΄ ΠΈΠ· ΠΏΠΎΡΡΠΊΠ΅ Ρ ΠΎΠ±Π»ΠΈΠΊΡ ΠΏΠΎΠ³ΠΎΠ΄Π½ΠΎΠΌ Π·Π° ΠΈΠ·Π²ΡΡΠ΅ΡΠ΅ ΡΠ΅ Π΄ΠΎΡΡΡΠΏΠ°Π½ Ρ
Π‘Π°Π΄ΡΠΆΠ°Ρ:
ΠΡΠΈΠΊΠ°ΡΠ½ΠΎ ΡΡΠΈΡΠ°ΡΡΠ΅ ΠΏΠΎΠ΄Π°ΡΠΊΠ΅ ΠΈΠ· Π¦Π‘Π-Π° Ρ ΠΠΎΠ½Π΅ΡΠΠ ΠΡΠΈΠΏΡΠ΅ΠΌΠ° ΡΠ΅ΡΠΈΡΠ° ΠΡΠ΅ΡΠ°ΡΠΎΡΠΈ Π·Π° ΠΈΡΡΠΎΠ²Π°Ρ ΠΏΠ°ΠΊΠ΅ΡΠ° ΠΈΠ· Π±Π°Π·Π΅ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° ΠΠ·Π±ΠΎΡ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ΅ ΠΌΠΎΠ΄Π΅Π»Π° ΠΠ°ΡΠ°ΠΌΠ΅ΡΠ΅ΡΠΈΠ·Π°ΡΠΈΡΠ° ΡΠΊΡΠΈΠΏΡΠ΅ ΠΠΎΠΊΠ΅ΡΠΈΠ·Π°ΡΠΈΡΠ° ΡΠΊΡΠΈΠΏΡΠΈ ΠΠΎΡΠΈΡΡΠ΅ΡΠ΅ Π²ΠΈΡΠ΅ ΠΠΠ£-Π° Π½Π° ΠΠΎΠΎΠ³Π»Π΅ Π¦Π»ΠΎΡΠ΄-Ρ Π£ΠΌΠ΅ΡΡΠΎ Π·Π°ΠΊΡΡΡΠΊΠ°
1. ΠΡΠΈΠΊΠ°ΡΠ½ΠΎ ΡΡΠΈΡΠ°ΡΡΠ΅ ΠΏΠΎΠ΄Π°ΡΠΊΠ΅ ΠΈΠ· Π¦Π‘Π-Π° Ρ ΠΠΎΠ½Π΅ΡΠΠ Π±Π°Π·Ρ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°
ΠΠΎΠ΄Π°ΡΠΈ Ρ ΠΎΠ²ΠΎΠΌ ΠΊΠΎΠ½ΠΊΡΡΡΡ Π½ΠΈΡΡ Π΄Π°ΡΠΈ Ρ ΠΎΠ±Π»ΠΈΠΊΡ Π³ΠΎΡΠΎΠ²ΠΈΡ ΡΠ»ΠΈΠΊΠ°, Π²Π΅Ρ Ρ ΠΎΠ±Π»ΠΈΠΊΡ 340 Π¦Π‘Π ΡΠ°ΡΠ»ΠΎΠ²Π° (ΠΏΠΎ ΡΠ΅Π΄Π°Π½ ΡΠ°ΡΠ» Π·Π° ΡΠ²Π°ΠΊΡ ΠΊΠ»Π°ΡΡ) ΠΊΠΎΡΠΈ ΡΠ°Π΄ΡΠΆΠ΅ ΠΠ‘ΠΠ ΡΠ° ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ°ΠΌΠ° ΡΠ°ΡΠ°ΠΊΠ°. ΠΠΎΠ²Π΅Π·ΠΈΠ²Π°ΡΠ΅ΠΌ ΠΎΠ²ΠΈΡ ΡΠ°ΡΠ°ΠΊΠ° Π»ΠΈΠ½ΠΈΡΠ°ΠΌΠ° Π΄ΠΎΠ±ΠΈΡΠ°ΠΌΠΎ ΠΊΠΎΠ½Π°ΡΠ½Ρ ΡΠ»ΠΈΠΊΡ Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΡΠ° 256ΠΊ256 ΠΏΠΈΠΊΡΠ΅Π»Π°. Π’Π°ΠΊΠΎΡΠ΅ Π·Π° ΡΠ²Π°ΠΊΠΈ Π·Π°ΠΏΠΈΡ ΠΏΠΎΡΡΠΎΡΠΈ ΠΎΠ·Π½Π°ΠΊΠ° ΠΊΠΎΡΠ° ΠΏΠΎΠΊΠ°Π·ΡΡΠ΅ Π΄Π° Π»ΠΈ ΡΠ΅ ΡΠ»ΠΈΠΊΡ ΠΈΡΠΏΡΠ°Π²Π½ΠΎ ΠΏΡΠ΅ΠΏΠΎΠ·Π½Π°ΠΎ ΠΊΠ»Π°ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΊΠΎΡΠΈ ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠ΅Π½ Ρ Π²ΡΠ΅ΠΌΠ΅ ΠΏΡΠΈΠΊΡΠΏΡΠ°ΡΠ° ΡΠΊΡΠΏΠ° ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°, Π΄Π²ΠΎΡΠ»ΠΎΠ²Π½ΠΈ ΠΊΠΎΠ΄ Π·Π΅ΠΌΡΠ΅ ΠΏΡΠ΅Π±ΠΈΠ²Π°Π»ΠΈΡΡΠ° Π°ΡΡΠΎΡΠ° ΡΠ»ΠΈΠΊΠ΅, ΡΠ΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½ΠΈ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ, Π²ΡΠ΅ΠΌΠ΅Π½ΡΠΊΠ° ΠΎΠ·Π½Π°ΠΊΠ° ΠΈ ΠΈΠΌΠ΅ ΠΊΠ»Π°ΡΠ΅ ΠΊΠΎΡΠ΅ ΠΎΠ΄Π³ΠΎΠ²Π°ΡΠ° ΠΈΠΌΠ΅Π½Ρ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ΅. ΠΠΎΡΠ΅Π΄Π½ΠΎΡΡΠ°Π²ΡΠ΅Π½Π° Π²Π΅ΡΠ·ΠΈΡΠ° ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΈΡ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° ΡΠ΅ΠΆΠΈ 7.4 ΠΠ Ρ Π°ΡΡ ΠΈΠ²ΠΈ ΠΈ ΠΏΡΠΈΠ±Π»ΠΈΠΆΠ½ΠΎ 20 ΠΠ Π½Π°ΠΊΠΎΠ½ ΡΠ°ΡΠΏΠ°ΠΊΠΈΠ²Π°ΡΠ°, ΠΏΡΠ½ΠΈ ΠΏΠΎΠ΄Π°ΡΠΈ Π½Π°ΠΊΠΎΠ½ ΡΠ°ΡΠΏΠ°ΠΊΠΈΠ²Π°ΡΠ° Π·Π°ΡΠ·ΠΈΠΌΠ°ΡΡ 240 ΠΠ. ΠΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΎΡΠΈ ΡΡ ΠΎΠ±Π΅Π·Π±Π΅Π΄ΠΈΠ»ΠΈ Π΄Π° ΠΎΠ±Π΅ Π²Π΅ΡΠ·ΠΈΡΠ΅ ΡΠ΅ΠΏΡΠΎΠ΄ΡΠΊΡΡΡ ΠΈΡΡΠ΅ ΡΡΡΠ΅ΠΆΠ΅, ΡΡΠΎ Π·Π½Π°ΡΠΈ Π΄Π° ΡΠ΅ ΠΏΡΠ½Π° Π²Π΅ΡΠ·ΠΈΡΠ° ΡΡΠ²ΠΈΡΠ½Π°. Π£ ΡΠ²Π°ΠΊΠΎΠΌ ΡΠ»ΡΡΠ°ΡΡ, ΡΠΊΠ»Π°Π΄ΠΈΡΡΠ΅ΡΠ΅ 50 ΠΌΠΈΠ»ΠΈΠΎΠ½Π° ΡΠ»ΠΈΠΊΠ° Ρ Π³ΡΠ°ΡΠΈΡΠΊΠΈΠΌ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ°ΠΌΠ° ΠΈΠ»ΠΈ Ρ ΠΎΠ±Π»ΠΈΠΊΡ Π½ΠΈΠ·ΠΎΠ²Π° ΠΎΠ΄ΠΌΠ°Ρ ΡΠ΅ ΡΠΌΠ°ΡΡΠ°Π½ΠΎ Π½Π΅ΠΈΡΠΏΠ»Π°ΡΠΈΠ²ΠΈΠΌ, ΠΏΠ° ΡΠΌΠΎ ΠΎΠ΄Π»ΡΡΠΈΠ»ΠΈ Π΄Π° ΡΠΏΠΎΡΠΈΠΌΠΎ ΡΠ²Π΅ Π¦Π‘Π Π΄Π°ΡΠΎΡΠ΅ΠΊΠ΅ ΠΈΠ· Π°ΡΡ ΠΈΠ²Π΅ ΡΡΠ°ΠΈΠ½_ΡΠΈΠΌΠΏΠ»ΠΈΡΠΈΠ΅Π΄.Π·ΠΈΠΏ Ρ Π±Π°Π·Ρ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° ΡΠ° Π½Π°ΠΊΠ½Π°Π΄Π½ΠΈΠΌ Π³Π΅Π½Π΅ΡΠΈΡΠ°ΡΠ΅ΠΌ ΡΠ»ΠΈΠΊΠ° ΠΏΠΎΡΡΠ΅Π±Π½Π΅ Π²Π΅Π»ΠΈΡΠΈΠ½Π΅ βΡ Ρ ΠΎΠ΄Ρβ Π·Π° ΡΠ²Π°ΠΊΡ ΡΠ΅ΡΠΈΡΡ.
ΠΠ°ΠΎ ΠΠΠΠ‘ ΠΈΠ·Π°Π±ΡΠ°Π½ ΡΠ΅ Π΄ΠΎΠ±ΡΠΎ Π΄ΠΎΠΊΠ°Π·Π°Π½ ΡΠΈΡΡΠ΅ΠΌ ΠΠΎΠ½Π΅ΡΠΠ, ΠΎΠ΄Π½ΠΎΡΠ½ΠΎ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ° Π·Π° Π ΠΊΠ°ΠΎ ΠΏΠ°ΠΊΠ΅Ρ
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"
)
)
}
ΠΠ°ΡΠ±ΡΠΆΠΈ Π½Π°ΡΠΈΠ½ Π·Π° ΡΡΠΈΡΠ°Π²Π°ΡΠ΅ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° Ρ Π±Π°Π·Ρ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° Π±ΠΈΠΎ ΡΠ΅ Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ ΠΊΠΎΠΏΠΈΡΠ°ΡΠ΅ Π¦Π‘Π Π΄Π°ΡΠΎΡΠ΅ΠΊΠ° ΠΏΠΎΠΌΠΎΡΡ Π‘ΠΠ - ΠΊΠΎΠΌΠ°Π½Π΄Π΅ 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
ΠΡΠ΅ΠΌΠ΅ ΡΡΠΈΡΠ°Π²Π°ΡΠ° ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° Π²Π°ΡΠΈΡΠ° Ρ Π·Π°Π²ΠΈΡΠ½ΠΎΡΡΠΈ ΠΎΠ΄ ΠΊΠ°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΡΠΈΠΊΠ° Π±ΡΠ·ΠΈΠ½Π΅ ΠΊΠΎΡΠΈΡΡΠ΅Π½ΠΎΠ³ Π΄ΡΠ°ΡΠ²Π°. Π£ Π½Π°ΡΠ΅ΠΌ ΡΠ»ΡΡΠ°ΡΡ, ΡΠΈΡΠ°ΡΠ΅ ΠΈ ΠΏΠΈΡΠ°ΡΠ΅ ΡΠ½ΡΡΠ°Ρ ΡΠ΅Π΄Π½ΠΎΠ³ Π‘Π‘Π-Π° ΠΈΠ»ΠΈ ΡΠ° ΡΠ»Π΅Ρ Π΄ΠΈΡΠΊΠ° (ΠΈΠ·Π²ΠΎΡΠ½Π΅ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ΅) Π½Π° Π‘Π‘Π (ΠΠ) ΡΡΠ°ΡΠ΅ ΠΌΠ°ΡΠ΅ ΠΎΠ΄ 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 ΡΡΠΈΠΊΠ°. ΠΡΠ²ΠΈ ΡΠ΅ Π±ΠΈΠΎ Π΄Π° ΡΠ΅ ΡΠΌΠ°ΡΠΈ Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΠΎΠ½Π°Π»Π½ΠΎΡΡ ΡΠΈΠΏΠ° ΠΊΠΎΡΠΈ ΡΡΠ²Π° ΠΠ ΠΏΠΎΡΠΌΠ°ΡΡΠ°ΡΠ°. Π£ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΎΠΌ ΡΠΊΡΠΏΡ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°, ΡΠΈΠΏ ΠΊΠΎΡΠΈ ΡΠ΅ ΠΏΠΎΡΡΠ΅Π±Π°Π½ Π·Π° ΡΡΠ²Π°ΡΠ΅ ΠΠ-Π° ΡΠ΅ 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. ΠΡΠΈΠΏΡΠ΅ΠΌΠ° ΡΠ΅ΡΠΈΡΠ°
Π¦Π΅ΠΎ ΠΏΡΠΎΡΠ΅Ρ ΠΏΡΠΈΠΏΡΠ΅ΠΌΠ΅ ΡΠ΅ΡΠΈΡΠ΅ ΡΠ°ΡΡΠΎΡΠΈ ΡΠ΅ ΠΎΠ΄ ΡΠ»Π΅Π΄Π΅ΡΠΈΡ ΠΊΠΎΡΠ°ΠΊΠ°:
- ΠΠ°ΡΡΠΈΡΠ°ΡΠ΅ Π½Π΅ΠΊΠΎΠ»ΠΈΠΊΠΎ ΠΠ‘ΠΠ-ΠΎΠ²Π° ΠΊΠΎΡΠΈ ΡΠ°Π΄ΡΠΆΠ΅ Π²Π΅ΠΊΡΠΎΡΠ΅ Π½ΠΈΠ·ΠΎΠ²Π° ΡΠ° ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ°ΠΌΠ° ΡΠ°ΡΠ°ΠΊΠ°.
- Π¦ΡΡΠ°ΡΠ΅ Π»ΠΈΠ½ΠΈΡΠ° Ρ Π±ΠΎΡΠΈ Π½Π° ΠΎΡΠ½ΠΎΠ²Ρ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ° ΡΠ°ΡΠ°ΠΊΠ° Π½Π° ΡΠ»ΠΈΡΠΈ ΠΏΠΎΡΡΠ΅Π±Π½Π΅ Π²Π΅Π»ΠΈΡΠΈΠ½Π΅ (Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ, 256Γ256 ΠΈΠ»ΠΈ 128Γ128).
- ΠΡΠ΅ΡΠ²Π°ΡΠ°ΡΠ΅ Π΄ΠΎΠ±ΠΈΡΠ΅Π½ΠΈΡ ΡΠ»ΠΈΠΊΠ° Ρ ΡΠ΅Π½Π·ΠΎΡ.
Π£ ΠΎΠΊΠ²ΠΈΡΡ ΡΠ°ΠΊΠΌΠΈΡΠ΅ΡΠ° ΠΌΠ΅ΡΡ ΠΠΈΡΡ ΠΎΠ½ ΠΊΠ΅ΡΠ½Π΅Π»ΠΈΠΌΠ°, ΠΏΡΠΎΠ±Π»Π΅ΠΌ ΡΠ΅ ΠΏΡΠ²Π΅Π½ΡΡΠ²Π΅Π½ΠΎ ΡΠ΅ΡΠ΅Π½ ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ΠΌ ΠΠΏΠ΅Π½Π¦Π. ΠΠ΅Π΄Π°Π½ ΠΎΠ΄ Π½Π°ΡΡΠ΅Π΄Π½ΠΎΡΡΠ°Π²Π½ΠΈΡΠΈΡ ΠΈ Π½Π°ΡΠΎΡΠΈΠ³Π»Π΅Π΄Π½ΠΈΡΠΈΡ Π°Π½Π°Π»ΠΎΠ³Π° Ρ Π Π±ΠΈ ΠΈΠ·Π³Π»Π΅Π΄Π°ΠΎ ΠΎΠ²Π°ΠΊΠΎ:
ΠΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ° ΠΊΠΎΠ½Π²Π΅ΡΠ·ΠΈΡΠ΅ ΠΠ‘ΠΠ Ρ ΡΠ΅Π½Π·ΠΎΡ Ρ Π
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)
}
Π¦ΡΡΠ°ΡΠ΅ ΡΠ΅ ΠΈΠ·Π²ΠΎΠ΄ΠΈ ΠΏΠΎΠΌΠΎΡΡ ΡΡΠ°Π½Π΄Π°ΡΠ΄Π½ΠΈΡ
Π Π°Π»Π°ΡΠ° ΠΈ ΡΡΠ²Π° Ρ ΠΏΡΠΈΠ²ΡΠ΅ΠΌΠ΅Π½ΠΎΠΌ ΠΠΠ ΡΠΎΡΠΌΠ°ΡΡ ΠΊΠΎΡΠΈ ΡΠ΅ ΡΡΠ²Π° Ρ Π ΠΠ-Ρ (Π½Π° ΠΠΈΠ½ΡΠΊ-Ρ, ΠΏΡΠΈΠ²ΡΠ΅ΠΌΠ΅Π½ΠΈ Π Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡΡΠΌΠΈ ΡΠ΅ Π½Π°Π»Π°Π·Π΅ Ρ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡΡΠΌΡ /tmp
, ΠΌΠΎΠ½ΡΠΈΡΠ°Π½ Ρ Π ΠΠ). ΠΠ²Π° Π΄Π°ΡΠΎΡΠ΅ΠΊΠ° ΡΠ΅ Π·Π°ΡΠΈΠΌ ΡΠΈΡΠ° ΠΊΠ°ΠΎ ΡΡΠΎΠ΄ΠΈΠΌΠ΅Π½Π·ΠΈΠΎΠ½Π°Π»Π½ΠΈ Π½ΠΈΠ· ΡΠ° Π±ΡΠΎΡΠ΅Π²ΠΈΠΌΠ° Ρ ΡΠ°ΡΠΏΠΎΠ½Ρ ΠΎΠ΄ 0 Π΄ΠΎ 1. ΠΠ²ΠΎ ΡΠ΅ Π²Π°ΠΆΠ½ΠΎ ΡΠ΅Ρ Π±ΠΈ ΠΊΠΎΠ½Π²Π΅Π½ΡΠΈΠΎΠ½Π°Π»Π½ΠΈΡΠΈ ΠΠΠ Π±ΠΈΠΎ ΠΏΡΠΎΡΠΈΡΠ°Π½ Ρ ΡΠΈΡΠΎΠ²ΠΈ Π½ΠΈΠ· ΡΠ° Ρ
Π΅ΠΊΡΠ°Π΄Π΅ΡΠΈΠΌΠ°Π»Π½ΠΈΠΌ ΠΊΠΎΠ΄ΠΎΠ²ΠΈΠΌΠ° Π±ΠΎΡΠ°.
Π₯Π°ΡΠ΄Π΅ Π΄Π° ΡΠ΅ΡΡΠΈΡΠ°ΠΌΠΎ ΡΠ΅Π·ΡΠ»ΡΠ°Ρ:
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
ΠΠ²Π° ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ° Π½Π°ΠΌ ΡΠ΅ ΡΠΈΠ½ΠΈΠ»Π° Π½Π΅ΠΎΠΏΡΠΈΠΌΠ°Π»Π½Π°, ΠΏΠΎΡΡΠΎ ΡΠΎΡΠΌΠΈΡΠ°ΡΠ΅ Π²Π΅Π»ΠΈΠΊΠΈΡ ΡΠ΅ΡΠΈΡΠ° ΡΡΠ°ΡΠ΅ Π½Π΅ΠΏΡΠΈΡΡΠΎΡΠ½ΠΎ Π΄ΡΠ³ΠΎ, ΠΏΠ° ΡΠΌΠΎ ΠΎΠ΄Π»ΡΡΠΈΠ»ΠΈ Π΄Π° ΠΈΡΠΊΠΎΡΠΈΡΡΠΈΠΌΠΎ ΠΈΡΠΊΡΡΡΠ²ΠΎ Π½Π°ΡΠΈΡ ΠΊΠΎΠ»Π΅Π³Π° ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ΠΌ ΠΌΠΎΡΠ½Π΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅ ΠΠΏΠ΅Π½Π¦Π. Π£ ΡΠΎ Π²ΡΠ΅ΠΌΠ΅ Π½ΠΈΡΠ΅ ΠΏΠΎΡΡΠΎΡΠ°ΠΎ Π³ΠΎΡΠΎΠ² ΠΏΠ°ΠΊΠ΅Ρ Π·Π° Π (ΡΠ°Π΄Π° Π³Π° Π½Π΅ΠΌΠ°), ΠΏΠ° ΡΠ΅ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½Π° ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ° ΠΏΠΎΡΡΠ΅Π±Π½Π΅ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎΡΡΠΈ Π½Π°ΠΏΠΈΡΠ°Π½Π° Ρ Π¦++ ΡΠ° ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡΠΎΠΌ Ρ Π ΠΊΠΎΠ΄ ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ΠΌ Π ΡΠΏΠΏ.
ΠΠ° Π±ΠΈ ΡΠ΅ ΡΠ΅ΡΠΈΠΎ ΠΏΡΠΎΠ±Π»Π΅ΠΌ, ΠΊΠΎΡΠΈΡΡΠ΅Π½ΠΈ ΡΡ ΡΠ»Π΅Π΄Π΅ΡΠΈ ΠΏΠ°ΠΊΠ΅ΡΠΈ ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅:
-
ΠΠΏΠ΅Π½Π¦Π Π·Π° ΡΠ°Π΄ ΡΠ° ΡΠ»ΠΈΠΊΠ°ΠΌΠ° ΠΈ ΡΡΡΠ°ΡΠ΅ Π»ΠΈΠ½ΠΈΡΠ°. ΠΠΎΡΠΈΡΡΠ΅Π½Π΅ ΡΡ ΡΠ½Π°ΠΏΡΠ΅Π΄ ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ°Π½Π΅ ΡΠΈΡΡΠ΅ΠΌΡΠΊΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅ ΠΈ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ΅ Π·Π°Π³Π»Π°Π²ΡΠ°, ΠΊΠ°ΠΎ ΠΈ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠΊΠΎ ΠΏΠΎΠ²Π΅Π·ΠΈΠ²Π°ΡΠ΅.
-
ΠΊΡΠ΅Π½ΡΠΎΡ Π·Π° ΡΠ°Π΄ ΡΠ° Π²ΠΈΡΠ΅Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΠΎΠ½Π°Π»Π½ΠΈΠΌ Π½ΠΈΠ·ΠΎΠ²ΠΈΠΌΠ° ΠΈ ΡΠ΅Π½Π·ΠΎΡΠΈΠΌΠ°. ΠΠΎΡΠΈΡΡΠΈΠ»ΠΈ ΡΠΌΠΎ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ΅ Π·Π°Π³Π»Π°Π²ΡΠ° ΡΠΊΡΡΡΠ΅Π½Π΅ Ρ ΠΈΡΡΠΎΠΈΠΌΠ΅Π½ΠΈ Π ΠΏΠ°ΠΊΠ΅Ρ. ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π²Π°ΠΌ ΠΎΠΌΠΎΠ³ΡΡΠ°Π²Π° Π΄Π° ΡΠ°Π΄ΠΈΡΠ΅ ΡΠ° Π²ΠΈΡΠ΅Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΠΎΠ½Π°Π»Π½ΠΈΠΌ Π½ΠΈΠ·ΠΎΠ²ΠΈΠΌΠ°, ΠΊΠ°ΠΊΠΎ Ρ ΡΠ΅Π΄ΠΎΠ²ΠΈΠΌΠ°, ΡΠ°ΠΊΠΎ ΠΈ Ρ Π³Π»Π°Π²Π½ΠΎΠΌ ΡΠ΅Π΄ΠΎΡΠ»Π΅Π΄Ρ ΠΊΠΎΠ»ΠΎΠ½Π°.
-
Π½Π΄ΡΡΠΎΠ½ Π·Π° ΡΠ°ΡΡΠ»Π°ΡΠΈΠ²Π°ΡΠ΅ ΠΠ‘ΠΠ-Π°. ΠΠ²Π° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈ Ρ ΠΊΡΠ΅Π½ΡΠΎΡ Π°ΡΡΠΎΠΌΠ°ΡΡΠΊΠΈ Π°ΠΊΠΎ ΡΠ΅ ΠΏΡΠΈΡΡΡΠ°Π½ Ρ ΠΏΡΠΎΡΠ΅ΠΊΡΡ.
-
Π ΡΠΏΠΏΠ’Ρ ΡΠ΅Π°Π΄ Π·Π° ΠΎΡΠ³Π°Π½ΠΈΠ·ΠΎΠ²Π°ΡΠ΅ Π²ΠΈΡΠ΅Π½ΠΈΡΠ½Π΅ ΠΎΠ±ΡΠ°Π΄Π΅ Π²Π΅ΠΊΡΠΎΡΠ° ΠΈΠ· ΠΠ‘ΠΠ-Π°. ΠΠΎΡΠΈΡΡΠΈΠΎ ΡΠ΅ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ΅ Π·Π°Π³Π»Π°Π²ΡΠ° ΠΊΠΎΡΠ΅ ΠΎΠ±Π΅Π·Π±Π΅ΡΡΡΠ΅ ΠΎΠ²Π°Ρ ΠΏΠ°ΠΊΠ΅Ρ. ΠΠ΄ ΠΏΠΎΠΏΡΠ»Π°ΡΠ½ΠΈΡΠΈΡ Π ΡΠΏΠΏΠΠ°ΡΠ°Π»Π»Π΅Π» ΠΠ°ΠΊΠ΅Ρ, ΠΈΠ·ΠΌΠ΅ΡΡ ΠΎΡΡΠ°Π»ΠΎΠ³, ΠΈΠΌΠ° ΡΠ³ΡΠ°ΡΠ΅Π½ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·Π°ΠΌ Π·Π° ΠΏΡΠ΅ΠΊΠΈΠ΄ ΠΏΠ΅ΡΡΠ΅.
Π’ΡΠ΅Π±Π° Π½Π°ΠΏΠΎΠΌΠ΅Π½ΡΡΠΈ Π΄Π° ΠΊΡΠ΅Π½ΡΠΎΡ ΠΈΡΠΏΠΎΡΡΠ°Π²ΠΈΠ»ΠΎ ΡΠ΅ Π΄Π° ΡΠ΅ Π±ΠΎΠΆΡΠΈ Π΄Π°Ρ: ΠΏΠΎΡΠ΅Π΄ ΡΠΈΡΠ΅Π½ΠΈΡΠ΅ Π΄Π° ΠΈΠΌΠ° ΡΠΈΡΠΎΠΊΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎΡΡ ΠΈ Π²ΠΈΡΠΎΠΊΠ΅ ΠΏΠ΅ΡΡΠΎΡΠΌΠ°Π½ΡΠ΅, ΠΈΡΠΏΠΎΡΡΠ°Π²ΠΈΠ»ΠΎ ΡΠ΅ Π΄Π° ΡΡ ΡΠ΅Π³ΠΎΠ²ΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ΅ΡΠΈ ΠΏΡΠΈΠ»ΠΈΡΠ½ΠΎ ΡΠ΅Π°Π³ΠΎΠ²Π°Π»ΠΈ ΠΈ ΠΎΠ΄Π³ΠΎΠ²ΠΎΡΠΈΠ»ΠΈ Π½Π° ΠΏΠΈΡΠ°ΡΠ° Π±ΡΠ·ΠΎ ΠΈ Π΄Π΅ΡΠ°ΡΠ½ΠΎ. Π£Π· ΡΠΈΡ ΠΎΠ²Ρ ΠΏΠΎΠΌΠΎΡ, Π±ΠΈΠ»ΠΎ ΡΠ΅ ΠΌΠΎΠ³ΡΡΠ΅ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΠΈ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΡΠ΅ ΠΠΏΠ΅Π½Π¦Π ΠΌΠ°ΡΡΠΈΡΠ° Ρ ΠΊΡΠ΅Π½Π·ΠΎΡ ΡΠ΅Π½Π·ΠΎΡΠ°, ΠΊΠ°ΠΎ ΠΈ Π½Π°ΡΠΈΠ½ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΎΠ²Π°ΡΠ° 3-Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΠΎΠ½Π°Π»Π½ΠΈΡ ΡΠ΅Π½Π·ΠΎΡΠ° ΡΠ»ΠΈΠΊΠ΅ Ρ 4-Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΠΎΠ½Π°Π»Π½ΠΈ ΡΠ΅Π½Π·ΠΎΡ ΠΈΡΠΏΡΠ°Π²Π½Π΅ Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΡΠ΅ (ΡΠ°ΠΌΠ° ΡΠ΅ΡΠΈΡΠ°).
ΠΠ°ΡΠ΅ΡΠΈΡΠ°Π»ΠΈ Π·Π° ΡΡΠ΅ΡΠ΅ Π ΡΠΏΠΏ, ΠΊΡΠ΅Π½ΡΠΎΡ ΠΈ Π ΡΠΏΠΏΠ’Ρ ΡΠ΅Π°Π΄
ΠΠ° ΠΊΠΎΠΌΠΏΠ°ΡΠ»ΠΈΡΠ°ΡΠ΅ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ° ΠΊΠΎΡΠ΅ ΠΊΠΎΡΠΈΡΡΠ΅ ΡΠΈΡΡΠ΅ΠΌΡΠΊΠ΅ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ΅ ΠΈ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠΊΠΎ ΠΏΠΎΠ²Π΅Π·ΠΈΠ²Π°ΡΠ΅ ΡΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΠΌΠ° ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ°Π½ΠΈΠΌ Π½Π° ΡΠΈΡΡΠ΅ΠΌΡ, ΠΊΠΎΡΠΈΡΡΠΈΠ»ΠΈ ΡΠΌΠΎ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·Π°ΠΌ Π΄ΠΎΠ΄Π°ΡΠ°ΠΊΠ° ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠΈΡΠ°Π½ Ρ ΠΏΠ°ΠΊΠ΅ΡΡ Π ΡΠΏΠΏ. ΠΠ° Π±ΠΈΡΠΌΠΎ Π°ΡΡΠΎΠΌΠ°ΡΡΠΊΠΈ ΠΏΡΠΎΠ½Π°ΡΠ»ΠΈ ΠΏΡΡΠ°ΡΠ΅ ΠΈ Π·Π°ΡΡΠ°Π²ΠΈΡΠ΅, ΠΊΠΎΡΠΈΡΡΠΈΠ»ΠΈ ΡΠΌΠΎ ΠΏΠΎΠΏΡΠ»Π°ΡΠ½ΠΈ ΠΠΈΠ½ΡΠΊ ΡΡΠ»ΡΠΆΠ½ΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌ ΠΏΠΊΠ³-ΡΠΎΠ½ΡΠΈΠ³.
ΠΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ° Π ΡΠΏΠΏ Π΄ΠΎΠ΄Π°ΡΠΊΠ° Π·Π° ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ ΠΠΏΠ΅Π½Π¦Π Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅
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"
ΠΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΠΎΠ½ΠΈ ΠΊΠΎΠ΄ Π·Π° ΡΠ°ΡΡΠ»Π°ΡΠΈΠ²Π°ΡΠ΅ ΠΠ‘ΠΠ-Π° ΠΈ Π³Π΅Π½Π΅ΡΠΈΡΠ°ΡΠ΅ Π³ΡΡΠΏΠ΅ Π·Π° ΠΏΡΠ΅Π½ΠΎΡ Ρ ΠΌΠΎΠ΄Π΅Π» ΡΠ΅ Π΄Π°Ρ ΠΈΡΠΏΠΎΠ΄ ΡΠΏΠΎΡΠ»Π΅ΡΠ°. ΠΡΠ²ΠΎ Π΄ΠΎΠ΄Π°ΡΡΠ΅ Π»ΠΎΠΊΠ°Π»Π½ΠΈ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡΡΠΌ ΠΏΡΠΎΡΠ΅ΠΊΡΠ° Π΄Π° Π±ΠΈΡΡΠ΅ ΡΡΠ°ΠΆΠΈΠ»ΠΈ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ΅ Π·Π°Π³Π»Π°Π²ΡΠ° (ΠΏΠΎΡΡΠ΅Π±Π½ΠΎ Π·Π° Π½Π΄ΡΡΠΎΠ½):
Sys.setenv("PKG_CXXFLAGS" = paste0("-I", normalizePath(file.path("src"))))
ΠΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ° ΠΊΠΎΠ½Π²Π΅ΡΠ·ΠΈΡΠ΅ ΠΠ‘ΠΠ Ρ ΡΠ΅Π½Π·ΠΎΡ Ρ Π¦++
// [[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
β ΡΡΠ½ΠΊΡΠΈΡΠ° Π°Π½Π°Π»ΠΈΠ·ΠΈΡΠ° ΠΠ‘ΠΠ ΡΡΡΠΈΠ½Π³, ΠΈΠ·Π΄Π²Π°ΡΠ° ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ΅ ΡΠ°ΡΠ°ΠΊΠ°, ΠΏΠ°ΠΊΡΡΠ΅ ΠΈΡ Ρ Π²Π΅ΠΊΡΠΎΡ; -
ocv_draw_lines
β ΠΈΠ· ΡΠ΅Π·ΡΠ»ΡΡΡΡΡΠ΅Π³ Π²Π΅ΠΊΡΠΎΡΠ° ΡΠ°ΡΠ°ΠΊΠ°, ΡΡΡΠ° Π²ΠΈΡΠ΅Π±ΠΎΡΠ½Π΅ Π»ΠΈΠ½ΠΈΡΠ΅; -
process
β ΠΊΠΎΠΌΠ±ΠΈΠ½ΡΡΠ΅ Π³ΠΎΡΠ΅ Π½Π°Π²Π΅Π΄Π΅Π½Π΅ ΡΡΠ½ΠΊΡΠΈΡΠ΅ ΠΈ ΡΠ°ΠΊΠΎΡΠ΅ Π΄ΠΎΠ΄Π°ΡΠ΅ ΠΌΠΎΠ³ΡΡΠ½ΠΎΡΡ ΡΠΊΠ°Π»ΠΈΡΠ°ΡΠ° ΡΠ΅Π·ΡΠ»ΡΠΈΡΠ°ΡΡΡΠ΅ ΡΠ»ΠΈΠΊΠ΅; -
cpp_process_json_str
- ΠΎΠΌΠΎΡΠ°Ρ ΠΏΡΠ΅ΠΊΠΎ ΡΡΠ½ΠΊΡΠΈΡΠ΅process
, ΠΊΠΎΡΠΈ ΠΈΠ·Π²ΠΎΠ·ΠΈ ΡΠ΅Π·ΡΠ»ΡΠ°Ρ Ρ Π -ΠΎΠ±ΡΠ΅ΠΊΠ°Ρ (Π²ΠΈΡΠ΅Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΠΎΠ½Π°Π»Π½ΠΈ Π½ΠΈΠ·); -
cpp_process_json_vector
- ΠΎΠΌΠΎΡΠ°Ρ ΠΏΡΠ΅ΠΊΠΎ ΡΡΠ½ΠΊΡΠΈΡΠ΅cpp_process_json_str
, ΠΊΠΎΡΠΈ Π²Π°ΠΌ ΠΎΠΌΠΎΠ³ΡΡΠ°Π²Π° Π΄Π° ΠΎΠ±ΡΠ°ΡΡΡΠ΅ΡΠ΅ Π²Π΅ΠΊΡΠΎΡ Π½ΠΈΠ·Π° Ρ Π²ΠΈΡΠ΅Π½ΠΈΡΠ½ΠΎΠΌ ΡΠ΅ΠΆΠΈΠΌΡ.
ΠΠ° ΡΡΡΠ°ΡΠ΅ Π²ΠΈΡΠ΅Π±ΠΎΡΠ½ΠΈΡ Π»ΠΈΠ½ΠΈΡΠ° ΠΊΠΎΡΠΈΡΡΠ΅Π½ ΡΠ΅ Π₯Π‘Π ΠΌΠΎΠ΄Π΅Π» Π±ΠΎΡΠ°, Π½Π°ΠΊΠΎΠ½ ΡΠ΅Π³Π° ΡΠ΅ ΡΡΠ»Π΅Π΄ΠΈΠ»Π° ΠΊΠΎΠ½Π²Π΅ΡΠ·ΠΈΡΠ° Ρ Π ΠΠ. Π₯Π°ΡΠ΄Π΅ Π΄Π° ΡΠ΅ΡΡΠΈΡΠ°ΠΌΠΎ ΡΠ΅Π·ΡΠ»ΡΠ°Ρ:
arr <- cpp_process_json_str(tmp_data[4, drawing])
dim(arr)
# [1] 256 256 3
plot(magick::image_read(arr))
ΠΠΎΡΠ΅ΡΠ΅ΡΠ΅ Π±ΡΠ·ΠΈΠ½Π΅ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ° Ρ Π ΠΈ Π¦++
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")
ΠΠ°ΠΎ ΡΡΠΎ Π²ΠΈΠ΄ΠΈΡΠ΅, ΠΏΠΎΠ²Π΅ΡΠ°ΡΠ΅ Π±ΡΠ·ΠΈΠ½Π΅ ΡΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Π»ΠΎ Π²Π΅ΠΎΠΌΠ° Π·Π½Π°ΡΠ°ΡΠ½ΠΈΠΌ ΠΈ Π½ΠΈΡΠ΅ ΠΌΠΎΠ³ΡΡΠ΅ ΡΡΡΡΠΈΡΠΈ Π¦++ ΠΊΠΎΠ΄ ΠΏΠ°ΡΠ°Π»Π΅Π»ΠΈΠ·Π°ΡΠΈΡΠΎΠΌ Π ΠΊΠΎΠ΄Π°.
3. ΠΡΠ΅ΡΠ°ΡΠΎΡΠΈ Π·Π° ΠΈΡΡΠΎΠ²Π°Ρ ΠΏΠ°ΡΡΠΈΡΠ° ΠΈΠ· Π±Π°Π·Π΅ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°
Π ΠΈΠΌΠ° Π·Π°ΡΠ»ΡΠΆΠ΅Π½Ρ ΡΠ΅ΠΏΡΡΠ°ΡΠΈΡΡ Π·Π° ΠΎΠ±ΡΠ°Π΄Ρ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° ΠΊΠΎΡΠΈ ΡΠ΅ ΡΠΊΠ»Π°ΠΏΠ°ΡΡ Ρ Π ΠΠ, Π΄ΠΎΠΊ ΠΠΈΡΡ ΠΎΠ½ Π²ΠΈΡΠ΅ ΠΊΠ°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΠ΅ ΠΈΡΠ΅ΡΠ°ΡΠΈΠ²Π½Π° ΠΎΠ±ΡΠ°Π΄Π° ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°, ΡΡΠΎ Π²Π°ΠΌ ΠΎΠΌΠΎΠ³ΡΡΠ°Π²Π° Π΄Π° Π»Π°ΠΊΠΎ ΠΈ ΠΏΡΠΈΡΠΎΠ΄Π½ΠΎ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠΈΡΠ°ΡΠ΅ ΠΏΡΠΎΡΠ°ΡΡΠ½Π΅ Π²Π°Π½ ΡΠ΅Π·Π³ΡΠ° (ΠΏΡΠΎΡΠ°ΡΡΠ½ΠΈ ΠΏΠΎΠΌΠΎΡΡ Π΅ΠΊΡΡΠ΅ΡΠ½Π΅ ΠΌΠ΅ΠΌΠΎΡΠΈΡΠ΅). ΠΠ»Π°ΡΠΈΡΠ°Π½ ΠΈ ΡΠ΅Π»Π΅Π²Π°Π½ΡΠ°Π½ ΠΏΡΠΈΠΌΠ΅Ρ Π·Π° Π½Π°Ρ Ρ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΡ ΠΎΠΏΠΈΡΠ°Π½ΠΎΠ³ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° ΡΡ Π΄ΡΠ±ΠΎΠΊΠ΅ Π½Π΅ΡΡΠΎΠ½ΡΠΊΠ΅ ΠΌΡΠ΅ΠΆΠ΅ ΠΎΠ±ΡΡΠ΅Π½Π΅ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠΌ Π³ΡΠ°Π΄ΠΈΡΠ΅Π½ΡΠ° ΡΠΏΡΡΡΠ°ΡΠ° ΡΠ° Π°ΠΏΡΠΎΠΊΡΠΈΠΌΠ°ΡΠΈΡΠΎΠΌ Π³ΡΠ°Π΄ΠΈΡΠ΅Π½ΡΠ° Π½Π° ΡΠ²Π°ΠΊΠΎΠΌ ΠΊΠΎΡΠ°ΠΊΡ ΠΊΠΎΡΠΈΡΡΠ΅ΡΠΈ ΠΌΠ°Π»ΠΈ Π΄Π΅ΠΎ ΠΏΠΎΡΠΌΠ°ΡΡΠ°ΡΠ°, ΠΈΠ»ΠΈ ΠΌΠΈΠ½ΠΈ-Π±Π°ΡΡΡ .
ΠΠΊΠ²ΠΈΡΠΈ Π·Π° Π΄ΡΠ±ΠΎΠΊΠΎ ΡΡΠ΅ΡΠ΅ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈ Ρ ΠΠΈΡΡ ΠΎΠ½-Ρ ΠΈΠΌΠ°ΡΡ ΠΏΠΎΡΠ΅Π±Π½Π΅ ΠΊΠ»Π°ΡΠ΅ ΠΊΠΎΡΠ΅ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠΈΡΠ°ΡΡ ΠΈΡΠ΅ΡΠ°ΡΠΎΡΠ΅ Π½Π° ΠΎΡΠ½ΠΎΠ²Ρ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°: ΡΠ°Π±Π΅Π»Π΅, ΡΠ»ΠΈΠΊΠ΅ Ρ ΡΠ°ΡΡΠΈΠΊΠ»Π°ΠΌΠ°, Π±ΠΈΠ½Π°ΡΠ½ΠΈ ΡΠΎΡΠΌΠ°ΡΠΈ, ΠΈΡΠ΄. ΠΠΎΠΆΠ΅ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈΡΠΈ Π³ΠΎΡΠΎΠ²Π΅ ΠΎΠΏΡΠΈΡΠ΅ ΠΈΠ»ΠΈ Π½Π°ΠΏΠΈΡΠ°ΡΠΈ ΡΠ²ΠΎΡΠ΅ Π·Π° ΠΎΠ΄ΡΠ΅ΡΠ΅Π½Π΅ Π·Π°Π΄Π°ΡΠΊΠ΅. Π£ Π ΠΌΠΎΠΆΠ΅ΠΌΠΎ ΠΈΡΠΊΠΎΡΠΈΡΡΠΈΡΠΈ ΡΠ²Π΅ ΠΊΠ°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΡΠΈΠΊΠ΅ ΠΠΈΡΡ ΠΎΠ½ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅ ΠΊΠ΅ΡΠ°Ρ ΡΠ° ΡΠ²ΠΎΡΠΈΠΌ ΡΠ°Π·Π»ΠΈΡΠΈΡΠΈΠΌ ΠΏΠΎΠ·Π°Π΄ΠΈΠ½Π°ΠΌΠ° ΠΊΠΎΡΠΈΡΡΠ΅ΡΠΈ ΠΈΡΡΠΎΠΈΠΌΠ΅Π½ΠΈ ΠΏΠ°ΠΊΠ΅Ρ, ΠΊΠΎΡΠΈ Π·Π°ΡΠ·Π²ΡΠ°Ρ ΡΠ°Π΄ΠΈ Π½Π° Π²ΡΡ Ρ ΠΏΠ°ΠΊΠ΅ΡΠ° ΠΌΡΠ΅ΠΆΠ°ΡΡΠΈ. ΠΠ²ΠΎ ΠΏΠΎΡΠ»Π΅Π΄ΡΠ΅ Π·Π°ΡΠ»ΡΠΆΡΡΠ΅ ΠΏΠΎΡΠ΅Π±Π°Π½ Π΄ΡΠ³ ΡΠ»Π°Π½Π°ΠΊ; Π½Π΅ ΡΠ°ΠΌΠΎ Π΄Π° Π²Π°ΠΌ ΠΎΠΌΠΎΠ³ΡΡΠ°Π²Π° Π΄Π° ΠΏΠΎΠΊΡΠ΅Π½Π΅ΡΠ΅ ΠΠΈΡΡ ΠΎΠ½ ΠΊΠΎΠ΄ ΠΈΠ· Π , Π²Π΅Ρ Π²Π°ΠΌ ΡΠ°ΠΊΠΎΡΠ΅ ΠΎΠΌΠΎΠ³ΡΡΠ°Π²Π° Π΄Π° ΠΏΡΠ΅Π½ΠΎΡΠΈΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΠ΅ ΠΈΠ·ΠΌΠ΅ΡΡ Π ΠΈ ΠΠΈΡΡ ΠΎΠ½ ΡΠ΅ΡΠΈΡΠ°, Π°ΡΡΠΎΠΌΠ°ΡΡΠΊΠΈ ΠΎΠ±Π°Π²ΡΠ°ΡΡΡΠΈ ΡΠ²Π΅ ΠΏΠΎΡΡΠ΅Π±Π½Π΅ ΠΊΠΎΠ½Π²Π΅ΡΠ·ΠΈΡΠ΅ ΡΠΈΠΏΠΎΠ²Π°.
Π Π΅ΡΠΈΠ»ΠΈ ΡΠΌΠΎ ΡΠ΅ ΠΏΠΎΡΡΠ΅Π±Π΅ Π΄Π° ΡΡΠ²Π°ΠΌΠΎ ΡΠ²Π΅ ΠΏΠΎΠ΄Π°ΡΠΊΠ΅ Ρ Π ΠΠ-Ρ ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ΠΌ ΠΠΎΠ½Π΅ΡΠΠΠΠΈΡΠ΅-Π°, ΡΠ°Π² ΠΏΠΎΡΠ°ΠΎ Π½Π° βΠ½Π΅ΡΡΠ°Π»Π½ΠΎΡ ΠΌΡΠ΅ΠΆΠΈβ ΡΠ΅ ΠΎΠ±Π°Π²ΡΠ°ΡΠΈ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΈ ΠΊΠΎΠ΄ Ρ ΠΠΈΡΡ ΠΎΠ½-Ρ, ΡΠ°ΠΌΠΎ ΠΌΠΎΡΠ°ΠΌΠΎ Π΄Π° Π½Π°ΠΏΠΈΡΠ΅ΠΌΠΎ ΠΈΡΠ΅ΡΠ°ΡΠΎΡ ΠΏΡΠ΅ΠΊΠΎ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°, ΠΏΠΎΡΡΠΎ Π½ΠΈΡΡΠ° Π½ΠΈΡΠ΅ ΡΠΏΡΠ΅ΠΌΠ½ΠΎ Π·Π° ΡΠ°ΠΊΠ²Ρ ΡΠΈΡΡΠ°ΡΠΈΡΡ Ρ Π ΠΈΠ»ΠΈ ΠΠΈΡΡ ΠΎΠ½-Ρ. Π£ ΡΡΡΡΠΈΠ½ΠΈ ΠΏΠΎΡΡΠΎΡΠ΅ ΡΠ°ΠΌΠΎ Π΄Π²Π° Π·Π°Ρ ΡΠ΅Π²Π° Π·Π° ΡΠ΅Π³Π°: ΠΌΠΎΡΠ° Π΄Π° Π²ΡΠ°ΡΠ° ΠΏΠ°ΠΊΠ΅ΡΠ΅ Ρ Π±Π΅ΡΠΊΠΎΠ½Π°ΡΠ½ΠΎΡ ΠΏΠ΅ΡΡΠΈ ΠΈ Π΄Π° ΡΠ°ΡΡΠ²Π° ΡΠ²ΠΎΡΠ΅ ΡΡΠ°ΡΠ΅ ΠΈΠ·ΠΌΠ΅ΡΡ ΠΈΡΠ΅ΡΠ°ΡΠΈΡΠ° (ΠΎΠ²ΠΎ ΠΏΠΎΡΠ»Π΅Π΄ΡΠ΅ Ρ Π ΡΠ΅ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠΈΡΠ° Π½Π° Π½Π°ΡΡΠ΅Π΄Π½ΠΎΡΡΠ°Π²Π½ΠΈΡΠΈ Π½Π°ΡΠΈΠ½ ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ΠΌ Π·Π°ΡΠ²Π°ΡΠ°ΡΠ°). Π Π°Π½ΠΈΡΠ΅ ΡΠ΅ Π±ΠΈΠ»ΠΎ ΠΏΠΎΡΡΠ΅Π±Π½ΠΎ Π΅ΠΊΡΠΏΠ»ΠΈΡΠΈΡΠ½ΠΎ ΠΊΠΎΠ½Π²Π΅ΡΡΠΎΠ²Π°ΡΠΈ Π Π½ΠΈΠ·ΠΎΠ²Π΅ Ρ Π½ΡΠΌΠΏΠΈ Π½ΠΈΠ·ΠΎΠ²Π΅ ΡΠ½ΡΡΠ°Ρ ΠΈΡΠ΅ΡΠ°ΡΠΎΡΠ°, Π°Π»ΠΈ ΡΡΠ΅Π½ΡΡΠ½Π° Π²Π΅ΡΠ·ΠΈΡΠ° ΠΏΠ°ΠΊΠ΅ΡΠ° ΠΊΠ΅ΡΠ°Ρ ΡΠ°ΠΌΠ° ΡΠΎ ΡΠ°Π΄ΠΈ.
ΠΠΎΠΊΠ°Π·Π°Π»ΠΎ ΡΠ΅ Π΄Π° ΡΠ΅ ΠΈΡΠ΅ΡΠ°ΡΠΎΡ Π·Π° ΠΏΠΎΠ΄Π°ΡΠΊΠ΅ ΠΎ ΠΎΠ±ΡΡΠΈ ΠΈ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡΠΈ ΡΠ»Π΅Π΄Π΅ΡΠΈ:
ΠΡΠ΅ΡΠ°ΡΠΎΡ Π·Π° ΠΎΠ±ΡΠΊΡ ΠΈ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡΡ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°
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
ΡΠ²Π°ΠΊΠΈ ΠΏΠΎΡΠ΅Π· ΡΠ΅ Π½Π°ΡΡΡΠ°Π½ Ρ Π½ΠΎΠ²ΠΎΡ Π±ΠΎΡΠΈ) ΠΈ ΠΈΠ½Π΄ΠΈΠΊΠ°ΡΠΎΡ Π·Π° ΠΏΡΠ΅ΡΡ
ΠΎΠ΄Π½Ρ ΠΎΠ±ΡΠ°Π΄Ρ Π·Π° ΠΌΡΠ΅ΠΆΠ΅ ΠΏΡΠ΅ΡΡ
ΠΎΠ΄Π½ΠΎ ΠΎΠ±ΡΡΠ΅Π½Π΅ Π½Π° ΠΈΠΌΠ°Π³Π΅Π½Π΅Ρ-Ρ. ΠΠ²ΠΎ ΠΏΠΎΡΠ»Π΅Π΄ΡΠ΅ ΡΠ΅ ΠΏΠΎΡΡΠ΅Π±Π½ΠΎ Π΄Π° Π±ΠΈ ΡΠ΅ ΡΠΊΠ°Π»ΠΈΡΠ°Π»ΠΈ Π²ΡΠ΅Π΄Π½ΠΎΡΡΠΈ ΠΏΠΈΠΊΡΠ΅Π»Π° ΠΎΠ΄ ΠΈΠ½ΡΠ΅ΡΠ²Π°Π»Π° [0, 1] Π΄ΠΎ ΠΈΠ½ΡΠ΅ΡΠ²Π°Π»Π° [-1, 1], ΠΊΠΎΡΠΈ ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠ΅Π½ ΠΏΡΠΈ ΠΎΠ±ΡΡΠ°Π²Π°ΡΡ ΠΈΡΠΏΠΎΡΡΡΠ΅Π½ΠΈΡ
ΠΊΠ΅ΡΠ°Ρ ΠΌΠΎΠ΄Π΅Π»ΠΈ.
ΠΠΊΡΡΠ΅ΡΠ½Π° ΡΡΠ½ΠΊΡΠΈΡΠ° ΡΠ°Π΄ΡΠΆΠΈ ΠΏΡΠΎΠ²Π΅ΡΡ ΡΠΈΠΏΠ° Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠ°, ΡΠ°Π±Π΅Π»Ρ data.table
ΡΠ° Π½Π°ΡΡΠΌΠΈΡΠ½ΠΎ ΠΏΠΎΠΌΠ΅ΡΠ°Π½ΠΈΠΌ Π±ΡΠΎΡΠ΅Π²ΠΈΠΌΠ° Π»ΠΈΠ½ΠΈΡΠ° ΠΈΠ· samples_index
ΠΈ Π±ΡΠΎΡΠ΅Π²ΠΈ ΡΠ΅ΡΠΈΡΠ°, Π±ΡΠΎΡΠ°Ρ ΠΈ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»Π°Π½ Π±ΡΠΎΡ ΡΠ΅ΡΠΈΡΠ°, ΠΊΠ°ΠΎ ΠΈ Π‘ΠΠ ΠΈΠ·ΡΠ°Π· Π·Π° ΠΈΡΡΠΎΠ²Π°Ρ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° ΠΈΠ· Π±Π°Π·Π΅ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°. ΠΠΎΠ΄Π°ΡΠ½ΠΎ, Π΄Π΅ΡΠΈΠ½ΠΈΡΠ°Π»ΠΈ ΡΠΌΠΎ Π±ΡΠ·ΠΈ Π°Π½Π°Π»ΠΎΠ³ ΡΡΠ½ΠΊΡΠΈΡΠ΅ ΡΠ½ΡΡΡΠ° keras::to_categorical()
. ΠΠΎΡΠΈΡΡΠΈΠ»ΠΈ ΡΠΌΠΎ ΡΠΊΠΎΡΠΎ ΡΠ²Π΅ ΠΏΠΎΠ΄Π°ΡΠΊΠ΅ Π·Π° ΠΎΠ±ΡΠΊΡ, ΠΎΡΡΠ°Π²ΡΠ°ΡΡΡΠΈ ΠΏΠΎΠ»Π° ΠΏΡΠΎΡΠ΅Π½ΡΠ° Π·Π° Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡΡ, ΡΠ°ΠΊΠΎ Π΄Π° ΡΠ΅ Π²Π΅Π»ΠΈΡΠΈΠ½Π° Π΅ΠΏΠΎΡ
Π΅ Π±ΠΈΠ»Π° ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½Π° ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠΌ steps_per_epoch
ΠΏΡΠΈΠ»ΠΈΠΊΠΎΠΌ ΠΏΠΎΠ·ΠΈΠ²Π°ΡΠ° keras::fit_generator()
, ΠΈ ΡΡΠ°ΡΠ΅ if (i > max_i)
ΡΠ°Π΄ΠΈΠΎ ΡΠ°ΠΌΠΎ Π·Π° ΠΈΡΠ΅ΡΠ°ΡΠΎΡ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡΠ΅.
Π£ ΠΈΠ½ΡΠ΅ΡΠ½ΠΎΡ ΡΡΠ½ΠΊΡΠΈΡΠΈ, ΠΈΠ½Π΄Π΅ΠΊΡΠΈ ΡΠ΅Π΄ΠΎΠ²Π° ΡΠ΅ ΠΏΡΠ΅ΡΠ·ΠΈΠΌΠ°ΡΡ Π·Π° ΡΠ»Π΅Π΄Π΅ΡΡ Π³ΡΡΠΏΡ, Π·Π°ΠΏΠΈΡΠΈ ΡΠ΅ ΡΡΠΈΡΠ°Π²Π°ΡΡ ΠΈΠ· Π±Π°Π·Π΅ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° ΡΠ° ΠΏΠΎΠ²Π΅ΡΠ°ΡΠ΅ΠΌ Π±ΡΠΎΡΠ°ΡΠ° Π³ΡΡΠΏΠ΅, ΠΠ‘ΠΠ ΡΠ°ΡΡΠ»Π°ΡΠΈΠ²Π°ΡΠ΅ΠΌ (ΡΡΠ½ΠΊΡΠΈΡΠ° cpp_process_json_vector()
, Π½Π°ΠΏΠΈΡΠ°Π½ Ρ Π¦++) ΠΈ ΠΊΡΠ΅ΠΈΡΠ°ΡΠ΅ Π½ΠΈΠ·ΠΎΠ²Π° ΠΊΠΎΡΠΈ ΠΎΠ΄Π³ΠΎΠ²Π°ΡΠ°ΡΡ ΡΠ»ΠΈΠΊΠ°ΠΌΠ°. ΠΠ°ΡΠΈΠΌ ΡΠ΅ ΠΊΡΠ΅ΠΈΡΠ°ΡΡ ΡΠ΅Π΄Π½ΠΎΠΊΡΠ°ΡΠ½ΠΈ Π²Π΅ΠΊΡΠΎΡΠΈ ΡΠ° ΠΎΠ·Π½Π°ΠΊΠ°ΠΌΠ° ΠΊΠ»Π°ΡΠ°, Π½ΠΈΠ·ΠΎΠ²ΠΈ ΡΠ° Π²ΡΠ΅Π΄Π½ΠΎΡΡΠΈΠΌΠ° ΠΏΠΈΠΊΡΠ΅Π»Π° ΠΈ ΠΎΠ·Π½Π°ΠΊΠ°ΠΌΠ° ΡΠ΅ ΠΊΠΎΠΌΠ±ΠΈΠ½ΡΡΡ Ρ Π»ΠΈΡΡΡ, ΡΡΠΎ ΡΠ΅ ΠΏΠΎΠ²ΡΠ°ΡΠ½Π° Π²ΡΠ΅Π΄Π½ΠΎΡΡ. ΠΠ° Π±ΠΈΡΠΌΠΎ ΡΠ±ΡΠ·Π°Π»ΠΈ ΡΠ°Π΄, ΠΊΠΎΡΠΈΡΡΠΈΠ»ΠΈ ΡΠΌΠΎ ΠΊΡΠ΅ΠΈΡΠ°ΡΠ΅ ΠΈΠ½Π΄Π΅ΠΊΡΠ° Ρ ΡΠ°Π±Π΅Π»Π°ΠΌΠ° data.table
ΠΈ ΠΌΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΈΡΠ° ΠΏΡΠ΅ΠΊΠΎ Π²Π΅Π·Π΅ - Π±Π΅Π· ΠΎΠ²ΠΈΡ
ΠΏΠ°ΠΊΠ΅ΡΠ° βΡΠΈΠΏΠΎΠ²Π°β ΠΏΠΎΠ΄Π°ΡΠΈ.ΡΠ°Π±Π΅Π»Π° ΠΡΠΈΠ»ΠΈΡΠ½ΠΎ ΡΠ΅ ΡΠ΅ΡΠΊΠΎ Π·Π°ΠΌΠΈΡΠ»ΠΈΡΠΈ Π΅ΡΠΈΠΊΠ°ΡΠ°Π½ ΡΠ°Π΄ ΡΠ° Π±ΠΈΠ»ΠΎ ΠΊΠΎΡΠΎΠΌ Π·Π½Π°ΡΠ°ΡΠ½ΠΎΠΌ ΠΊΠΎΠ»ΠΈΡΠΈΠ½ΠΎΠΌ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° Ρ Π .
Π Π΅Π·ΡΠ»ΡΠ°ΡΠΈ ΠΌΠ΅ΡΠ΅ΡΠ° Π±ΡΠ·ΠΈΠ½Π΅ Π½Π° Π¦ΠΎΡΠ΅ ΠΈ5 Π»Π°ΠΏΡΠΎΠΏΡ ΡΡ ΡΠ»Π΅Π΄Π΅ΡΠΈ:
ΠΠ΅Π½ΡΡ ΠΌΠ°ΡΠΊ ΠΈΡΠ΅ΡΠ°ΡΠΎΡΠ°
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)
, ΠΎΠ΄Π½ΠΎΡΠ½ΠΎ Π±ΡΠΎΡ ΠΊΠ°Π½Π°Π»Π° ΡΠ΅ Π½Π΅ ΠΌΠΎΠΆΠ΅ ΠΌΠ΅ΡΠ°ΡΠΈ. Π£ ΠΠΈΡΡ
ΠΎΠ½-Ρ Π½Π΅ΠΌΠ° ΡΠ°ΠΊΠ²ΠΎΠ³ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅ΡΠ°, ΠΏΠ° ΡΠΌΠΎ ΠΏΠΎΠΆΡΡΠΈΠ»ΠΈ ΠΈ Π½Π°ΠΏΠΈΡΠ°Π»ΠΈ ΡΠΎΠΏΡΡΠ²Π΅Π½Ρ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡ ΠΎΠ²Π΅ Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΠ΅, ΠΏΡΠ°ΡΠ΅ΡΠΈ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΈ ΡΠ»Π°Π½Π°ΠΊ (Π±Π΅Π· ΠΈΡΠΏΠ°Π΄Π°ΡΠ° ΠΊΠΎΡΠΈ ΡΠ΅ Ρ ΠΊΠ΅ΡΠ°Ρ Π²Π΅ΡΠ·ΠΈΡΠΈ):
ΠΠΎΠ±ΠΈΠ»Π΅Π½Π΅Ρ Π²1 Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ°
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()
Π΄ΠΎΠ±ΠΈΡΡΠ΅ ΡΠ΅ΠΆΠΈΠ½Π΅ ΠΌΠΎΠ΄Π΅Π»Π° Ρ ΠΎΠ±Π»ΠΈΠΊΡ Π»ΠΈΡΡΠ΅ Π Π½ΠΈΠ·ΠΎΠ²Π°, ΠΏΡΠΎΠΌΠ΅Π½ΠΈΡΠ΅ Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΡΡ ΠΏΡΠ²ΠΎΠ³ Π΅Π»Π΅ΠΌΠ΅Π½ΡΠ° ΠΎΠ²Π΅ Π»ΠΈΡΡΠ΅ (ΡΠ·ΠΈΠΌΠ°ΡΠ΅ΠΌ ΡΠ΅Π΄Π½ΠΎΠ³ ΠΊΠ°Π½Π°Π»Π° Π±ΠΎΡΠ΅ ΠΈΠ»ΠΈ ΡΡΡΠ΅Π΄ΡΠ°Π²Π°ΡΠ΅ΠΌ ΡΠ²Π° ΡΡΠΈ), Π° Π·Π°ΡΠΈΠΌ ΡΡΠΈΡΠ°ΡΡΠ΅ ΡΠ΅ΠΆΠΈΠ½Π΅ Π½Π°Π·Π°Π΄ Ρ ΠΌΠΎΠ΄Π΅Π» ΠΏΠΎΠΌΠΎΡΡ ΡΡΠ½ΠΊΡΠΈΡΠ΅ set_weights()
. ΠΠΈΠΊΠ°Π΄Π° Π½ΠΈΡΠΌΠΎ Π΄ΠΎΠ΄Π°Π»ΠΈ ΠΎΠ²Ρ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎΡΡ, ΡΠ΅Ρ ΡΠ΅ Ρ ΠΎΠ²ΠΎΡ ΡΠ°Π·ΠΈ Π²Π΅Ρ Π±ΠΈΠ»ΠΎ ΡΠ°ΡΠ½ΠΎ Π΄Π° ΡΠ΅ ΠΏΡΠΎΠ΄ΡΠΊΡΠΈΠ²Π½ΠΈΡΠ΅ ΡΠ°Π΄ΠΈΡΠΈ ΡΠ° ΡΠ»ΠΈΠΊΠ°ΠΌΠ° Ρ Π±ΠΎΡΠΈ.
ΠΠ·Π²Π΅Π»ΠΈ ΡΠΌΠΎ Π²Π΅ΡΠΈΠ½Ρ Π΅ΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½Π°ΡΠ° ΠΊΠΎΡΠΈΡΡΠ΅ΡΠΈ ΠΌΠΎΠ±ΠΈΠ»Π½Π΅ ΠΌΡΠ΅ΠΆΠ΅ Π²Π΅ΡΠ·ΠΈΡΠ΅ 1 ΠΈ 2, ΠΊΠ°ΠΎ ΠΈ ΡΠ΅ΡΠ½Π΅Ρ34. ΠΠΎΠ΄Π΅ΡΠ½ΠΈΡΠ΅ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ΅ ΠΊΠ°ΠΎ ΡΡΠΎ ΡΠ΅ Π‘Π-Π Π΅ΡΠΠ΅ΠΡΡ ΡΡ ΡΠ΅ Π΄ΠΎΠ±ΡΠΎ ΠΏΠΎΠΊΠ°Π·Π°Π»Π΅ Π½Π° ΠΎΠ²ΠΎΠΌ ΡΠ°ΠΊΠΌΠΈΡΠ΅ΡΡ. ΠΠ°ΠΆΠ°Π»ΠΎΡΡ, Π½ΠΈΡΠΌΠΎ ΠΈΠΌΠ°Π»ΠΈ Π³ΠΎΡΠΎΠ²Π΅ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ΅ Π½Π° ΡΠ°ΡΠΏΠΎΠ»Π°Π³Π°ΡΡ, Π° Π½ΠΈΡΠΌΠΎ Π½ΠΈ ΠΏΠΈΡΠ°Π»ΠΈ ΡΠ²ΠΎΡΠ΅ (Π°Π»ΠΈ ΡΠ΅ΠΌΠΎ ΡΠ²Π°ΠΊΠ°ΠΊΠΎ ΠΏΠΈΡΠ°ΡΠΈ).
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)
ΠΠ»Π°ΡΡΠΈΡΠ½Π° ΠΊΠ΅ΡΠ° Π΄ΠΎΡΠΎΠΏΡ ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΡΠ° ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡ 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
ΠΈΠ· ΡΡΠ΅Π½ΡΡΠ½Π΅ Π²Π΅ΡΠ·ΠΈΡΠ΅ ΠΊΠ΅ΡΠ°Ρ Ρ ΡΠΏΠΎΡΡΠ΅Π±ΠΈ Π
ΠΠ²Π°Ρ ΠΏΡΠΈΡΡΡΠΏ ΡΠ΅ ΠΎΠΌΠΎΠ³ΡΡΠΈΠΎ Π΄Π° ΡΠ΅ Π·Π½Π°ΡΠ°ΡΠ½ΠΎ ΡΠ±ΡΠ·Π°ΡΡ Π΅ΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΠΈ ΡΠ° ΡΠ°Π·Π»ΠΈΡΠΈΡΠΈΠΌ ΠΌΠΎΠ΄Π΅Π»ΠΈΠΌΠ° Ρ ΠΏΠΎΡΠ΅ΡΠ΅ΡΡ ΡΠ° ΡΡΠ°Π΄ΠΈΡΠΈΠΎΠ½Π°Π»Π½ΠΈΡΠΈΠΌ ΠΏΠΎΠΊΡΠ΅ΡΠ°ΡΠ΅ΠΌ ΡΠΊΡΠΈΠΏΡΠΈ Ρ Π Π‘ΡΡΠ΄ΠΈΡ (ΠΏΠ°ΠΊΠ΅Ρ Π½Π°Π²ΠΎΠ΄ΠΈΠΌΠΎ ΠΊΠ°ΠΎ ΠΌΠΎΠ³ΡΡΡ Π°Π»ΡΠ΅ΡΠ½Π°ΡΠΈΠ²Ρ
6. ΠΠΎΠΊΠ΅ΡΠΈΠ·Π°ΡΠΈΡΠ° ΡΠΊΡΠΈΠΏΡΠΈ
ΠΠΎΡΠΈΡΡΠΈΠ»ΠΈ ΡΠΌΠΎ ΠΠΎΡΠΊΠ΅Ρ Π΄Π° ΠΎΠ±Π΅Π·Π±Π΅Π΄ΠΈΠΌΠΎ ΠΏΡΠ΅Π½ΠΎΡΠΈΠ²ΠΎΡΡ ΠΎΠΊΡΡΠΆΠ΅ΡΠ° Π·Π° ΠΌΠΎΠ΄Π΅Π»Π΅ ΠΎΠ±ΡΠΊΠ΅ ΠΈΠ·ΠΌΠ΅ΡΡ ΡΠ»Π°Π½ΠΎΠ²Π° ΡΠΈΠΌΠ° ΠΈ Π·Π° Π±ΡΠ·Ρ ΠΏΡΠΈΠΌΠ΅Π½Ρ Ρ ΠΎΠ±Π»Π°ΠΊΡ. ΠΠΎΠΆΠ΅ΡΠ΅ ΠΏΠΎΡΠ΅ΡΠΈ Π΄Π° ΡΠ΅ ΡΠΏΠΎΠ·Π½Π°ΡΠ΅ ΡΠ° ΠΎΠ²ΠΈΠΌ Π°Π»Π°ΡΠΎΠΌ, ΠΊΠΎΡΠΈ ΡΠ΅ ΡΠ΅Π»Π°ΡΠΈΠ²Π½ΠΎ Π½Π΅ΠΎΠ±ΠΈΡΠ°Π½ Π·Π° Π ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ΅ΡΠ°
ΠΠΎΡΠΊΠ΅Ρ Π²Π°ΠΌ ΠΎΠΌΠΎΠ³ΡΡΠ°Π²Π° Π΄Π° ΠΊΡΠ΅ΠΈΡΠ°ΡΠ΅ ΡΠΎΠΏΡΡΠ²Π΅Π½Π΅ ΡΠ»ΠΈΠΊΠ΅ ΠΎΠ΄ Π½ΡΠ»Π΅ ΠΈ Π΄Π° ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ Π΄ΡΡΠ³Π΅ ΡΠ»ΠΈΠΊΠ΅ ΠΊΠ°ΠΎ ΠΎΡΠ½ΠΎΠ²Ρ Π·Π° ΠΊΡΠ΅ΠΈΡΠ°ΡΠ΅ ΡΠΎΠΏΡΡΠ²Π΅Π½ΠΈΡ
. ΠΠ½Π°Π»ΠΈΠ·ΠΈΡΠ°ΡΡΡΠΈ Π΄ΠΎΡΡΡΠΏΠ½Π΅ ΠΎΠΏΡΠΈΡΠ΅, Π΄ΠΎΡΠ»ΠΈ ΡΠΌΠΎ Π΄ΠΎ Π·Π°ΠΊΡΡΡΠΊΠ° Π΄Π° ΡΠ΅ ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ°ΡΠ΅ ΠΠΠΠΠΠ, Π¦Π£ΠΠ+ΡΡΠΠΠ Π΄ΡΠ°ΡΠ²Π΅ΡΠ° ΠΈ ΠΠΈΡΡ
ΠΎΠ½ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° ΠΏΡΠΈΠ»ΠΈΡΠ½ΠΎ ΠΎΠ±ΠΈΠΌΠ½ΠΈ Π΄Π΅ΠΎ ΡΠ»ΠΈΠΊΠ΅ ΠΈ ΠΎΠ΄Π»ΡΡΠΈΠ»ΠΈ ΡΠΌΠΎ Π΄Π° Π·Π° ΠΎΡΠ½ΠΎΠ²Ρ ΡΠ·ΠΌΠ΅ΠΌΠΎ Π·Π²Π°Π½ΠΈΡΠ½Ρ ΡΠ»ΠΈΠΊΡ tensorflow/tensorflow:1.12.0-gpu
, Π΄ΠΎΠ΄Π°ΡΡΡΠΈ ΡΠ°ΠΌΠΎ ΠΏΠΎΡΡΠ΅Π±Π½Π΅ Π ΠΏΠ°ΠΊΠ΅ΡΠ΅.
ΠΠΎΠ½Π°ΡΠ½Π° Π΄ΠΎΡΠΊΠ΅Ρ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ° ΡΠ΅ ΠΈΠ·Π³Π»Π΅Π΄Π°Π»Π° ΠΎΠ²Π°ΠΊΠΎ:
ΠΠΎΡΠΊΠ΅ΡΡΠΈΠ»Π΅
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
ΡΠ° ΠΏΠΎΠ΄ΡΠ°Π·ΡΠΌΠ΅Π²Π°Π½ΠΈΠΌ Π²ΡΠ΅Π΄Π½ΠΎΡΡΠΈΠΌΠ°; Π°ΠΊΠΎ ΡΠ΅ ΠΏΡΠ²ΠΈ ΠΏΠΎΠ·ΠΈΡΠΈΠΎΠ½ΠΈ Π°ΡΠ³ΡΠΌΠ΅Π½Ρ "Π±Π°ΡΡ
", ΠΎΠ½Π΄Π° ΡΠ΅ ΠΊΠΎΠ½ΡΠ΅ΡΠ½Π΅Ρ Π·Π°ΠΏΠΎΡΠ΅ΡΠΈ ΠΈΠ½ΡΠ΅ΡΠ°ΠΊΡΠΈΠ²Π½ΠΎ ΡΠ° ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΌ ΡΠΊΠΎΡΠΊΠΎΠΌ. Π£ ΡΠ²ΠΈΠΌ ΠΎΡΡΠ°Π»ΠΈΠΌ ΡΠ»ΡΡΠ°ΡΠ΅Π²ΠΈΠΌΠ°, Π²ΡΠ΅Π΄Π½ΠΎΡΡΠΈ ΠΏΠΎΠ·ΠΈΡΠΈΠΎΠ½ΠΈΡ
Π°ΡΠ³ΡΠΌΠ΅Π½Π°ΡΠ° ΡΠ΅ Π·Π°ΠΌΠ΅ΡΡΡΡ: CMD="Rscript /app/train_nn.R $@"
.
ΠΡΠ΅Π΄ΠΈ Π½Π°ΠΏΠΎΠΌΠ΅Π½ΡΡΠΈ Π΄Π° ΡΠ΅ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡΡΠΌΠΈ ΡΠ° ΠΈΠ·Π²ΠΎΡΠ½ΠΈΠΌ ΠΏΠΎΠ΄Π°ΡΠΈΠΌΠ° ΠΈ Π±Π°Π·ΠΎΠΌ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ°, ΠΊΠ°ΠΎ ΠΈ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡΡΠΌ Π·Π° ΡΡΠ²Π°ΡΠ΅ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ ΠΌΠΎΠ΄Π΅Π»Π°, ΠΌΠΎΠ½ΡΠΈΡΠ°ΡΡ ΡΠ½ΡΡΠ°Ρ ΠΊΠΎΠ½ΡΠ΅ΡΠ½Π΅ΡΠ° ΠΈΠ· Ρ ΠΎΡΡ ΡΠΈΡΡΠ΅ΠΌΠ°, ΡΡΠΎ Π²Π°ΠΌ ΠΎΠΌΠΎΠ³ΡΡΠ°Π²Π° Π΄Π° ΠΏΡΠΈΡΡΡΠΏΠΈΡΠ΅ ΡΠ΅Π·ΡΠ»ΡΠ°ΡΠΈΠΌΠ° ΡΠΊΡΠΈΠΏΡΠΈ Π±Π΅Π· Π½Π΅ΠΏΠΎΡΡΠ΅Π±Π½ΠΈΡ ΠΌΠ°Π½ΠΈΠΏΡΠ»Π°ΡΠΈΡΠ°.
7. ΠΠΎΡΠΈΡΡΠ΅ΡΠ΅ Π²ΠΈΡΠ΅ ΠΠΠ£-Π° Π½Π° ΠΠΎΠΎΠ³Π»Π΅ Π¦Π»ΠΎΡΠ΄-Ρ
ΠΠ΅Π΄Π½Π° ΠΎΠ΄ ΠΊΠ°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΡΠΈΠΊΠ° ΡΠ°ΠΊΠΌΠΈΡΠ΅ΡΠ° ΡΡ Π±ΠΈΠ»ΠΈ Π²Π΅ΠΎΠΌΠ° Π±ΡΡΠ½ΠΈ ΠΏΠΎΠ΄Π°ΡΠΈ (ΠΏΠΎΠ³Π»Π΅Π΄Π°ΡΡΠ΅ Π½Π°ΡΠ»ΠΎΠ²Π½Ρ ΡΠ»ΠΈΠΊΡ, ΠΏΠΎΠ·Π°ΡΠΌΡΠ΅Π½Ρ ΡΠ° @ΠΠ΅ΠΈΠ³Ρ
.ΠΏΠ»Ρ ΠΈΠ· ΠΠΠ‘ ΡΠ»Π°ΡΠΊ-Π°). ΠΠ΅Π»ΠΈΠΊΠ΅ ΡΠ΅ΡΠΈΡΠ΅ ΠΏΠΎΠΌΠ°ΠΆΡ Ρ Π±ΠΎΡΠ±ΠΈ ΠΏΡΠΎΡΠΈΠ² ΠΎΠ²ΠΎΠ³Π°, ΠΈ Π½Π°ΠΊΠΎΠ½ Π΅ΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½Π°ΡΠ° Π½Π° ΡΠ°ΡΡΠ½Π°ΡΡ ΡΠ° 1 ΠΠΠ£-ΠΎΠΌ, ΠΎΠ΄Π»ΡΡΠΈΠ»ΠΈ ΡΠΌΠΎ Π΄Π° ΡΠ°Π²Π»Π°Π΄Π°ΠΌΠΎ ΠΌΠΎΠ΄Π΅Π»Π΅ ΠΎΠ±ΡΠΊΠ΅ Π½Π° Π½Π΅ΠΊΠΎΠ»ΠΈΠΊΠΎ ΠΠΠ£-Π° Ρ ΠΎΠ±Π»Π°ΠΊΡ. ΠΠΎΡΠΈΡΡΠΈ ΠΠΎΠΎΠ³Π»Π΅Π¦Π»ΠΎΡΠ΄ (dev/shm
.
ΠΠ°ΡΠ²Π΅ΡΠΈ ΠΈΠ½ΡΠ΅ΡΠ΅Ρ ΡΠ΅ ΡΡΠ°Π³ΠΌΠ΅Π½Ρ ΠΊΠΎΠ΄Π° ΠΎΠ΄Π³ΠΎΠ²ΠΎΡΠ°Π½ Π·Π° ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ Π²ΠΈΡΠ΅ ΠΠΠ£-ΠΎΠ²Π°. ΠΡΠ²ΠΎ, ΠΌΠΎΠ΄Π΅Π» ΡΠ΅ ΠΊΡΠ΅ΠΈΡΠ° Π½Π° Π¦ΠΠ£-Ρ ΠΏΠΎΠΌΠΎΡΡ ΠΌΠ΅Π½Π°ΡΠ΅ΡΠ° ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ°, Π±Π°Ρ ΠΊΠ°ΠΎ Ρ ΠΠΈΡΡ ΠΎΠ½-Ρ:
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
)
})
ΠΠ°ΡΠΈΠΌ ΡΠ΅ Π½Π΅ΠΏΡΠ΅Π²Π΅Π΄Π΅Π½ΠΈ (ΠΎΠ²ΠΎ ΡΠ΅ Π²Π°ΠΆΠ½ΠΎ) ΠΌΠΎΠ΄Π΅Π» ΠΊΠΎΠΏΠΈΡΠ° Π½Π° Π΄Π°ΡΠΈ Π±ΡΠΎΡ Π΄ΠΎΡΡΡΠΏΠ½ΠΈΡ ΠΠΠ£-Π° ΠΈ ΡΠ΅ΠΊ Π½Π°ΠΊΠΎΠ½ ΡΠΎΠ³Π° ΡΠ΅ ΠΊΠΎΠΌΠΏΠ°ΡΠ»ΠΈΡΠ°:
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)
)
ΠΠ»Π°ΡΠΈΡΠ½Π° ΡΠ΅Ρ Π½ΠΈΠΊΠ° Π·Π°ΠΌΡΠ·Π°Π²Π°ΡΠ° ΡΠ²ΠΈΡ ΡΠ»ΠΎΡΠ΅Π²Π° ΠΎΡΠΈΠΌ ΠΏΠΎΡΠ»Π΅Π΄ΡΠ΅Π³, ΠΎΠ±ΡΡΠ°Π²Π°ΡΠ° ΠΏΠΎΡΠ»Π΅Π΄ΡΠ΅Π³ ΡΠ»ΠΎΡΠ°, ΠΎΠ΄ΠΌΡΠ·Π°Π²Π°ΡΠ° ΠΈ ΠΏΡΠ΅ΠΎΠ±ΡΠΊΠ΅ ΡΠ΅Π»ΠΎΠ³ ΠΌΠΎΠ΄Π΅Π»Π° Π·Π° Π½Π΅ΠΊΠΎΠ»ΠΈΠΊΠΎ ΠΠΠ£-Π° Π½ΠΈΡΠ΅ ΠΌΠΎΠ³Π»Π° Π΄Π° ΡΠ΅ ΠΏΡΠΈΠΌΠ΅Π½ΠΈ.
ΠΠ±ΡΠΊΠ° ΡΠ΅ ΠΏΡΠ°ΡΠ΅Π½Π° Π±Π΅Π· ΡΠΏΠΎΡΡΠ΅Π±Π΅. ΡΠ΅Π½ΡΠΎΡΠ±ΠΎΠ°ΡΠ΄, ΠΎΠ³ΡΠ°Π½ΠΈΡΠ°Π²Π°ΡΡΡΠΈ ΡΠ΅ Π½Π° ΡΠ½ΠΈΠΌΠ°ΡΠ΅ Π΄Π½Π΅Π²Π½ΠΈΠΊΠ° ΠΈ ΡΡΠ²Π°ΡΠ΅ ΠΌΠΎΠ΄Π΅Π»Π° ΡΠ° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠ²Π½ΠΈΠΌ Π½Π°Π·ΠΈΠ²ΠΈΠΌΠ° Π½Π°ΠΊΠΎΠ½ ΡΠ²Π°ΠΊΠ΅ Π΅ΠΏΠΎΡ Π΅:
ΠΠΎΠ²ΡΠ°ΡΠ½ΠΈ ΠΏΠΎΠ·ΠΈΠ²ΠΈ
# Π¨Π°Π±Π»ΠΎΠ½ ΠΈΠΌΠ΅Π½ΠΈ ΡΠ°ΠΉΠ»Π° Π»ΠΎΠ³Π°
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
Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΡΠΈ Π±ΡΠ·ΠΎ.Π°ΠΈ); Π£Π· ΠΎΠ΄ΡΠ΅ΡΠ΅Π½ΠΈ Π½Π°ΠΏΠΎΡ, ΠΌΠΎΠ³ΡΡΠ΅ ΡΠ΅ ΠΏΡΠ΅Π½Π΅ΡΠΈ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ΅ ΡΡΠ΅ΡΠ΅ ΡΡΡΠ°Π½Π΅ Π½Π° Π , Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ,ΠΎΠ²ΠΎ ; - ΠΊΠ°ΠΎ ΠΏΠΎΡΠ»Π΅Π΄ΠΈΡΠ° ΠΏΡΠ΅ΡΡ ΠΎΠ΄Π½Π΅ ΡΠ°ΡΠΊΠ΅, Π½ΠΈΡΠ΅ Π±ΠΈΠ»ΠΎ ΠΌΠΎΠ³ΡΡΠ΅ ΠΈΠ·Π°Π±ΡΠ°ΡΠΈ ΠΈΡΠΏΡΠ°Π²Π½Ρ Π±ΡΠ·ΠΈΠ½Ρ ΡΡΠ΅Π½ΠΈΠ½Π³Π° ΠΊΠ°Π΄Π° ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈ Π½Π΅ΠΊΠΎΠ»ΠΈΠΊΠΎ ΠΠΠ£-Π°;
- ΠΏΠΎΡΡΠΎΡΠΈ Π½Π΅Π΄ΠΎΡΡΠ°ΡΠ°ΠΊ ΠΌΠΎΠ΄Π΅ΡΠ½ΠΈΡ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° Π½Π΅ΡΡΠΎΠ½ΡΠΊΠΈΡ ΠΌΡΠ΅ΠΆΠ°, ΠΏΠΎΡΠ΅Π±Π½ΠΎ ΠΎΠ½ΠΈΡ ΠΏΡΠ΅ΡΡ ΠΎΠ΄Π½ΠΎ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ Π½Π° ΠΈΠΌΠ°Π³Π΅Π½Π΅Ρ-Ρ;
- ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠ° ΡΠ΅Π΄Π½ΠΎΠ³ ΡΠΈΠΊΠ»ΡΡΠ° ΠΈ Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΈΠ²Π½Π΅ ΡΡΠΎΠΏΠ΅ ΡΡΠ΅ΡΠ° (ΠΊΠΎΡΠΈΠ½ΡΡΠ½ΠΎ ΠΆΠ°ΡΠ΅ΡΠ΅ ΡΠ΅ Π±ΠΈΠ»ΠΎ Π½Π° Π½Π°Ρ Π·Π°Ρ
ΡΠ΅Π²
ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠΈΡΠ°Π½ , Π₯Π²Π°Π»Π°ΡΠΊΠ΅ΠΈΠ΄Π°Π½ ).
Π¨ΡΠ° ΡΠ΅ ΠΊΠΎΡΠΈΡΠ½ΠΎ Π½Π°ΡΡΠΈΠ»ΠΎ ΡΠ° ΠΎΠ²ΠΎΠ³ ΡΠ°ΠΊΠΌΠΈΡΠ΅ΡΠ°:
- ΠΠ° Ρ Π°ΡΠ΄Π²Π΅ΡΡ ΡΠ° ΡΠ΅Π»Π°ΡΠΈΠ²Π½ΠΎ ΠΌΠ°Π»ΠΎΠΌ ΠΏΠΎΡΡΠΎΡΡΠΎΠΌ, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠ°Π΄ΠΈΡΠ΅ ΡΠ° ΠΏΡΠΈΡΡΠΎΡΠ½ΠΈΠΌ (Π²ΠΈΡΠ΅ΡΡΡΡΠΊΠΎ Π²Π΅ΡΠΈΠΌ ΠΎΠ΄ Π ΠΠ-Π°) ΠΎΠ±ΠΈΠΌΠΈΠΌΠ° ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° Π±Π΅Π· ΠΌΡΠΊΠ΅. ΠΠ»Π°ΡΡΠΈΡΠ½Π° ΠΊΠ΅ΡΠ° ΠΏΠΎΠ΄Π°ΡΠΈ.ΡΠ°Π±Π΅Π»Π° ΡΡΠ΅Π΄ΠΈ ΠΌΠ΅ΠΌΠΎΡΠΈΡΡ Π·Π°Ρ Π²Π°ΡΡΡΡΡΠΈ ΠΌΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΈΡΠΈ ΡΠ°Π±Π΅Π»Π° Π½Π° ΠΌΠ΅ΡΡΡ, ΡΠΈΠΌΠ΅ ΡΠ΅ ΠΈΠ·Π±Π΅Π³Π°Π²Π° ΡΠΈΡ ΠΎΠ²ΠΎ ΠΊΠΎΠΏΠΈΡΠ°ΡΠ΅, Π° ΠΊΠ°Π΄Π° ΡΠ΅ ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΠΊΠΎΡΠΈΡΡΠ΅, ΡΠ΅Π³ΠΎΠ²Π΅ ΠΌΠΎΠ³ΡΡΠ½ΠΎΡΡΠΈ ΡΠΊΠΎΡΠΎ ΡΠ²Π΅ΠΊ ΠΏΠΎΠΊΠ°Π·ΡΡΡ Π½Π°ΡΠ²Π΅ΡΡ Π±ΡΠ·ΠΈΠ½Ρ ΠΌΠ΅ΡΡ ΡΠ²ΠΈΠΌ Π½Π°ΠΌΠ° ΠΏΠΎΠ·Π½Π°ΡΠΈΠΌ Π°Π»Π°ΡΠΈΠΌΠ° Π·Π° ΡΠΊΡΠΈΠΏΡΠ½Π΅ ΡΠ΅Π·ΠΈΠΊΠ΅. Π§ΡΠ²Π°ΡΠ΅ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° Ρ Π±Π°Π·ΠΈ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° Π²Π°ΠΌ ΠΎΠΌΠΎΠ³ΡΡΠ°Π²Π°, Ρ ΠΌΠ½ΠΎΠ³ΠΈΠΌ ΡΠ»ΡΡΠ°ΡΠ΅Π²ΠΈΠΌΠ°, Π΄Π° ΡΠΎΠΏΡΡΠ΅ Π½Π΅ ΡΠ°Π·ΠΌΠΈΡΡΠ°ΡΠ΅ ΠΎ ΠΏΠΎΡΡΠ΅Π±ΠΈ Π΄Π° ΡΠ΅ ΡΠ΅ΠΎ ΡΠΊΡΠΏ ΠΏΠΎΠ΄Π°ΡΠ°ΠΊΠ° ΡΠ³ΡΡΠ° Ρ Π ΠΠ.
- Π‘ΠΏΠΎΡΠ΅ ΡΡΠ½ΠΊΡΠΈΡΠ΅ Ρ Π ΠΌΠΎΠ³Ρ ΡΠ΅ Π·Π°ΠΌΠ΅Π½ΠΈΡΠΈ Π±ΡΠ·ΠΈΠΌ Ρ Π¦++ ΠΏΠΎΠΌΠΎΡΡ ΠΏΠ°ΠΊΠ΅ΡΠ° Π ΡΠΏΠΏ. ΠΠΊΠΎ ΠΏΠΎΡΠ΅Π΄ ΡΠΏΠΎΡΡΠ΅Π±Π΅ Π ΡΠΏΠΏΠ’Ρ ΡΠ΅Π°Π΄ ΠΈΠ»ΠΈ Π ΡΠΏΠΏΠΠ°ΡΠ°Π»Π»Π΅Π», Π΄ΠΎΠ±ΠΈΡΠ°ΠΌΠΎ Π²ΠΈΡΠ΅ΠΏΠ»Π°ΡΡΠΎΡΠΌΡΠΊΠ΅ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ΅ ΡΠ° Π²ΠΈΡΠ΅ Π½ΠΈΡΠΈ, ΡΠ°ΠΊΠΎ Π΄Π° Π½Π΅ΠΌΠ° ΠΏΠΎΡΡΠ΅Π±Π΅ Π·Π° ΠΏΠ°ΡΠ°Π»Π΅Π»ΠΈΠ·Π°ΡΠΈΡΠΎΠΌ ΠΊΠΎΠ΄Π° Π½Π° Π½ΠΈΠ²ΠΎΡ Π .
- ΠΠ°ΠΊΠ΅Ρ Π ΡΠΏΠΏ ΠΌΠΎΠΆΠ΅ ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈΡΠΈ Π±Π΅Π· ΠΎΠ·Π±ΠΈΡΠ½ΠΎΠ³ ΠΏΠΎΠ·Π½Π°Π²Π°ΡΠ° Π¦++-Π°, Π½Π°Π²Π΅Π΄Π΅Π½ ΡΠ΅ ΠΏΠΎΡΡΠ΅Π±Π°Π½ ΠΌΠΈΠ½ΠΈΠΌΡΠΌ
ΠΎΠ²Π΄Π΅ . ΠΠ°ΡΠΎΡΠ΅ΠΊΠ΅ Π·Π°Π³Π»Π°Π²ΡΠ° Π·Π° Π±ΡΠΎΡΠ½Π΅ ΡΠΎΠΎΠ» Π¦-Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅ ΠΊΠ°ΠΎ ΡΡΠΎ ΡΡ ΠΊΡΠ΅Π½ΡΠΎΡ Π΄ΠΎΡΡΡΠΏΠ½ΠΎ Π½Π° Π¦Π ΠΠ-Ρ, ΠΎΠ΄Π½ΠΎΡΠ½ΠΎ ΡΠΎΡΠΌΠΈΡΠ° ΡΠ΅ ΠΈΠ½ΡΡΠ°ΡΡΡΡΠΊΡΡΡΠ° Π·Π° ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡ ΠΏΡΠΎΡΠ΅ΠΊΠ°ΡΠ° ΠΊΠΎΡΠΈ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΡ Π³ΠΎΡΠΎΠ² Π¦++ ΠΊΠΎΠ΄ Π²ΠΈΡΠΎΠΊΠΈΡ ΠΏΠ΅ΡΡΠΎΡΠΌΠ°Π½ΡΠΈ Ρ Π . ΠΠΎΠ΄Π°ΡΠ½Π° ΠΏΠΎΠ³ΠΎΠ΄Π½ΠΎΡΡ ΡΠ΅ ΠΈΡΡΠΈΡΠ°ΡΠ΅ ΡΠΈΠ½ΡΠ°ΠΊΡΠ΅ ΠΈ ΡΡΠ°ΡΠΈΡΠΊΠΈ Π¦++ Π°Π½Π°Π»ΠΈΠ·Π°ΡΠΎΡ ΠΊΠΎΠ΄Π° Ρ Π Π‘ΡΡΠ΄ΠΈΡ. - Π΄ΠΎΡΠΎΠΏΡ ΠΎΠΌΠΎΠ³ΡΡΠ°Π²Π° Π²Π°ΠΌ Π΄Π° ΠΏΠΎΠΊΡΠ΅Π½Π΅ΡΠ΅ ΡΠ°ΠΌΠΎΡΡΠ°Π»Π½Π΅ ΡΠΊΡΠΈΠΏΡΠ΅ ΡΠ° ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈΠΌΠ°. ΠΠ²ΠΎ ΡΠ΅ Π·Π³ΠΎΠ΄Π½ΠΎ Π·Π° ΡΠΏΠΎΡΡΠ΅Π±Ρ Π½Π° ΡΠ΄Π°ΡΠ΅Π½ΠΎΠΌ ΡΠ΅ΡΠ²Π΅ΡΡ, ΡΠΊΡ. ΠΏΠΎΠ΄ Π΄ΠΎΡΠΊΠ΅Ρ. Π£ Π Π‘ΡΡΠ΄ΠΈΡ ΡΠ΅ Π½Π΅Π·Π³ΠΎΠ΄Π½ΠΎ ΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠΈ ΠΌΠ½ΠΎΠ³ΠΎ ΡΠ°ΡΠΈ Π΅ΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½Π°ΡΠ° ΡΠ° ΠΎΠ±ΡΡΠ°Π²Π°ΡΠ΅ΠΌ Π½Π΅ΡΡΠΎΠ½ΡΠΊΠΈΡ ΠΌΡΠ΅ΠΆΠ°, Π° ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ°ΡΠ΅ ΠΠΠ-Π° Π½Π° ΡΠ°ΠΌΠΎΠΌ ΡΠ΅ΡΠ²Π΅ΡΡ Π½ΠΈΡΠ΅ ΡΠ²Π΅ΠΊ ΠΎΠΏΡΠ°Π²Π΄Π°Π½ΠΎ.
- ΠΠΎΡΠΊΠ΅Ρ ΠΎΠ±Π΅Π·Π±Π΅ΡΡΡΠ΅ ΠΏΡΠ΅Π½ΠΎΡΠΈΠ²ΠΎΡΡ ΠΊΠΎΠ΄Π° ΠΈ ΠΏΠΎΠ½ΠΎΠ²ΡΠΈΠ²ΠΎΡΡ ΡΠ΅Π·ΡΠ»ΡΠ°ΡΠ° ΠΈΠ·ΠΌΠ΅ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ΅ΡΠ° ΡΠ° ΡΠ°Π·Π»ΠΈΡΠΈΡΠΈΠΌ Π²Π΅ΡΠ·ΠΈΡΠ°ΠΌΠ° ΠΠ‘-Π° ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°, ΠΊΠ°ΠΎ ΠΈ Π»Π°ΠΊΠΎΡΡ ΠΈΠ·Π²ΡΡΠ°Π²Π°ΡΠ° Π½Π° ΡΠ΅ΡΠ²Π΅ΡΠΈΠΌΠ°. ΠΠΎΠΆΠ΅ΡΠ΅ ΠΏΠΎΠΊΡΠ΅Π½ΡΡΠΈ ΡΠ΅ΠΎ ΡΠ΅Π²ΠΎΠ²ΠΎΠ΄ ΠΎΠ±ΡΠΊΠ΅ ΡΠ° ΡΠ°ΠΌΠΎ ΡΠ΅Π΄Π½ΠΎΠΌ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΌ.
- ΠΠΎΠΎΠ³Π»Π΅ Π¦Π»ΠΎΡΠ΄ ΡΠ΅ ΡΠ΅ΡΡΠΈΠ½ Π½Π°ΡΠΈΠ½ Π·Π° Π΅ΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΠΈΡΠ°ΡΠ΅ Π½Π° ΡΠΊΡΠΏΠΎΠΌ Ρ Π°ΡΠ΄Π²Π΅ΡΡ, Π°Π»ΠΈ ΠΌΠΎΡΠ°ΡΠ΅ ΠΏΠ°ΠΆΡΠΈΠ²ΠΎ Π΄Π° ΠΈΠ·Π°Π±Π΅ΡΠ΅ΡΠ΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠ΅.
- ΠΠ΅ΡΠ΅ΡΠ΅ Π±ΡΠ·ΠΈΠ½Π΅ ΠΏΠΎΡΠ΅Π΄ΠΈΠ½Π°ΡΠ½ΠΈΡ ΡΡΠ°Π³ΠΌΠ΅Π½Π°ΡΠ° ΠΊΠΎΠ΄Π° ΡΠ΅ Π²Π΅ΠΎΠΌΠ° ΠΊΠΎΡΠΈΡΠ½ΠΎ, ΠΏΠΎΡΠ΅Π±Π½ΠΎ ΠΊΠ°Π΄Π° ΡΠ΅ ΠΊΠΎΠΌΠ±ΠΈΠ½ΡΡΡ Π ΠΈ Π¦++, ΠΈ ΡΠ° ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ ΠΊΠ»ΡΠΏΠ° - ΡΠ°ΠΊΠΎΡΠ΅ Π²ΡΠ»ΠΎ Π»Π°ΠΊΠΎ.
Π‘Π²Π΅ Ρ ΡΠ²Π΅ΠΌΡ, ΠΎΠ²ΠΎ ΠΈΡΠΊΡΡΡΠ²ΠΎ ΡΠ΅ Π±ΠΈΠ»ΠΎ Π²Π΅ΠΎΠΌΠ° ΠΊΠΎΡΠΈΡΠ½ΠΎ ΠΈ Π½Π°ΡΡΠ°Π²ΡΠ°ΠΌΠΎ Π΄Π° ΡΠ°Π΄ΠΈΠΌΠΎ Π½Π° ΡΠ΅ΡΠ°Π²Π°ΡΡ Π½Π΅ΠΊΠΈΡ ΠΎΠ΄ ΠΏΠΎΡΡΠ°Π²ΡΠ΅Π½ΠΈΡ ΠΏΠΈΡΠ°ΡΠ°.
ΠΠ·Π²ΠΎΡ: Π²Π²Π².Ρ Π°Π±Ρ.ΡΠΎΠΌ