рд╣реЗ рд╣рдмрд░!
рдкрд┐рдЫрд▓реА рдмрд╛рд░, рдХрд╛рдЧрд▓ рдиреЗ рд╣рд╛рде рд╕реЗ рдЦреАрдВрдЪреА рдЧрдИ рддрд╕реНрд╡реАрд░реЛрдВ рдХреЛ рд╡рд░реНрдЧреАрдХреГрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд╡рд┐рдХ рдбреНрд░реЙ рдбреВрдбрд▓ рд░рд┐рдХреЙрдЧреНрдирд┐рд╢рди рдирд╛рдордХ рдПрдХ рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рдХреА рдореЗрдЬрдмрд╛рдиреА рдХреА рдереА, рдЬрд┐рд╕рдореЗрдВ рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрд░-рд╡реИрдЬреНрдЮрд╛рдирд┐рдХреЛрдВ рдХреА рдПрдХ рдЯреАрдо рдиреЗ рднрд╛рдЧ рд▓рд┐рдпрд╛ рдерд╛:
рдЗрд╕ рдмрд╛рд░ рдкрджрдХ рдЦреЗрддреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рд╣реБрдЖ, рд▓реЗрдХрд┐рди рдмрд╣реБрдд рдореВрд▓реНрдпрд╡рд╛рди рдЕрдиреБрднрд╡ рдкреНрд░рд╛рдкреНрдд рд╣реБрдЖ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рд╕рдореБрджрд╛рдп рдХреЛ рдХрд╛рдЧрд▓реЗ рдФрд░ рд░реЛрдЬрдорд░реНрд░рд╛ рдХреЗ рдХрд╛рдо рдореЗрдВ рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рдФрд░ рдЙрдкрдпреЛрдЧреА рдЪреАрдЬреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдЪрд░реНрдЪрд╛ рдХрд┐рдП рдЧрдП рд╡рд┐рд╖рдпреЛрдВ рдореЗрдВ: рдмрд┐рдирд╛ рдХрдард┐рди рдЬреАрд╡рди OpenCV, JSON рдкрд╛рд░реНрд╕рд┐рдВрдЧ (рдпреЗ рдЙрджрд╛рд╣рд░рдг R рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдпрд╛ рдкреИрдХреЗрдЬ рдореЗрдВ C++ рдХреЛрдб рдХреЗ рдПрдХреАрдХрд░рдг рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ) рдЖрд░рд╕реАрдкреАрдкреА), рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдорд╛рдирдХреАрдХрд░рдг рдФрд░ рдЕрдВрддрд┐рдо рд╕рдорд╛рдзрд╛рди рдХрд╛ рдбреЙрдХрд░реАрдХрд░рдгред рд╕рдВрджреЗрд╢ рдХреЗ рд╕рднреА рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд░реВрдк рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ
рд╕рд╛рдордЧреНрд░реА:
CSV рд╕реЗ MonetDB рдореЗрдВ рдбреЗрдЯрд╛ рдХреЛ рдХреБрд╢рд▓рддрд╛рдкреВрд░реНрд╡рдХ рд▓реЛрдб рдХрд░реЗрдВ рдмреИрдЪ рддреИрдпрд╛рд░ рдХрд░рдирд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдмреИрдЪреЛрдВ рдХреЛ рдЕрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдЯрд░реЗрдЯрд░ рдПрдХ рдореЙрдбрд▓ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХрд╛ рдЪрдпрди рдХрд░рдирд╛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдорд╛рдирдХреАрдХрд░рдг рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдбреЙрдХрд░реАрдХрд░рдг Google рдХреНрд▓рд╛рдЙрдб рдкрд░ рдПрдХрд╛рдзрд┐рдХ GPU рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдирд┐рд╖реНрдХрд░реНрд╖ рдХреА
1. CSV рд╕реЗ MonetDB рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЛ рдХреБрд╢рд▓рддрд╛рдкреВрд░реНрд╡рдХ рд▓реЛрдб рдХрд░реЗрдВ
рдЗрд╕ рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рдореЗрдВ рдбреЗрдЯрд╛ рддреИрдпрд╛рд░ рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдмрд┐рдВрджреБ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЗ рд╕рд╛рде JSON рдпреБрдХреНрдд 340 CSV рдлрд╝рд╛рдЗрд▓реЛрдВ (рдкреНрд░рддреНрдпреЗрдХ рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рд╛рдЗрд▓) рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрди рдмрд┐рдВрджреБрдУрдВ рдХреЛ рд░реЗрдЦрд╛рдУрдВ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдкрд░ рд╣рдореЗрдВ 256x256 рдкрд┐рдХреНрд╕реЗрд▓ рдХреА рдЕрдВрддрд┐рдо рдЫрд╡рд┐ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддреА рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдкреНрд░рддреНрдпреЗрдХ рд░рд┐рдХреЙрд░реНрдб рдХреЗ рд▓рд┐рдП рдПрдХ рд▓реЗрдмрд▓ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛рд╕реЗрдЯ рдПрдХрддреНрд░ рдХрд░рдиреЗ рдХреЗ рд╕рдордп рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдП рдЧрдП рдХреНрд▓рд╛рд╕рд┐рдлрд╛рдпрд░ рджреНрд╡рд╛рд░рд╛ рдЪрд┐рддреНрд░ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкрд╣рдЪрд╛рдирд╛ рдЧрдпрд╛ рдерд╛ рдпрд╛ рдирд╣реАрдВ, рдЪрд┐рддреНрд░ рдХреЗ рд▓реЗрдЦрдХ рдХреЗ рдирд┐рд╡рд╛рд╕ рдХреЗ рджреЗрд╢ рдХрд╛ рджреЛ-рдЕрдХреНрд╖рд░ рдХреЛрдб, рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛, рдПрдХ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдФрд░ рдПрдХ рд╡рд░реНрдЧ рдирд╛рдо рдЬреЛ рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реЛред рдореВрд▓ рдбреЗрдЯрд╛ рдХрд╛ рдПрдХ рд╕рд░рд▓реАрдХреГрдд рд╕рдВрд╕реНрдХрд░рдг рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ 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"
)
)
}
рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рддреЗрдЬрд╝ рддрд░реАрдХрд╛ SQL - рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реАрдзреЗ CSV рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдХреЙрдкреА рдХрд░рдирд╛ рдерд╛ COPY OFFSET 2 INTO tablename FROM path USING DELIMITERS ',','n','"' NULL AS '' BEST EFFORT
рдЬрд╣рд╛рдВ tablename
- рдЯреЗрдмрд▓ рдХрд╛ рдирд╛рдо рдФрд░ path
- рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдкрде. рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп, рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди unzip
рдЖрд░ рд╕рдВрдЧреНрд░рд╣ рд╕реЗ рдХрдИ рдлрд╛рдЗрд▓реЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдордиреЗ рд╕рд┐рд╕реНрдЯрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ unzip
(рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ getOption("unzip")
).
рдбреЗрдЯрд╛рдмреЗрд╕ рдкрд░ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдХрд╛рд░реНрдп
#' @title ╨Ш╨╖╨▓╨╗╨╡╤З╨╡╨╜╨╕╨╡ ╨╕ ╨╖╨░╨│╤А╤Г╨╖╨║╨░ ╤Д╨░╨╣╨╗╨╛╨▓
#'
#' @description
#' ╨Ш╨╖╨▓╨╗╨╡╤З╨╡╨╜╨╕╨╡ CSV-╤Д╨░╨╣╨╗╨╛╨▓ ╨╕╨╖ ZIP-╨░╤А╤Е╨╕╨▓╨░ ╨╕ ╨╖╨░╨│╤А╤Г╨╖╨║╨░ ╨╕╤Е ╨▓ ╨▒╨░╨╖╤Г ╨┤╨░╨╜╨╜╤Л╤Е
#'
#' @param con ╨Ю╨▒╤К╨╡╨║╤В ╨┐╨╛╨┤╨║╨╗╤О╤З╨╡╨╜╨╕╤П ╨║ ╨▒╨░╨╖╨╡ ╨┤╨░╨╜╨╜╤Л╤Е (╨║╨╗╨░╤Б╤Б `MonetDBEmbeddedConnection`).
#' @param tablename ╨Э╨░╨╖╨▓╨░╨╜╨╕╨╡ ╤В╨░╨▒╨╗╨╕╤Ж╤Л ╨▓ ╨▒╨░╨╖╨╡ ╨┤╨░╨╜╨╜╤Л╤Е.
#' @oaram zipfile ╨Я╤Г╤В╤М ╨║ ZIP-╨░╤А╤Е╨╕╨▓╤Г.
#' @oaram filename ╨Ш╨╝╤П ╤Д╨░╨╣╨╗╨░ ╨▓╨╜╤Г╤А╨╕ ZIP-╨░╤А╤Е╨╕╨▓╨░.
#' @param preprocess ╨д╤Г╨╜╨║╤Ж╨╕╤П ╨┐╤А╨╡╨┤╨╛╨▒╤А╨░╨▒╨╛╤В╨║╨╕, ╨║╨╛╤В╨╛╤А╨░╤П ╨▒╤Г╨┤╨╡╤В ╨┐╤А╨╕╨╝╨╡╨╜╨╡╨╜╨░ ╨╕╨╖╨▓╨╗╨╡╤З╤С╨╜╨╜╨╛╨╝╤Г ╤Д╨░╨╣╨╗╤Г.
#' ╨Ф╨╛╨╗╨╢╨╜╨░ ╨┐╤А╨╕╨╜╨╕╨╝╨░╤В╤М ╨╛╨┤╨╕╨╜ ╨░╤А╨│╤Г╨╝╨╡╨╜╤В `data` (╨╛╨▒╤К╨╡╨║╤В `data.table`).
#'
#' @return `TRUE`.
#'
upload_file <- function(con, tablename, zipfile, filename, preprocess = NULL) {
# ╨Я╤А╨╛╨▓╨╡╤А╨║╨░ ╨░╤А╨│╤Г╨╝╨╡╨╜╤В╨╛╨▓
checkmate::assert_class(con, "MonetDBEmbeddedConnection")
checkmate::assert_string(tablename)
checkmate::assert_string(filename)
checkmate::assert_true(DBI::dbExistsTable(con, tablename))
checkmate::assert_file_exists(zipfile, access = "r", extension = "zip")
checkmate::assert_function(preprocess, args = c("data"), null.ok = TRUE)
# ╨Ш╨╖╨▓╨╗╨╡╤З╨╡╨╜╨╕╨╡ ╤Д╨░╨╣╨╗╨░
path <- file.path(tempdir(), filename)
unzip(zipfile, files = filename, exdir = tempdir(),
junkpaths = TRUE, unzip = getOption("unzip"))
on.exit(unlink(file.path(path)))
# ╨Я╤А╨╕╨╝╨╡╨╜╤П╨╡╨╝ ╤Д╤Г╨╜╨║╤Ж╨╕╤П ╨┐╤А╨╡╨┤╨╛╨▒╤А╨░╨▒╨╛╤В╨║╨╕
if (!is.null(preprocess)) {
.data <- data.table::fread(file = path)
.data <- preprocess(data = .data)
data.table::fwrite(x = .data, file = path, append = FALSE)
rm(.data)
}
# ╨Ч╨░╨┐╤А╨╛╤Б ╨║ ╨С╨Ф ╨╜╨░ ╨╕╨╝╨┐╨╛╤А╤В CSV
sql <- sprintf(
"COPY OFFSET 2 INTO %s FROM '%s' USING DELIMITERS ',','n','"' NULL AS '' BEST EFFORT",
tablename, path
)
# ╨Т╤Л╨┐╨╛╨╗╨╜╨╡╨╜╨╕╨╡ ╨╖╨░╨┐╤А╨╛╤Б╨░ ╨║ ╨С╨Ф
DBI::dbExecute(con, sql)
# ╨Ф╨╛╨▒╨░╨▓╨╗╨╡╨╜╨╕╨╡ ╨╖╨░╨┐╨╕╤Б╨╕ ╨╛╨▒ ╤Г╤Б╨┐╨╡╤И╨╜╨╛╨╣ ╨╖╨░╨│╤А╤Г╨╖╨║╨╡ ╨▓ ╤Б╨╗╤Г╨╢╨╡╨▒╨╜╤Г╤О ╤В╨░╨▒╨╗╨╕╤Ж╤Г
DBI::dbExecute(con, sprintf("INSERT INTO upload_log(file_name, uploaded) VALUES('%s', true)",
filename))
return(invisible(TRUE))
}
рдпрджрд┐ рдЖрдкрдХреЛ рддрд╛рд▓рд┐рдХрд╛ рдХреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд▓рд┐рдЦрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЙрд╕реЗ рд░реВрдкрд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдпрд╣ рддрд░реНрдХ рдореЗрдВ рдкрд╛рд░рд┐рдд рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ preprocess
рдлрд╝рдВрдХреНрд╢рди рдЬреЛ рдбреЗрдЯрд╛ рдХреЛ рд░реВрдкрд╛рдВрддрд░рд┐рдд рдХрд░реЗрдЧрд╛.
рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЛ рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб:
рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдбреЗрдЯрд╛ рд▓рд┐рдЦрдирд╛
# ╨б╨┐╨╕╤Б╨╛╨║ ╤Д╨░╨╣╨╗╨╛╨▓ ╨┤╨╗╤П ╨╖╨░╨┐╨╕╤Б╨╕
files <- unzip(zipfile, list = TRUE)$Name
# ╨б╨┐╨╕╤Б╨╛╨║ ╨╕╤Б╨║╨╗╤О╤З╨╡╨╜╨╕╨╣, ╨╡╤Б╨╗╨╕ ╤З╨░╤Б╤В╤М ╤Д╨░╨╣╨╗╨╛╨▓ ╤Г╨╢╨╡ ╨▒╤Л╨╗╨░ ╨╖╨░╨│╤А╤Г╨╢╨╡╨╜╨░
to_skip <- DBI::dbGetQuery(con, "SELECT file_name FROM upload_log")[[1L]]
files <- setdiff(files, to_skip)
if (length(files) > 0L) {
# ╨Ч╨░╨┐╤Г╤Б╨║╨░╨╡╨╝ ╤В╨░╨╣╨╝╨╡╤А
tictoc::tic()
# ╨Я╤А╨╛╨│╤А╨╡╤Б╤Б ╨▒╨░╤А
pb <- txtProgressBar(min = 0L, max = length(files), style = 3)
for (i in seq_along(files)) {
upload_file(con = con, tablename = "doodles",
zipfile = zipfile, filename = files[i])
setTxtProgressBar(pb, i)
}
close(pb)
# ╨Ю╤Б╤В╨░╨╜╨░╨▓╨╗╨╕╨▓╨░╨╡╨╝ ╤В╨░╨╣╨╝╨╡╤А
tictoc::toc()
}
# 526.141 sec elapsed - ╨║╨╛╨┐╨╕╤А╨╛╨▓╨░╨╜╨╕╨╡ SSD->SSD
# 558.879 sec elapsed - ╨║╨╛╨┐╨╕╤А╨╛╨▓╨░╨╜╨╕╨╡ USB->SSD
рдЙрдкрдпреЛрдЧ рдХреА рдЧрдИ рдбреНрд░рд╛рдЗрд╡ рдХреА рдЧрддрд┐ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдбреЗрдЯрд╛ рд▓реЛрдбрд┐рдВрдЧ рд╕рдордп рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдПрдХ рдПрд╕рдПрд╕рдбреА рдХреЗ рднреАрддрд░ рдпрд╛ рдлреНрд▓реИрд╢ рдбреНрд░рд╛рдЗрд╡ (рд╕реНрд░реЛрдд рдлрд╝рд╛рдЗрд▓) рд╕реЗ рдПрд╕рдПрд╕рдбреА (рдбреАрдмреА) рддрдХ рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдореЗрдВ 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. рдмреИрдЪ рддреИрдпрд╛рд░ рдХрд░рдирд╛
рд╕рдВрдкреВрд░реНрдг рдмреИрдЪ рддреИрдпрд╛рд░реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЪрд░рдг рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:
- рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЗ рд╕рд╛рде рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╡реИрдХреНрдЯрд░ рд╡рд╛рд▓реЗ рдХрдИ JSON рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдирд╛ред
- рдЖрд╡рд╢реНрдпрдХ рдЖрдХрд╛рд░ рдХреА рдЫрд╡рд┐ рдкрд░ рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд░рдВрдЧреАрди рд░реЗрдЦрд╛рдПрдБ рдЦреАрдВрдЪрдирд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 256├Ч256 рдпрд╛ 128├Ч128)ред
- рдкрд░рд┐рдгрд╛рдореА рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рдЯреЗрдВрд╕рд░ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛ред
рдкрд╛рдпрдерди рдХрд░реНрдиреЗрд▓ рдХреЗ рдмреАрдЪ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛ рдХреЗ рднрд╛рдЧ рдХреЗ рд░реВрдк рдореЗрдВ, рд╕рдорд╕реНрдпрд╛ рдХреЛ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ OpenCV. рдЖрд░ рдореЗрдВ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдФрд░ рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рдПрдирд╛рд▓реЙрдЧреНрд╕ рдореЗрдВ рд╕реЗ рдПрдХ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:
R рдореЗрдВ JSON рд╕реЗ Tensor рд░реВрдкрд╛рдВрддрд░рдг рд▓рд╛рдЧреВ рдХрд░рдирд╛
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
рдпрд╣ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣рдореЗрдВ рдЗрд╖реНрдЯрддрдо рдирд╣реАрдВ рд▓рдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдмрдбрд╝реЗ рдмреИрдЪреЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдореЗрдВ рдмрд╣реБрдд рд▓рдВрдмрд╛ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ, рдФрд░ рд╣рдордиреЗ рдПрдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдиреЗ рд╕рд╣рдпреЛрдЧрд┐рдпреЛрдВ рдХреЗ рдЕрдиреБрднрд╡ рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред OpenCV. рдЙрд╕ рд╕рдордп рдЖрд░ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рддреИрдпрд╛рд░ рдкреИрдХреЗрдЬ рдирд╣реАрдВ рдерд╛ (рдЕрдм рдХреЛрдИ рдирд╣реАрдВ рд╣реИ), рдЗрд╕рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдиреНрдпреВрдирддрдо рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реА ++ рдореЗрдВ рдЖрд░ рдХреЛрдб рдореЗрдВ рдПрдХреАрдХрд░рдг рдХреЗ рд╕рд╛рде рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ рдЖрд░рд╕реАрдкреАрдкреА.
рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреИрдХреЗрдЬ рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛:
-
OpenCV рдЫрд╡рд┐рдпреЛрдВ рдФрд░ рд░реЗрдЦрд╛рдПрдБ рдЦреАрдВрдЪрдиреЗ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдкреВрд░реНрд╡-рд╕реНрдерд╛рдкрд┐рдд рд╕рд┐рд╕реНрдЯрдо рд▓рд╛рдЗрдмреНрд░реЗрд░реАрдЬрд╝ рдФрд░ рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдбрд╛рдпрдирд╛рдорд┐рдХ рд▓рд┐рдВрдХрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ред
-
xtensor рдмрд╣реБрдЖрдпрд╛рдореА рд╕рд░рдгрд┐рдпреЛрдВ рдФрд░ рдЯреЗрдВрд╕рд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рд╣рдордиреЗ рдЗрд╕реА рдирд╛рдо рдХреЗ рдЖрд░ рдкреИрдХреЗрдЬ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЖрдкрдХреЛ рдкрдВрдХреНрддрд┐ рдкреНрд░рдореБрдЦ рдФрд░ рд╕реНрддрдВрдн рдкреНрд░рдореБрдЦ рдХреНрд░рдо рджреЛрдиреЛрдВ рдореЗрдВ рдмрд╣реБрдЖрдпрд╛рдореА рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред
-
ndjson JSON рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдЗрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ xtensor рдпрджрд┐ рдпрд╣ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдореМрдЬреВрдж рд╣реИ рддреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗред
-
рдЖрд░рд╕реАрдкреАрдкреАрдереНрд░реЗрдб JSON рд╕реЗ рдПрдХ рд╡реЗрдХреНрдЯрд░ рдХреЗ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдЗрд╕ рдкреИрдХреЗрдЬ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ред рдЕрдзрд┐рдХ рд▓реЛрдХрдкреНрд░рд┐рдп рд╕реЗ Rcppрд╕рдорд╛рдирд╛рдВрддрд░ рдкреИрдХреЗрдЬ рдореЗрдВ, рдЕрдиреНрдп рдмрд╛рддреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд▓реВрдк рдЗрдВрдЯрд░рдкреНрдЯ рддрдВрддреНрд░ рд╣реИред
рдпрд╣ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ xtensor рдпрд╣ рдПрдХ рд╡рд░рджрд╛рди рд╕рд╛рдмрд┐рдд рд╣реБрдЖ: рдЗрд╕ рддрдереНрдп рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐ рдЗрд╕рдореЗрдВ рд╡реНрдпрд╛рдкрдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдФрд░ рдЙрдЪреНрдЪ рдкреНрд░рджрд░реНрд╢рди рд╣реИ, рдЗрд╕рдХреЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХрд╛рдлреА рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдирд┐рдХрд▓реЗ рдФрд░ рдЙрдиреНрд╣реЛрдВрдиреЗ рддреБрд░рдВрдд рдФрд░ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╕рд╡рд╛рд▓реЛрдВ рдХреЗ рдЬрд╡рд╛рдм рджрд┐рдПред рдЙрдирдХреА рдорджрдж рд╕реЗ, рдУрдкрдирд╕реАрд╡реА рдореИрдЯреНрд░рд┐рд╕реЗрд╕ рдХреЗ xtensor рдЯреЗрдВрд╕рд░ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдерд╛, рд╕рд╛рде рд╣реА 3-рдЖрдпрд╛рдореА рдЫрд╡рд┐ рдЯреЗрдВрд╕рд░ рдХреЛ рд╕рд╣реА рдЖрдпрд╛рдо (рдмреИрдЪ рд╣реА) рдХреЗ 4-рдЖрдпрд╛рдореА рдЯреЗрдВрд╕рд░ рдореЗрдВ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рднреА рд╕рдВрднрд╡ рдерд╛ред
Rcpp, xtensor рдФрд░ RcppThread рд╕реАрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╛рдордЧреНрд░реА
рд╕рд┐рд╕реНрдЯрдо рдлрд╝рд╛рдЗрд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдФрд░ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рд╕реНрдерд╛рдкрд┐рдд рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд╕рд╛рде рдЧрддрд┐рд╢реАрд▓ рд▓рд┐рдВрдХрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП, рд╣рдордиреЗ рдкреИрдХреЗрдЬ рдореЗрдВ рд▓рд╛рдЧреВ рдкреНрд▓рдЧрдЗрди рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЖрд░рд╕реАрдкреАрдкреА. рдкрдереЛрдВ рдФрд░ рдЭрдВрдбреЛрдВ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдордиреЗ рдПрдХ рд▓реЛрдХрдкреНрд░рд┐рдп рд▓рд┐рдирдХреНрд╕ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдкреАрдХреЗрдЬреА-рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди.
OpenCV рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Rcpp рдкреНрд▓рдЧрдЗрди рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
Rcpp::registerPlugin("opencv", function() {
# ╨Т╨╛╨╖╨╝╨╛╨╢╨╜╤Л╨╡ ╨╜╨░╨╖╨▓╨░╨╜╨╕╤П ╨┐╨░╨║╨╡╤В╨░
pkg_config_name <- c("opencv", "opencv4")
# ╨С╨╕╨╜╨░╤А╨╜╤Л╨╣ ╤Д╨░╨╣╨╗ ╤Г╤В╨╕╨╗╨╕╤В╤Л pkg-config
pkg_config_bin <- Sys.which("pkg-config")
# ╨Я╤А╨╛╨▓╤А╨╡╨║╨░ ╨╜╨░╨╗╨╕╤З╨╕╤П ╤Г╤В╨╕╨╗╨╕╤В╤Л ╨▓ ╤Б╨╕╤Б╤В╨╡╨╝╨╡
checkmate::assert_file_exists(pkg_config_bin, access = "x")
# ╨Я╤А╨╛╨▓╨╡╤А╨║╨░ ╨╜╨░╨╗╨╕╤З╨╕╤П ╤Д╨░╨╣╨╗╨░ ╨╜╨░╤Б╤В╤А╨╛╨╡╨║ OpenCV ╨┤╨╗╤П pkg-config
check <- sapply(pkg_config_name,
function(pkg) system(paste(pkg_config_bin, pkg)))
if (all(check != 0)) {
stop("OpenCV config for the pkg-config not found", call. = FALSE)
}
pkg_config_name <- pkg_config_name[check == 0]
list(env = list(
PKG_CXXFLAGS = system(paste(pkg_config_bin, "--cflags", pkg_config_name),
intern = TRUE),
PKG_LIBS = system(paste(pkg_config_bin, "--libs", pkg_config_name),
intern = TRUE)
))
})
рдкреНрд▓рдЧрдЗрди рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╕рдВрдХрд▓рди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рджреМрд░рд╛рди рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд╛рди рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗ:
Rcpp:::.plugins$opencv()$env
# $PKG_CXXFLAGS
# [1] "-I/usr/include/opencv"
#
# $PKG_LIBS
# [1] "-lopencv_shape -lopencv_stitching -lopencv_superres -lopencv_videostab -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_datasets -lopencv_dpm -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hdf -lopencv_line_descriptor -lopencv_optflow -lopencv_video -lopencv_plot -lopencv_reg -lopencv_saliency -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_rgbd -lopencv_viz -lopencv_surface_matching -lopencv_text -lopencv_ximgproc -lopencv_calib3d -lopencv_features2d -lopencv_flann -lopencv_xobjdetect -lopencv_objdetect -lopencv_ml -lopencv_xphoto -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_photo -lopencv_imgproc -lopencv_core"
JSON рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдФрд░ рдореЙрдбрд▓ рдореЗрдВ рдЯреНрд░рд╛рдВрд╕рдорд┐рд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдмреИрдЪ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛрдб рд╕реНрдкреЙрдЗрд▓рд░ рдХреЗ рдиреАрдЪреЗ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдерд╛рдиреАрдп рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдЬреЛрдбрд╝реЗрдВ (рдПрдирдбреАрдЬреЗрд╕рди рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ):
Sys.setenv("PKG_CXXFLAGS" = paste0("-I", normalizePath(file.path("src"))))
C++ рдореЗрдВ JSON рд╕реЗ рдЯреЗрдВрд╕рд░ рд░реВрдкрд╛рдВрддрд░рдг рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
// [[Rcpp::plugins(cpp14)]]
// [[Rcpp::plugins(opencv)]]
// [[Rcpp::depends(xtensor)]]
// [[Rcpp::depends(RcppThread)]]
#include <xtensor/xjson.hpp>
#include <xtensor/xadapt.hpp>
#include <xtensor/xview.hpp>
#include <xtensor-r/rtensor.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <Rcpp.h>
#include <RcppThread.h>
// ╨б╨╕╨╜╨╛╨╜╨╕╨╝╤Л ╨┤╨╗╤П ╤В╨╕╨┐╨╛╨▓
using RcppThread::parallelFor;
using json = nlohmann::json;
using points = xt::xtensor<double,2>; // ╨Ш╨╖╨▓╨╗╨╡╤З╤С╨╜╨╜╤Л╨╡ ╨╕╨╖ JSON ╨║╨╛╨╛╤А╨┤╨╕╨╜╨░╤В╤Л ╤В╨╛╤З╨╡╨║
using strokes = std::vector<points>; // ╨Ш╨╖╨▓╨╗╨╡╤З╤С╨╜╨╜╤Л╨╡ ╨╕╨╖ JSON ╨║╨╛╨╛╤А╨┤╨╕╨╜╨░╤В╤Л ╤В╨╛╤З╨╡╨║
using xtensor3d = xt::xtensor<double, 3>; // ╨в╨╡╨╜╨╖╨╛╤А ╨┤╨╗╤П ╤Е╤А╨░╨╜╨╡╨╜╨╕╤П ╨╝╨░╤В╤А╨╕╤Ж╤Л ╨╕╨╖╨╛╨╛╨▒╤А╨░╨╢╨╡╨╜╨╕╤П
using xtensor4d = xt::xtensor<double, 4>; // ╨в╨╡╨╜╨╖╨╛╤А ╨┤╨╗╤П ╤Е╤А╨░╨╜╨╡╨╜╨╕╤П ╨╝╨╜╨╛╨╢╨╡╤Б╤В╨▓╨░ ╨╕╨╖╨╛╨▒╤А╨░╨╢╨╡╨╜╨╕╨╣
using rtensor3d = xt::rtensor<double, 3>; // ╨Ю╨▒╤С╤А╤В╨║╨░ ╨┤╨╗╤П ╤Н╨║╤Б╨┐╨╛╤А╤В╨░ ╨▓ R
using rtensor4d = xt::rtensor<double, 4>; // ╨Ю╨▒╤С╤А╤В╨║╨░ ╨┤╨╗╤П ╤Н╨║╤Б╨┐╨╛╤А╤В╨░ ╨▓ R
// ╨б╤В╨░╤В╨╕╤З╨╡╤Б╨║╨╕╨╡ ╨║╨╛╨╜╤Б╤В╨░╨╜╤В╤Л
// ╨а╨░╨╖╨╝╨╡╤А ╨╕╨╖╨╛╨▒╤А╨░╨╢╨╡╨╜╨╕╤П ╨▓ ╨┐╨╕╨║╤Б╨╡╨╗╤П╤Е
const static int SIZE = 256;
// ╨в╨╕╨┐ ╨╗╨╕╨╜╨╕╨╕
// ╨б╨╝. https://en.wikipedia.org/wiki/Pixel_connectivity#2-dimensional
const static int LINE_TYPE = cv::LINE_4;
// ╨в╨╛╨╗╤Й╨╕╨╜╨░ ╨╗╨╕╨╜╨╕╨╕ ╨▓ ╨┐╨╕╨║╤Б╨╡╨╗╤П╤Е
const static int LINE_WIDTH = 3;
// ╨Р╨╗╨│╨╛╤А╨╕╤В╨╝ ╤А╨╡╤Б╨░╨╣╨╖╨░
// https://docs.opencv.org/3.1.0/da/d54/group__imgproc__transform.html#ga5bb5a1fea74ea38e1a5445ca803ff121
const static int RESIZE_TYPE = cv::INTER_LINEAR;
// ╨и╨░╨▒╨╗╨╛╨╜ ╨┤╨╗╤П ╨║╨╛╨╜╨▓╨╡╤А╤В╨╕╤А╨╛╨▓╨░╨╜╨╕╤П OpenCV-╨╝╨░╤В╤А╨╕╤Ж╤Л ╨▓ ╤В╨╡╨╜╨╖╨╛╤А
template <typename T, int NCH, typename XT=xt::xtensor<T,3,xt::layout_type::column_major>>
XT to_xt(const cv::Mat_<cv::Vec<T, NCH>>& src) {
// ╨а╨░╨╖╨╝╨╡╤А╨╜╨╛╤Б╤В╤М ╤Ж╨╡╨╗╨╡╨▓╨╛╨│╨╛ ╤В╨╡╨╜╨╖╨╛╤А╨░
std::vector<int> shape = {src.rows, src.cols, NCH};
// ╨Ю╨▒╤Й╨╡╨╡ ╨║╨╛╨╗╨╕╤З╨╡╤Б╤В╨▓╨╛ ╤Н╨╗╨╡╨╝╨╡╨╜╤В╨╛╨▓ ╨▓ ╨╝╨░╤Б╤Б╨╕╨▓╨╡
size_t size = src.total() * NCH;
// ╨Я╤А╨╡╨╛╨▒╤А╨░╨╖╨╛╨▓╨░╨╜╨╕╨╡ cv::Mat ╨▓ xt::xtensor
XT res = xt::adapt((T*) src.data, size, xt::no_ownership(), shape);
return res;
}
// ╨Я╤А╨╡╨╛╨▒╤А╨░╨╖╨╛╨▓╨░╨╜╨╕╨╡ JSON ╨▓ ╤Б╨┐╨╕╤Б╨╛╨║ ╨║╨╛╨╛╤А╨┤╨╕╨╜╨░╤В ╤В╨╛╤З╨╡╨║
strokes parse_json(const std::string& x) {
auto j = json::parse(x);
// ╨а╨╡╨╖╤Г╨╗╤М╤В╨░╤В ╨┐╨░╤А╤Б╨╕╨╜╨│╨░ ╨┤╨╛╨╗╨╢╨╡╨╜ ╨▒╤Л╤В╤М ╨╝╨░╤Б╤Б╨╕╨▓╨╛╨╝
if (!j.is_array()) {
throw std::runtime_error("'x' must be JSON array.");
}
strokes res;
res.reserve(j.size());
for (const auto& a: j) {
// ╨Ъ╨░╨╢╨┤╤Л╨╣ ╤Н╨╗╨╡╨╝╨╡╨╜╤В ╨╝╨░╤Б╤Б╨╕╨▓╨░ ╨┤╨╛╨╗╨╢╨╡╨╜ ╨▒╤Л╤В╤М 2-╨╝╨╡╤А╨╜╤Л╨╝ ╨╝╨░╤Б╤Б╨╕╨▓╨╛╨╝
if (!a.is_array() || a.size() != 2) {
throw std::runtime_error("'x' must include only 2d arrays.");
}
// ╨Ш╨╖╨▓╨╗╨╡╤З╨╡╨╜╨╕╨╡ ╨▓╨╡╨║╤В╨╛╤А╨░ ╤В╨╛╤З╨╡╨║
auto p = a.get<points>();
res.push_back(p);
}
return res;
}
// ╨Ю╤В╤А╨╕╤Б╨╛╨▓╨║╨░ ╨╗╨╕╨╜╨╕╨╣
// ╨ж╨▓╨╡╤В╨░ HSV
cv::Mat ocv_draw_lines(const strokes& x, bool color = true) {
// ╨Ш╤Б╤Е╨╛╨┤╨╜╤Л╨╣ ╤В╨╕╨┐ ╨╝╨░╤В╤А╨╕╤Ж╤Л
auto stype = color ? CV_8UC3 : CV_8UC1;
// ╨Ш╤В╨╛╨│╨╛╨▓╤Л╨╣ ╤В╨╕╨┐ ╨╝╨░╤В╤А╨╕╤Ж╤Л
auto dtype = color ? CV_32FC3 : CV_32FC1;
auto bg = color ? cv::Scalar(0, 0, 255) : cv::Scalar(255);
auto col = color ? cv::Scalar(0, 255, 220) : cv::Scalar(0);
cv::Mat img = cv::Mat(SIZE, SIZE, stype, bg);
// ╨Ъ╨╛╨╗╨╕╤З╨╡╤Б╤В╨▓╨╛ ╨╗╨╕╨╜╨╕╨╣
size_t n = x.size();
for (const auto& s: x) {
// ╨Ъ╨╛╨╗╨╕╤З╨╡╤Б╤В╨▓╨╛ ╤В╨╛╤З╨╡╨║ ╨▓ ╨╗╨╕╨╜╨╕╨╕
size_t n_points = s.shape()[1];
for (size_t i = 0; i < n_points - 1; ++i) {
// ╨в╨╛╤З╨║╨░ ╨╜╨░╤З╨░╨╗╨░ ╤И╤В╤А╨╕╤Е╨░
cv::Point from(s(0, i), s(1, i));
// ╨в╨╛╤З╨║╨░ ╨╛╨║╨╛╨╜╤З╨░╨╜╨╕╤П ╤И╤В╤А╨╕╤Е╨░
cv::Point to(s(0, i + 1), s(1, i + 1));
// ╨Ю╤В╤А╨╕╤Б╨╛╨▓╨║╨░ ╨╗╨╕╨╜╨╕╨╕
cv::line(img, from, to, col, LINE_WIDTH, LINE_TYPE);
}
if (color) {
// ╨Ь╨╡╨╜╤П╨╡╨╝ ╤Ж╨▓╨╡╤В ╨╗╨╕╨╜╨╕╨╕
col[0] += 180 / n;
}
}
if (color) {
// ╨Ь╨╡╨╜╤П╨╡╨╝ ╤Ж╨▓╨╡╤В╨╛╨▓╨╛╨╡ ╨┐╤А╨╡╨┤╤Б╤В╨░╨▓╨╗╨╡╨╜╨╕╨╡ ╨╜╨░ RGB
cv::cvtColor(img, img, cv::COLOR_HSV2RGB);
}
// ╨Ь╨╡╨╜╤П╨╡╨╝ ╤Д╨╛╤А╨╝╨░╤В ╨┐╤А╨╡╨┤╤Б╤В╨░╨▓╨╗╨╡╨╜╨╕╤П ╨╜╨░ float32 ╤Б ╨┤╨╕╨░╨┐╨░╨╖╨╛╨╜╨╛╨╝ [0, 1]
img.convertTo(img, dtype, 1 / 255.0);
return img;
}
// ╨Ю╨▒╤А╨░╨▒╨╛╤В╨║╨░ JSON ╨╕ ╨┐╨╛╨╗╤Г╤З╨╡╨╜╨╕╨╡ ╤В╨╡╨╜╨╖╨╛╤А╨░ ╤Б ╨┤╨░╨╜╨╜╤Л╨╝╨╕ ╨╕╨╖╨╛╨▒╤А╨░╨╢╨╡╨╜╨╕╤П
xtensor3d process(const std::string& x, double scale = 1.0, bool color = true) {
auto p = parse_json(x);
auto img = ocv_draw_lines(p, color);
if (scale != 1) {
cv::Mat out;
cv::resize(img, out, cv::Size(), scale, scale, RESIZE_TYPE);
cv::swap(img, out);
out.release();
}
xtensor3d arr = color ? to_xt<double,3>(img) : to_xt<double,1>(img);
return arr;
}
// [[Rcpp::export]]
rtensor3d cpp_process_json_str(const std::string& x,
double scale = 1.0,
bool color = true) {
xtensor3d res = process(x, scale, color);
return res;
}
// [[Rcpp::export]]
rtensor4d cpp_process_json_vector(const std::vector<std::string>& x,
double scale = 1.0,
bool color = false) {
size_t n = x.size();
size_t dim = floor(SIZE * scale);
size_t channels = color ? 3 : 1;
xtensor4d res({n, dim, dim, channels});
parallelFor(0, n, [&x, &res, scale, color](int i) {
xtensor3d tmp = process(x[i], scale, color);
auto view = xt::view(res, i, xt::all(), xt::all(), xt::all());
view = tmp;
});
return res;
}
рдпрд╣ рдХреЛрдб рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП src/cv_xt.cpp
рдФрд░ рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВ Rcpp::sourceCpp(file = "src/cv_xt.cpp", env = .GlobalEnv)
; рдХрд╛рдо рдХреЗ рд▓рд┐рдП рднреА рдЖрд╡рд╢реНрдпрдХ рд╣реИ nlohmann/json.hpp
рд╕реЗ
-
to_xt
- рдПрдХ рдЫрд╡рд┐ рдореИрдЯреНрд░рд┐рдХреНрд╕ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдлрд╝рдВрдХреНрд╢рди (cv::Mat
) рдПрдХ рдЯреЗрдВрд╕рд░ рдХреЗ рд▓рд┐рдПxt::xtensor
; -
parse_json
- рдлрд╝рдВрдХреНрд╢рди JSON рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддрд╛ рд╣реИ, рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдирд┐рдХрд╛рд▓рддрд╛ рд╣реИ, рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рдкреИрдХ рдХрд░рддрд╛ рд╣реИ; -
ocv_draw_lines
тАФ рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдкрд░рд┐рдгрд╛рдореА рд╡реЗрдХреНрдЯрд░ рд╕реЗ, рдмрд╣реБрд░рдВрдЧреА рд░реЗрдЦрд╛рдПрдБ рдЦреАрдВрдЪрддрд╛ рд╣реИ; -
process
- рдЙрдкрд░реЛрдХреНрдд рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдФрд░ рдкрд░рд┐рдгрд╛рдореА рдЫрд╡рд┐ рдХреЛ рд╕реНрдХреЗрд▓ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рднреА рдЬреЛрдбрд╝рддрд╛ рд╣реИ; -
cpp_process_json_str
- рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдКрдкрд░ рд░реИрдкрд░process
, рдЬреЛ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЖрд░-рдСрдмреНрдЬреЗрдХреНрдЯ (рдмрд╣реБрдЖрдпрд╛рдореА рд╕рд░рдгреА) рдореЗрдВ рдирд┐рд░реНрдпрд╛рдд рдХрд░рддрд╛ рд╣реИ; -
cpp_process_json_vector
- рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдКрдкрд░ рд░реИрдкрд░cpp_process_json_str
, рдЬреЛ рдЖрдкрдХреЛ рдорд▓реНрдЯреА-рдереНрд░реЗрдбреЗрдб рдореЛрдб рдореЗрдВ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╡реЗрдХреНрдЯрд░ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдмрд╣реБ-рд░рдВрдЧреАрди рд░реЗрдЦрд╛рдПрдБ рдЦреАрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, HSV рд░рдВрдЧ рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж RGB рдореЗрдВ рд░реВрдкрд╛рдВрддрд░рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ред рдЖрдЗрдП рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВ:
arr <- cpp_process_json_str(tmp_data[4, drawing])
dim(arr)
# [1] 256 256 3
plot(magick::image_read(arr))
рдЖрд░ рдФрд░ рд╕реА++ рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдЧрддрд┐ рдХреА рддреБрд▓рдирд╛
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++ рдХреЛрдб рдХреЛ рдкрдХрдбрд╝рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред
3. рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдмреИрдЪреЛрдВ рдХреЛ рдЕрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдЯрд░реЗрдЯрд░
рдЖрд░ рдХреЗ рдкрд╛рд╕ рд░реИрдо рдореЗрдВ рдлрд┐рдЯ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫреА-рдЦрд╛рд╕реА рдкреНрд░рддрд┐рд╖реНрдард╛ рд╣реИ, рдЬрдмрдХрд┐ рдкрд╛рдпрдерди рдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдбреЗрдЯрд╛ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреА рдЕрдзрд┐рдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИ, рдЬреЛ рдЖрдкрдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдФрд░ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЖрдЙрдЯ-рдСрдл-рдХреЛрд░ рдЧрдгрдирд╛ (рдмрд╛рд╣рд░реА рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЧрдгрдирд╛) рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╡рд░реНрдгрд┐рдд рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдПрдХ рдХреНрд▓рд╛рд╕рд┐рдХ рдФрд░ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдЙрджрд╛рд╣рд░рдг рдЧреНрд░реЗрдбрд┐рдПрдВрдЯ рдбрд┐рд╕реЗрдВрдЯ рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рдЧрд╣рди рддрдВрддреНрд░рд┐рдХрд╛ рдиреЗрдЯрд╡рд░реНрдХ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЪрд░рдг рдореЗрдВ рдЕрд╡рд▓реЛрдХрди рдХреЗ рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рд╣рд┐рд╕реНрд╕реЗ рдпрд╛ рдорд┐рдиреА-рдмреИрдЪ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЧреНрд░реЗрдбрд┐рдПрдВрдЯ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдкрд╛рдпрдерди рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рдбреАрдк рд▓рд░реНрдирд┐рдВрдЧ рдлреНрд░реЗрдорд╡рд░реНрдХ рдореЗрдВ рд╡рд┐рд╢реЗрд╖ рдХрдХреНрд╖рд╛рдПрдВ рд╣реЛрддреА рд╣реИрдВ рдЬреЛ рдбреЗрдЯрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреА рд╣реИрдВ: рдЯреЗрдмрд▓, рдлрд╝реЛрд▓реНрдбрд░реЛрдВ рдореЗрдВ рдЪрд┐рддреНрд░, рдмрд╛рдЗрдирд░реА рдкреНрд░рд╛рд░реВрдк, рдЖрджрд┐ред рдЖрдк рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рд▓рд┐рдЦ тАЛтАЛрд╕рдХрддреЗ рд╣реИрдВред R рдореЗрдВ рд╣рдо Python рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреА рд╕рднреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХрд╛ рд▓рд╛рдн рдЙрдард╛ рд╕рдХрддреЗ рд╣реИрдВ keras рдПрдХ рд╣реА рдирд╛рдо рдХреЗ рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдЗрд╕рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдмреИрдХрдПрдВрдб рдХреЗ рд╕рд╛рде, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рдкреИрдХреЗрдЬ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрд╛рд▓ рд╕реЗ рдврдБрдХрдирд╛. рдЙрддреНрддрд░рд╛рд░реНрджреНрдз рдПрдХ рдЕрд▓рдЧ рд▓рдВрдмреЗ рд▓реЗрдЦ рдХрд╛ рд╣рдХрджрд╛рд░ рд╣реИ; рдпрд╣ рди рдХреЗрд╡рд▓ рдЖрдкрдХреЛ рдЖрд░ рд╕реЗ рдкрд╛рдпрдерди рдХреЛрдб рдЪрд▓рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдЖрдкрдХреЛ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдкрд╛рдВрддрд░рдгреЛрдВ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реБрдП, рдЖрд░ рдФрд░ рдкрд╛рдпрдерди рд╕рддреНрд░реЛрдВ рдХреЗ рдмреАрдЪ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рднреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рд╣рдордиреЗ MonetDBLite рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рднреА рдбреЗрдЯрд╛ рдХреЛ RAM рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛ рд▓рд┐рдпрд╛ рд╣реИ, рд╕рднреА "рдиреНрдпреВрд░рд▓ рдиреЗрдЯрд╡рд░реНрдХ" рдХрд╛рд░реНрдп рдкрд╛рдпрдерди рдореЗрдВ рдореВрд▓ рдХреЛрдб рджреНрд╡рд╛рд░рд╛ рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗ, рд╣рдореЗрдВ рдмрд╕ рдбреЗрдЯрд╛ рдкрд░ рдПрдХ рдЗрдЯрд░реЗрдЯрд░ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдХреБрдЫ рднреА рддреИрдпрд╛рд░ рдирд╣реАрдВ рд╣реИ рдЖрд░ рдпрд╛ рдкрд╛рдпрдерди рдореЗрдВ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдПред рдЗрд╕рдХреЗ рд▓рд┐рдП рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдХреЗрд╡рд▓ рджреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рд╣реИрдВ: рдЗрд╕реЗ рдмреИрдЪреЛрдВ рдХреЛ рдПрдХ рдЕрдВрддрд╣реАрди рд▓реВрдк рдореЗрдВ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рдЕрдкрдиреА рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рд╣реЛрдЧрд╛ (рдЖрд░ рдореЗрдВ рдЙрддреНрддрд░рд╛рд░реНрджреНрдз рдХреЛ рдХреНрд▓реЛрдЬрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдмрд╕реЗ рд╕рд░рд▓ рддрд░реАрдХреЗ рд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рдкрд╣рд▓реЗ, рдЗрдЯрд░реЗрдЯрд░ рдХреЗ рдЕрдВрджрд░ рдЖрд░ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рд╕рд░рдгрд┐рдпреЛрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рдерд╛, рд▓реЗрдХрд┐рди рдкреИрдХреЗрдЬ рдХрд╛ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг 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
256x256 рдкрд┐рдХреНрд╕реЗрд▓ рдХреА рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИ, scale = 0.5
тАФ 128x128 рдкрд┐рдХреНрд╕реЗрд▓), рд░рдВрдЧ рд╕реВрдЪрдХ (color = FALSE
рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рдкрд░ рдЧреНрд░реЗрд╕реНрдХреЗрд▓ рдореЗрдВ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ color = TRUE
рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдЯреНрд░реЛрдХ рдХреЛ рдПрдХ рдирдП рд░рдВрдЧ рдореЗрдВ рдЦреАрдВрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ) рдФрд░ рдЗрдореЗрдЬрдиреЗрдЯ рдкрд░ рдкреВрд░реНрд╡-рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рд╕рдВрдХреЗрддрдХред рдЕрдВрддрд░рд╛рд▓ [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++ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ) рдФрд░ рдЪрд┐рддреНрд░реЛрдВ рдХреЗ рдЕрдиреБрд░реВрдк рд╕рд╛рд░рдгреА рдмрдирд╛рдирд╛ред рдлрд┐рд░ рдХреНрд▓рд╛рд╕ рд▓реЗрдмрд▓ рд╡рд╛рд▓реЗ рд╡рди-рд╣реЙрдЯ рд╡реЗрдХреНрдЯрд░ рдмрдирд╛рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдкрд┐рдХреНрд╕реЗрд▓ рдорд╛рди рдФрд░ рд▓реЗрдмрд▓ рд╡рд╛рд▓реЗ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЛ рдПрдХ рд╕реВрдЪреА рдореЗрдВ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рд░рд┐рдЯрд░реНрди рд╡реИрд▓реНрдпреВ рд╣реИред рдХрд╛рдо рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдордиреЗ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдореЗрдВ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ data.table
рдФрд░ рд▓рд┐рдВрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдВрд╢реЛрдзрди - рдЗрди рдкреИрдХреЗрдЬ "рдЪрд┐рдкреНрд╕" рдХреЗ рдмрд┐рдирд╛ рдбреЗрдЯрд╛ рддрд╛рд▓рд┐рдХрд╛ рдЖрд░ рдореЗрдВ рдХрд┐рд╕реА рднреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рдорд╛рддреНрд░рд╛ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдкреНрд░рднрд╛рд╡реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рдирд╛ рдХрд╛рдлреА рдХрдард┐рди рд╣реИред
рдХреЛрд░ 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)
рдпрд╛рдиреА рдЪреИрдирд▓реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдирд╣реАрдВ рдмрджрд▓реА рдЬрд╛ рд╕рдХрддреА. рдкрд╛рдпрдерди рдореЗрдВ рдРрд╕реА рдХреЛрдИ рд╕реАрдорд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдордиреЗ рдореВрд▓ рд▓реЗрдЦ (рдХреЗрд░рд╕ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдбреНрд░реЙрдкрдЖрдЙрдЯ рдХреЗ рдмрд┐рдирд╛) рдХрд╛ рдЕрдиреБрд╕рд░рдг рдХрд░рддреЗ рд╣реБрдП, рдЗрд╕ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХрд╛ рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рд┐рдЦрд╛ рдФрд░ рд▓рд┐рдЦрд╛:
рдореЛрдмрд╛рдЗрд▓рдиреЗрдЯ v1 рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░
library(keras)
top_3_categorical_accuracy <- custom_metric(
name = "top_3_categorical_accuracy",
metric_fn = function(y_true, y_pred) {
metric_top_k_categorical_accuracy(y_true, y_pred, k = 3)
}
)
layer_sep_conv_bn <- function(object,
filters,
alpha = 1,
depth_multiplier = 1,
strides = c(2, 2)) {
# NB! depth_multiplier != resolution multiplier
# https://github.com/keras-team/keras/issues/10349
layer_depthwise_conv_2d(
object = object,
kernel_size = c(3, 3),
strides = strides,
padding = "same",
depth_multiplier = depth_multiplier
) %>%
layer_batch_normalization() %>%
layer_activation_relu() %>%
layer_conv_2d(
filters = filters * alpha,
kernel_size = c(1, 1),
strides = c(1, 1)
) %>%
layer_batch_normalization() %>%
layer_activation_relu()
}
get_mobilenet_v1 <- function(input_shape = c(224, 224, 1),
num_classes = 340,
alpha = 1,
depth_multiplier = 1,
optimizer = optimizer_adam(lr = 0.002),
loss = "categorical_crossentropy",
metrics = c("categorical_crossentropy",
top_3_categorical_accuracy)) {
inputs <- layer_input(shape = input_shape)
outputs <- inputs %>%
layer_conv_2d(filters = 32, kernel_size = c(3, 3), strides = c(2, 2), padding = "same") %>%
layer_batch_normalization() %>%
layer_activation_relu() %>%
layer_sep_conv_bn(filters = 64, strides = c(1, 1)) %>%
layer_sep_conv_bn(filters = 128, strides = c(2, 2)) %>%
layer_sep_conv_bn(filters = 128, strides = c(1, 1)) %>%
layer_sep_conv_bn(filters = 256, strides = c(2, 2)) %>%
layer_sep_conv_bn(filters = 256, strides = c(1, 1)) %>%
layer_sep_conv_bn(filters = 512, strides = c(2, 2)) %>%
layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
layer_sep_conv_bn(filters = 512, strides = c(1, 1)) %>%
layer_sep_conv_bn(filters = 1024, strides = c(2, 2)) %>%
layer_sep_conv_bn(filters = 1024, strides = c(1, 1)) %>%
layer_global_average_pooling_2d() %>%
layer_dense(units = num_classes) %>%
layer_activation_softmax()
model <- keras_model(
inputs = inputs,
outputs = outputs
)
model %>% compile(
optimizer = optimizer,
loss = loss,
metrics = metrics
)
return(model)
}
рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдиреБрдХрд╕рд╛рди рд╕реНрдкрд╖реНрдЯ рд╣реИрдВ. рдореИрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдореЙрдбрд▓реЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рдореИрдВ рдкреНрд░рддреНрдпреЗрдХ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рд╣рдо рдЗрдореЗрдЬрдиреЗрдЯ рдкрд░ рдкреВрд░реНрд╡-рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рдореЙрдбрд▓реЛрдВ рдХреЗ рд╡рдЬрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдЕрд╡рд╕рд░ рд╕реЗ рднреА рд╡рдВрдЪрд┐рдд рдереЗред рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣, рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рд╕реЗ рдорджрдж рдорд┐рд▓реАред рд╕рдорд╛рд░реЛрд╣ get_config()
рдЖрдкрдХреЛ рд╕рдВрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд░реВрдк рдореЗрдВ рдореЙрдбрд▓ рдХрд╛ рд╡рд┐рд╡рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ (base_model_conf$layers
- рдПрдХ рдирд┐рдпрдорд┐рдд рдЖрд░ рд╕реВрдЪреА), рдФрд░ рдлрд╝рдВрдХреНрд╢рди from_config()
рдореЙрдбрд▓ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рд░рд┐рд╡рд░реНрд╕ рд░реВрдкрд╛рдВрддрд░рдг рдХрд░рддрд╛ рд╣реИ:
base_model_conf <- get_config(base_model)
base_model_conf$layers[[1]]$config$batch_input_shape[[4]] <- 1L
base_model <- from_config(base_model_conf)
рдЕрдм рдХрд┐рд╕реА рднреА рдЖрдкреВрд░реНрддрд┐ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ keras рдЗрдореЗрдЬрдиреЗрдЯ рдкрд░ рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рд╡рдЬрди рд╡рд╛рд▓реЗ рдпрд╛ рдмрд┐рдирд╛ рд╡рдЬрди рд╡рд╛рд▓реЗ рдореЙрдбрд▓:
рддреИрдпрд╛рд░ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп
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 рдХреЗ рд╕рд╛рде-рд╕рд╛рде 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)
рдкреИрдХреЗрдЬ docpt рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ Rscript bin/train_nn.R -m resnet50 -c -d /home/andrey/doodle_db
рдпрд╛ ./bin/train_nn.R -m resnet50 -c -d /home/andrey/doodle_db
, рдпрджрд┐ рдлрд╝рд╛рдЗрд▓ train_nn.R
рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рд╣реИ (рдпрд╣ рдЖрджреЗрд╢ рдореЙрдбрд▓ рдХреЛ рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрдЧрд╛ resnet50
128x128 рдкрд┐рдХреНрд╕реЗрд▓ рдорд╛рдкрдиреЗ рд╡рд╛рд▓реА рддреАрди-рд░рдВрдЧ рдХреА рдЫрд╡рд┐рдпреЛрдВ рдкрд░, рдбреЗрдЯрд╛рдмреЗрд╕ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд╕реНрдерд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП /home/andrey/doodle_db
). рдЖрдк рд╕реВрдЪреА рдореЗрдВ рд╕реАрдЦрдиреЗ рдХреА рдЧрддрд┐, рдЕрдиреБрдХреВрд▓рдХ рдкреНрд░рдХрд╛рд░ рдФрд░ рдХреЛрдИ рдЕрдиреНрдп рдЕрдиреБрдХреВрд▓рди рдпреЛрдЧреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд░рдХрд╛рд╢рди рдХреА рддреИрдпрд╛рд░реА рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ mobilenet_v2
рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг рд╕реЗ keras рдЖрд░ рдЙрдкрдпреЛрдЧ рдореЗрдВ
рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдиреЗ RStudio рдореЗрдВ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рдЕрдзрд┐рдХ рдкрд╛рд░рдВрдкрд░рд┐рдХ рд▓реЙрдиреНрдЪ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдореЙрдбрд▓реЛрдВ рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рддреЗрдЬ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛ рджрд┐рдпрд╛ (рд╣рдо рдкреИрдХреЗрдЬ рдХреЛ рд╕рдВрднрд╛рд╡рд┐рдд рд╡рд┐рдХрд▓реНрдк рдХреЗ рд░реВрдк рдореЗрдВ рдиреЛрдЯ рдХрд░рддреЗ рд╣реИрдВ)
6. рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдбреЙрдХрд░реАрдХрд░рдг
рд╣рдордиреЗ рдЯреАрдо рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдХреЗ рдмреАрдЪ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдФрд░ рдХреНрд▓рд╛рдЙрдб рдореЗрдВ рддреЗрдЬреА рд╕реЗ рддреИрдирд╛рддреА рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рд╡рд░рдг рдХреА рдкреЛрд░реНрдЯреЗрдмрд┐рд▓рд┐рдЯреА рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреЙрдХрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдЖрдк рдЗрд╕ рдЯреВрд▓ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реЛрдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдПрдХ рдЖрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗ рд▓рд┐рдП рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдЕрд╕рд╛рдорд╛рдиреНрдп рд╣реИ
рдбреЙрдХрд░ рдЖрдкрдХреЛ рд╕реНрдХреНрд░реИрдЪ рд╕реЗ рдЕрдкрдиреА рдЦреБрдж рдХреА рдЫрд╡рд┐рдпрд╛рдВ рдмрдирд╛рдиреЗ рдФрд░ рдЕрдкрдиреА рдЦреБрдж рдХреА рдЫрд╡рд┐рдпрд╛рдВ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреНрдп рдЫрд╡рд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЙрдкрд▓рдмреНрдз рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ рд╕рдордп, рд╣рдо рдЗрд╕ рдирд┐рд╖реНрдХрд░реНрд╖ рдкрд░ рдкрд╣реБрдВрдЪреЗ рдХрд┐ NVIDIA, CUDA+cuDNN рдбреНрд░рд╛рдЗрд╡рд░ рдФрд░ рдкрд╛рдпрдерди рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рдЫрд╡рд┐ рдХрд╛ рдХрд╛рдлреА рдмрдбрд╝рд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ, рдФрд░ рд╣рдордиреЗ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдЫрд╡рд┐ рдХреЛ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реЗрдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ tensorflow/tensorflow:1.12.0-gpu
, рд╡рд╣рд╛рдВ рдЖрд╡рд╢реНрдпрдХ рдЖрд░ рдкреИрдХреЗрдЬ рдЬреЛрдбрд╝рдирд╛ред
рдЕрдВрддрд┐рдо рдбреЛрдХрд░ рдлрд╝рд╛рдЗрд▓ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреА:
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
. рдЗрд╕рд╕реЗ рдХреЛрдб рдореЗрдВ OS рд╕рдВрд╕реНрдХрд░рдг рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕реЗ рдмрдЪрд╛ рдЬрд╛ рд╕рдХрд╛ред
рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд, рдПрдХ рдЫреЛрдЯреА рдмреИрд╢ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓рд┐рдЦреА рдЧрдИ рдереА рдЬреЛ рдЖрдкрдХреЛ рд╡рд┐рднрд┐рдиреНрди рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рдПрдХ рдХрдВрдЯреЗрдирд░ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпреЗ рддрдВрддреНрд░рд┐рдХрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдкрд╣рд▓реЗ рдХрдВрдЯреЗрдирд░ рдХреЗ рдЕрдВрджрд░ рд░рдЦреЗ рдЧрдП рдереЗ, рдпрд╛ рдбрд┐рдмрдЧрд┐рдВрдЧ рдФрд░ рдХрдВрдЯреЗрдирд░ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдорд╛рдВрдб рд╢реЗрд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:
рдХрдВрдЯреЗрдирд░ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░рд┐рдкреНрдЯ
#!/bin/sh
DBDIR=${PWD}/db
LOGSDIR=${PWD}/logs
MODELDIR=${PWD}/models
DATADIR=${PWD}/data
ARGS="--runtime=nvidia --rm -v ${DBDIR}:/db -v ${LOGSDIR}:/app/logs -v ${MODELDIR}:/app/models -v ${DATADIR}:/app/data"
if [ -z "$1" ]; then
CMD="Rscript /app/train_nn.R"
elif [ "$1" = "bash" ]; then
ARGS="${ARGS} -ti"
else
CMD="Rscript /app/train_nn.R $@"
fi
docker run ${ARGS} doodles-tf ${CMD}
рдпрджрд┐ рдпрд╣ рдмреИрд╢ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдмрд┐рдирд╛ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рдЪрд▓рддреА рд╣реИ, рддреЛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдХрдВрдЯреЗрдирд░ рдХреЗ рдЕрдВрджрд░ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ train_nn.R
рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде; рдпрджрд┐ рдкрд╣рд▓рд╛ рд╕реНрдерд┐рддреАрдп рддрд░реНрдХ "рдмреИрд╢" рд╣реИ, рддреЛ рдХрдВрдЯреЗрдирд░ рдПрдХ рдХрдорд╛рдВрдб рд╢реЗрд▓ рдХреЗ рд╕рд╛рде рдЗрдВрдЯрд░реИрдХреНрдЯрд┐рд╡ рд░реВрдк рд╕реЗ рд╢реБрд░реВ рд╣реЛрдЧрд╛ред рдЕрдиреНрдп рд╕рднреА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╕реНрдерд┐рддреАрдп рддрд░реНрдХреЛрдВ рдХреЗ рдорд╛рди рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ: CMD="Rscript /app/train_nn.R $@"
.
рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛, рд╕рд╛рде рд╣реА рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рдореЙрдбрд▓ рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛, рд╣реЛрд╕реНрдЯ рд╕рд┐рд╕реНрдЯрдо рд╕реЗ рдХрдВрдЯреЗрдирд░ рдХреЗ рдЕрдВрджрд░ рд▓рдЧрд╛рдИ рдЬрд╛рддреА рд╣реИ, рдЬреЛ рдЖрдкрдХреЛ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╣реЗрд░рдлреЗрд░ рдХреЗ рдмрд┐рдирд╛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред
7. Google рдХреНрд▓рд╛рдЙрдб рдкрд░ рдПрдХрд╛рдзрд┐рдХ GPU рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдмрд╣реБрдд рд╢реЛрд░ рд╡рд╛рд▓рд╛ рдбреЗрдЯрд╛ рдерд╛ (рд╢реАрд░реНрд╖рдХ рдЪрд┐рддреНрд░ рджреЗрдЦреЗрдВ, ODS рд╕реНрд▓реИрдХ рд╕реЗ @Leigh.plt рд╕реЗ рдЙрдзрд╛рд░ рд▓рд┐рдпрд╛ рдЧрдпрд╛)ред рдмрдбрд╝реЗ рдмреИрдЪ рдЗрд╕рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ 1 рдЬреАрдкреАрдпреВ рд╡рд╛рд▓реЗ рдкреАрд╕реА рдкрд░ рдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рдмрд╛рдж, рд╣рдордиреЗ рдХреНрд▓рд╛рдЙрдб рдореЗрдВ рдХрдИ рдЬреАрдкреАрдпреВ рдкрд░ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдореЙрдбрд▓ рдореЗрдВ рдорд╣рд╛рд░рдд рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдкреНрд░рдпреБрдХреНрдд GoogleCloud (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
)
})
рдлрд┐рд░ рдЕрд╕рдВрдХрд▓рд┐рдд (рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ) рдореЙрдбрд▓ рдХреЛ рдЙрдкрд▓рдмреНрдз 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)
)
рдЕрдВрддрд┐рдо рдкрд░рдд рдХреЛ рдЫреЛрдбрд╝рдХрд░ рд╕рднреА рдкрд░рддреЛрдВ рдХреЛ рдлрд╝реНрд░реАрдЬрд╝ рдХрд░рдиреЗ, рдЕрдВрддрд┐рдо рдкрд░рдд рдХреЛ рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рдХрд░рдиреЗ, рдЕрдирдлрд╝реНрд░реАрдЬрд╝рд┐рдВрдЧ рдХрд░рдиреЗ рдФрд░ рдХрдИ рдЬреАрдкреАрдпреВ рдХреЗ рд▓рд┐рдП рдкреВрд░реЗ рдореЙрдбрд▓ рдХреЛ рдкреБрдирдГ рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд▓рд╛рд╕рд┐рдХ рддрдХрдиреАрдХ рдХреЛ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрд╛ред
рдмрд┐рдирд╛ рдЙрдкрдпреЛрдЧ рдХреЗ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХреА рдЧрдИред рдЯреЗрдВрд╕рд░рдмреЛрд░реНрдб, рдкреНрд░рддреНрдпреЗрдХ рдпреБрдЧ рдХреЗ рдмрд╛рдж рдЬрд╛рдирдХрд╛рд░реАрдкреВрд░реНрдг рдирд╛рдореЛрдВ рдХреЗ рд╕рд╛рде рд▓реЙрдЧ рд░рд┐рдХреЙрд░реНрдб рдХрд░рдиреЗ рдФрд░ рдореЙрдбрд▓ рд╕рд╣реЗрдЬрдиреЗ рддрдХ рдЦреБрдж рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдирд╛:
рдХреЙрд▓рдмреИрдХ
# ╨и╨░╨▒╨╗╨╛╨╜ ╨╕╨╝╨╡╨╜╨╕ ╤Д╨░╨╣╨╗╨░ ╨╗╨╛╨│╨░
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
рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рддреЗрдЬреА рд╕реЗ); рдХреБрдЫ рдкреНрд░рдпрд╛рд╕реЛрдВ рд╕реЗ, рддреГрддреАрдп-рдкрдХреНрд╖ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ R рдореЗрдВ рдкреЛрд░реНрдЯ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,рдпрд╣ ; - рдкрд┐рдЫрд▓реЗ рдмрд┐рдВрджреБ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдХрдИ рдЬреАрдкреАрдпреВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рд╕рд╣реА рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдЧрддрд┐ рдХрд╛ рдЪрдпрди рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рдерд╛;
- рдЖрдзреБрдирд┐рдХ рддрдВрддреНрд░рд┐рдХрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреА рдХрдореА рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЗрдореЗрдЬрдиреЗрдЯ рдкрд░ рдкреВрд░реНрд╡-рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд;
- рдХреЛрдИ рдПрдХ рдЪрдХреНрд░ рдиреАрддрд┐ рдФрд░ рднреЗрджрднрд╛рд╡рдкреВрд░реНрдг рд╕реАрдЦрдиреЗ рдХреА рджрд░ (рдХреЛрд╕рд╛рдЗрди рдПрдиреАрд▓рд┐рдВрдЧ рд╣рдорд╛рд░реЗ рдЕрдиреБрд░реЛрдз рдкрд░ рдирд╣реАрдВ рдереА
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд , рдзрдиреНрдпрд╡рд╛рджрд╕реНрдХрд╛рдИрдбреИрди ).
рдЗрд╕ рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рд╕реЗ рдХреМрди рд╕реА рдЙрдкрдпреЛрдЧреА рдмрд╛рддреЗрдВ рд╕реАрдЦреАрдВ:
- рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдХрдо-рд╢рдХреНрддрд┐ рд╡рд╛рд▓реЗ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рдкрд░, рдЖрдк рдмрд┐рдирд╛ рдХрд┐рд╕реА рдкрд░реЗрд╢рд╛рдиреА рдХреЗ рдЕрдЪреНрдЫреА рдорд╛рддреНрд░рд╛ рдореЗрдВ (рд░реИрдо рдХреЗ рдЖрдХрд╛рд░ рд╕реЗ рдХрдИ рдЧреБрдирд╛ рдЕрдзрд┐рдХ) рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд▓рд╛рд╕реНрдЯрд┐рдХ рдмреИрдЧ рдбреЗрдЯрд╛ рддрд╛рд▓рд┐рдХрд╛ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЗ рд╕реНрдерд╛рди-рд╕реНрдерд╛рди рдкрд░ рд╕рдВрд╢реЛрдзрди рдХреЗ рдХрд╛рд░рдг рдореЗрдореЛрд░реА рдХреА рдмрдЪрдд рд╣реЛрддреА рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЙрдиреНрд╣реЗрдВ рдХреЙрдкреА рдХрд░рдиреЗ рд╕реЗ рдмрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЬрдм рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХреА рдХреНрд╖рдорддрд╛рдПрдВ рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ рд╕реНрдХреНрд░рд┐рдкреНрдЯрд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЬреНрдЮрд╛рдд рд╕рднреА рдЙрдкрдХрд░рдгреЛрдВ рдХреЗ рдмреАрдЪ рдЙрдЪреНрдЪрддрдо рдЧрддрд┐ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреА рд╣реИрдВред рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдбреЗрдЯрд╛ рд╕рд╣реЗрдЬрдиреЗ рд╕реЗ, рдХрдИ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЖрдкрдХреЛ рдкреВрд░реЗ рдбреЗрдЯрд╛рд╕реЗрдЯ рдХреЛ рд░реИрдо рдореЗрдВ рдирд┐рдЪреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдирд╣реАрдВ рд╕реЛрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд┐рд▓рддреА рд╣реИред
- рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ R рдореЗрдВ рдзреАрдореЗ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХреЛ C++ рдореЗрдВ рддреЗрдЬрд╝ рдлрд╝рдВрдХреНрд╢рдВрд╕ рд╕реЗ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЖрд░рд╕реАрдкреАрдкреА. рдпрджрд┐ рдЙрдкрдпреЛрдЧ рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдЖрд░рд╕реАрдкреАрдкреАрдереНрд░реЗрдб рдпрд╛ Rcppрд╕рдорд╛рдирд╛рдВрддрд░, рд╣рдореЗрдВ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдорд▓реНрдЯреА-рдереНрд░реЗрдбреЗрдб рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдорд┐рд▓рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрд░ рд╕реНрддрд░ рдкрд░ рдХреЛрдб рдХреЛ рд╕рдорд╛рдирд╛рдВрддрд░ рдХрд░рдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
- рдкреИрдХреЗрдЬ рдЖрд░рд╕реАрдкреАрдкреА C++ рдХреЗ рдЧрдВрднреАрд░ рдЬреНрдЮрд╛рди рдХреЗ рдмрд┐рдирд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЖрд╡рд╢реНрдпрдХ рдиреНрдпреВрдирддрдо рд░реВрдкрд░реЗрдЦрд╛ рджреА рдЧрдИ рд╣реИ
рдпрд╣рд╛рдВ . рдЬреИрд╕реЗ рдХрдИ рд╢рд╛рдирджрд╛рд░ рд╕реА-рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓реЗрдВ xtensor рд╕реАрдЖрд░рдПрдПрди рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ, рдпрд╛рдиреА, рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдПрдХ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪрд╛ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ рдЬреЛ рддреИрдпрд╛рд░ рдЙрдЪреНрдЪ-рдкреНрд░рджрд░реНрд╢рди рд╕реА ++ рдХреЛрдб рдХреЛ рдЖрд░ рдореЗрдВ рдПрдХреАрдХреГрдд рдХрд░рддрд╛ рд╣реИред рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реБрд╡рд┐рдзрд╛ рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╣рд╛рдЗрд▓рд╛рдЗрдЯрд┐рдВрдЧ рдФрд░ RStudio рдореЗрдВ рдПрдХ рд╕реНрдерд┐рд░ C++ рдХреЛрдб рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рд╣реИред - docpt рдЖрдкрдХреЛ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рд╕реНрд╡-рдирд┐рд╣рд┐рдд рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЪрд▓рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрд╣ рд░рд┐рдореЛрдЯ рд╕рд░реНрд╡рд░ рд╕рд╣рд┐рдд рдЕрдиреНрдп рдкрд░ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдбреЙрдХрд░ рдХреЗ рдЕрдВрддрд░реНрдЧрддред RStudio рдореЗрдВ, рддрдВрддреНрд░рд┐рдХрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХреЗ рд╕рд╛рде рдХрдИ рдШрдВрдЯреЛрдВ рдХреЗ рдкреНрд░рдпреЛрдЧ рдХрд░рдирд╛ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рдФрд░ рд╕рд░реНрд╡рд░ рдкрд░ IDE рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рд╣рдореЗрд╢рд╛ рдЙрдЪрд┐рдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред
- рдбреЙрдХрд░ рдУрдПрд╕ рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╡рд┐рднрд┐рдиреНрди рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рд╡рд╛рд▓реЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рдмреАрдЪ рдХреЛрдб рдкреЛрд░реНрдЯреЗрдмрд┐рд▓рд┐рдЯреА рдФрд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдпрддрд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рд╕рд░реНрд╡рд░ рдкрд░ рдирд┐рд╖реНрдкрд╛рджрди рдореЗрдВ рдЖрд╕рд╛рдиреА рднреА рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЖрдк рдХреЗрд╡рд▓ рдПрдХ рдХрдорд╛рдВрдб рд╕реЗ рд╕рдВрдкреВрд░реНрдг рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд▓реЙрдиреНрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
- Google рдХреНрд▓рд╛рдЙрдб рдорд╣рдВрдЧреЗ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рдкрд░ рдкреНрд░рдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдмрдЬрдЯ-рдЕрдиреБрдХреВрд▓ рддрд░реАрдХрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕рд╛рд╡рдзрд╛рдиреА рд╕реЗ рдЪреБрдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
- рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХреЛрдб рдЕрдВрд╢реЛрдВ рдХреА рдЧрддрд┐ рдХреЛ рдорд╛рдкрдирд╛ рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реИ, рдЦрд╛рд╕рдХрд░ рдЬрдм рдЖрд░ рдФрд░ рд╕реА++ рдФрд░ рдкреИрдХреЗрдЬ рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдХрд░рддреЗ рд╕рдордп рдмреЗрдВрдЪ - рдмрд╣реБрдд рдЖрд╕рд╛рди рднреА.
рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░ рдпрд╣ рдЕрдиреБрднрд╡ рдмрд╣реБрдд рдлрд╛рдпрджреЗрдордВрдж рд░рд╣рд╛ рдФрд░ рд╣рдо рдЙрдард╛рдП рдЧрдП рдХреБрдЫ рдореБрджреНрджреЛрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреЗрдВрдЧреЗред
рд╕реНрд░реЛрдд: www.habr.com