āĻ•ā§āĻ‡āĻ• āĻĄā§āĻ° āĻĄā§āĻĄāĻ˛ āĻ¸ā§āĻŦā§€āĻ•ā§ƒāĻ¤āĻŋ: āĻ•āĻŋāĻ­āĻžāĻŦā§‡ R, C++ āĻāĻŦāĻ‚ āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻŦāĻ¨ā§āĻ§ā§āĻ¤ā§āĻŦ āĻ•āĻ°āĻž āĻ¯āĻžāĻ¯āĻŧ

āĻ•ā§āĻ‡āĻ• āĻĄā§āĻ° āĻĄā§āĻĄāĻ˛ āĻ¸ā§āĻŦā§€āĻ•ā§ƒāĻ¤āĻŋ: āĻ•āĻŋāĻ­āĻžāĻŦā§‡ R, C++ āĻāĻŦāĻ‚ āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻŦāĻ¨ā§āĻ§ā§āĻ¤ā§āĻŦ āĻ•āĻ°āĻž āĻ¯āĻžāĻ¯āĻŧ

āĻšā§‡ āĻšāĻžāĻŦāĻ°!

āĻ—āĻ¤ āĻĒāĻ¤āĻ¨ā§‡, āĻ•āĻžāĻ—āĻ˛ āĻšāĻžāĻ¤ā§‡ āĻ†āĻāĻ•āĻž āĻ›āĻŦāĻŋ, āĻ•ā§āĻ‡āĻ• āĻĄā§āĻ° āĻĄā§āĻĄāĻ˛ āĻ°āĻŋāĻ•āĻ—āĻ¨āĻŋāĻļāĻ¨āĻ•ā§‡ āĻļā§āĻ°ā§‡āĻŖā§€āĻŦāĻĻā§āĻ§ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻĒā§āĻ°āĻ¤āĻŋāĻ¯ā§‹āĻ—āĻŋāĻ¤āĻžāĻ° āĻ†āĻ¯āĻŧā§‹āĻœāĻ¨ āĻ•āĻ°ā§‡āĻ›āĻŋāĻ˛, āĻ¯ā§‡āĻ–āĻžāĻ¨ā§‡ āĻ…āĻ¨ā§āĻ¯āĻĻā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡, R-āĻŦāĻŋāĻœā§āĻžāĻžāĻ¨ā§€āĻĻā§‡āĻ° āĻāĻ•āĻŸāĻŋ āĻĻāĻ˛ āĻ…āĻ‚āĻļ āĻ¨āĻŋāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛: āĻ†āĻ°ā§āĻŸā§‡āĻŽ āĻ•ā§āĻ˛ā§‡āĻ­āĻ¤āĻ¸ā§‹āĻ­āĻž, āĻĢāĻŋāĻ˛āĻŋāĻĒāĻž āĻŽā§āĻ¯āĻžāĻ¨ā§‡āĻœāĻžāĻ° и āĻ†āĻ¨ā§āĻĻā§āĻ°ā§‡ āĻ“āĻ—ā§āĻ°ā§āĻŸāĻ¸āĻ­. āĻ†āĻŽāĻ°āĻž āĻĒā§āĻ°āĻ¤āĻŋāĻ¯ā§‹āĻ—āĻŋāĻ¤āĻžāĻ° āĻŦāĻŋāĻ¸ā§āĻ¤āĻžāĻ°āĻŋāĻ¤ āĻŦāĻ°ā§āĻŖāĻ¨āĻž āĻ•āĻ°āĻŦ āĻ¨āĻž; āĻāĻŸāĻŋ āĻ‡āĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§‡āĻ‡ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›ā§‡ āĻ¸āĻžāĻŽā§āĻĒā§āĻ°āĻ¤āĻŋāĻ• āĻĒā§āĻ°āĻ•āĻžāĻļāĻ¨āĻž.

āĻāĻ‡āĻŦāĻžāĻ° āĻāĻŸāĻŋ āĻŽā§‡āĻĄā§‡āĻ˛ āĻĢāĻžāĻ°ā§āĻŽāĻŋāĻ‚āĻ¯āĻŧā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻ•āĻžāĻœ āĻ•āĻ°ā§‡āĻ¨āĻŋ, āĻ¤āĻŦā§‡ āĻ…āĻ¨ā§‡āĻ• āĻŽā§‚āĻ˛ā§āĻ¯āĻŦāĻžāĻ¨ āĻ…āĻ­āĻŋāĻœā§āĻžāĻ¤āĻž āĻ…āĻ°ā§āĻœāĻ¨ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›ā§‡, āĻ¤āĻžāĻ‡ āĻ†āĻŽāĻŋ āĻ¸āĻŽā§āĻĒā§āĻ°āĻĻāĻžāĻ¯āĻŧāĻ•ā§‡ āĻ•āĻžāĻ—āĻ˛ā§‡ āĻāĻŦāĻ‚ āĻĻā§ˆāĻ¨āĻ¨ā§āĻĻāĻŋāĻ¨ āĻ•āĻžāĻœā§‡āĻ° āĻŦā§‡āĻļ āĻ•āĻ¯āĻŧā§‡āĻ•āĻŸāĻŋ āĻ†āĻ•āĻ°ā§āĻˇāĻŖā§€āĻ¯āĻŧ āĻāĻŦāĻ‚ āĻĻāĻ°āĻ•āĻžāĻ°ā§€ āĻœāĻŋāĻ¨āĻŋāĻ¸ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻ•ā§‡ āĻŦāĻ˛āĻ¤ā§‡ āĻšāĻžāĻ‡āĨ¤ āĻ†āĻ˛ā§‹āĻšāĻŋāĻ¤ āĻŦāĻŋāĻˇāĻ¯āĻŧāĻ—ā§āĻ˛āĻŋāĻ° āĻŽāĻ§ā§āĻ¯ā§‡: āĻ›āĻžāĻĄāĻŧāĻž āĻ•āĻ āĻŋāĻ¨ āĻœā§€āĻŦāĻ¨ OpenCV, JSON āĻĒāĻžāĻ°ā§āĻ¸āĻŋāĻ‚ (āĻāĻ‡ āĻ‰āĻĻāĻžāĻšāĻ°āĻŖāĻ—ā§āĻ˛āĻŋ R āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸ āĻŦāĻž āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœā§‡ C++ āĻ•ā§‹āĻĄā§‡āĻ° āĻāĻ•ā§€āĻ•āĻ°āĻŖ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž āĻ•āĻ°ā§‡ Rcpp), āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸā§‡āĻ° āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻŸāĻžāĻ°āĻžāĻ‡āĻœā§‡āĻļāĻ¨ āĻāĻŦāĻ‚ āĻšā§‚āĻĄāĻŧāĻžāĻ¨ā§āĻ¤ āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ā§‡āĻ° āĻĄāĻ•āĻžāĻ°āĻžāĻ‡āĻœā§‡āĻļāĻ¨āĨ¤ āĻ¸āĻŽā§āĻĒāĻžāĻĻāĻ¨ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻ‰āĻĒāĻ¯ā§āĻ•ā§āĻ¤ āĻāĻ•āĻŸāĻŋ āĻĢāĻ°ā§āĻŽā§‡āĻ° āĻŦāĻžāĻ°ā§āĻ¤āĻž āĻĨā§‡āĻ•ā§‡ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻ•ā§‹āĻĄ āĻĒāĻžāĻ“āĻ¯āĻŧāĻž āĻ¯āĻžāĻ¯āĻŧ āĻ¸āĻ‚āĻ—ā§āĻ°āĻšāĻ¸ā§āĻĨāĻ˛.

āĻ¸ā§‚āĻšāĻŋāĻĒāĻ¤ā§āĻ°:

  1. āĻĻāĻ•ā§āĻˇāĻ¤āĻžāĻ° āĻ¸āĻžāĻĨā§‡ CSV āĻĨā§‡āĻ•ā§‡ MonetDB-āĻ¤ā§‡ āĻĄā§‡āĻŸāĻž āĻ˛ā§‹āĻĄ āĻ•āĻ°ā§āĻ¨
  2. āĻŦā§āĻ¯āĻžāĻš āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤ āĻ•āĻ°āĻž āĻšāĻšā§āĻ›ā§‡
  3. āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ āĻĨā§‡āĻ•ā§‡ āĻŦā§āĻ¯āĻžāĻš āĻ†āĻ¨āĻ˛ā§‹āĻĄ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻ•āĻžāĻ°ā§€
  4. āĻāĻ•āĻŸāĻŋ āĻŽāĻĄā§‡āĻ˛ āĻ†āĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āĻšāĻžāĻ° āĻ¨āĻŋāĻ°ā§āĻŦāĻžāĻšāĻ¨ āĻ•āĻ°āĻž
  5. āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸ āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻŸāĻžāĻ°āĻžāĻ‡āĻœā§‡āĻļāĻ¨
  6. āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸā§‡āĻ° āĻĄāĻ•āĻžāĻ°āĻžāĻ‡āĻœā§‡āĻļāĻ¨
  7. Google āĻ•ā§āĻ˛āĻžāĻ‰āĻĄā§‡ āĻāĻ•āĻžāĻ§āĻŋāĻ• GPU āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž
  8. āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤ā§‡ āĻāĻ•āĻŸāĻŋ āĻ‰āĻĒāĻ¸āĻ‚āĻšāĻžāĻ°ā§‡āĻ°

1. āĻĻāĻ•ā§āĻˇāĻ¤āĻžāĻ° āĻ¸āĻžāĻĨā§‡ CSV āĻĨā§‡āĻ•ā§‡ MonetDB āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ā§‡ āĻĄā§‡āĻŸāĻž āĻ˛ā§‹āĻĄ āĻ•āĻ°ā§āĻ¨

āĻāĻ‡ āĻĒā§āĻ°āĻ¤āĻŋāĻ¯ā§‹āĻ—āĻŋāĻ¤āĻžāĻ° āĻĄā§‡āĻŸāĻž āĻ°ā§‡āĻĄāĻŋāĻŽā§‡āĻĄ āĻ‡āĻŽā§‡āĻœ āĻ†āĻ•āĻžāĻ°ā§‡ āĻ¨āĻ¯āĻŧ, āĻŦāĻ°āĻ‚ āĻĒāĻ¯āĻŧā§‡āĻ¨ā§āĻŸ āĻ•ā§‹āĻ…āĻ°ā§āĻĄāĻŋāĻ¨ā§‡āĻŸ āĻ¸āĻš JSON āĻ¸āĻŽāĻ¨ā§āĻŦāĻŋāĻ¤ 340āĻŸāĻŋ CSV āĻĢāĻžāĻ‡āĻ˛ (āĻĒā§āĻ°āĻ¤āĻŋāĻŸāĻŋ āĻ•ā§āĻ˛āĻžāĻ¸ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻĢāĻžāĻ‡āĻ˛) āĻ†āĻ•āĻžāĻ°ā§‡ āĻĒā§āĻ°āĻĻāĻžāĻ¨ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧāĨ¤ āĻāĻ‡ āĻĒāĻ¯āĻŧā§‡āĻ¨ā§āĻŸāĻ—ā§āĻ˛āĻŋāĻ•ā§‡ āĻ˛āĻžāĻ‡āĻ¨ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻ¸āĻ‚āĻ¯ā§āĻ•ā§āĻ¤ āĻ•āĻ°ā§‡, āĻ†āĻŽāĻ°āĻž 256x256 āĻĒāĻŋāĻ•ā§āĻ¸ā§‡āĻ˛ āĻĒāĻ°āĻŋāĻŽāĻžāĻĒā§‡āĻ° āĻāĻ•āĻŸāĻŋ āĻšā§‚āĻĄāĻŧāĻžāĻ¨ā§āĻ¤ āĻšāĻŋāĻ¤ā§āĻ° āĻĒāĻžāĻ‡āĨ¤ āĻāĻ›āĻžāĻĄāĻŧāĻžāĻ“ āĻĒā§āĻ°āĻ¤āĻŋāĻŸāĻŋ āĻ°ā§‡āĻ•āĻ°ā§āĻĄā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻ˛ā§‡āĻŦā§‡āĻ˛ āĻ°āĻ¯āĻŧā§‡āĻ›ā§‡ āĻ¯āĻž āĻ¨āĻŋāĻ°ā§āĻĻā§‡āĻļ āĻ•āĻ°ā§‡ āĻ¯ā§‡ āĻĄā§‡āĻŸāĻžāĻ¸ā§‡āĻŸ āĻ¸āĻ‚āĻ—ā§āĻ°āĻšā§‡āĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻŦā§āĻ¯āĻŦāĻšā§ƒāĻ¤ āĻļā§āĻ°ā§‡āĻŖā§€āĻŦāĻŋāĻ­āĻžāĻ—āĻ•āĻžāĻ°ā§€āĻ° āĻĻā§āĻŦāĻžāĻ°āĻž āĻ›āĻŦāĻŋāĻŸāĻŋ āĻ¸āĻ āĻŋāĻ•āĻ­āĻžāĻŦā§‡ āĻ¸ā§āĻŦā§€āĻ•ā§ƒāĻ¤ āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛, āĻ›āĻŦāĻŋāĻ° āĻ˛ā§‡āĻ–āĻ•ā§‡āĻ° āĻŦāĻ¸āĻŦāĻžāĻ¸ā§‡āĻ° āĻĻā§‡āĻļā§‡āĻ° āĻāĻ•āĻŸāĻŋ āĻĻā§āĻ‡-āĻ…āĻ•ā§āĻˇāĻ°ā§‡āĻ° āĻ•ā§‹āĻĄ, āĻāĻ•āĻŸāĻŋ āĻ…āĻ¨āĻ¨ā§āĻ¯ āĻļāĻ¨āĻžāĻ•ā§āĻ¤āĻ•āĻžāĻ°ā§€, āĻāĻ•āĻŸāĻŋ āĻŸāĻžāĻ‡āĻŽāĻ¸ā§āĻŸā§āĻ¯āĻžāĻŽā§āĻĒ āĻāĻŦāĻ‚ āĻāĻ•āĻŸāĻŋ āĻļā§āĻ°ā§‡āĻŖā§€āĻ° āĻ¨āĻžāĻŽ āĻ¯āĻž āĻĢāĻžāĻ‡āĻ˛ā§‡āĻ° āĻ¨āĻžāĻŽā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻŽā§‡āĻ˛ā§‡āĨ¤ āĻŽā§‚āĻ˛ āĻĄā§‡āĻŸāĻžāĻ° āĻāĻ•āĻŸāĻŋ āĻ¸āĻ°āĻ˛ā§€āĻ•ā§ƒāĻ¤ āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖ āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖāĻžāĻ—āĻžāĻ°ā§‡ 7.4 āĻœāĻŋāĻŦāĻŋ āĻ“āĻœāĻ¨ā§‡āĻ° āĻāĻŦāĻ‚ āĻ†āĻ¨āĻĒā§āĻ¯āĻžāĻ• āĻ•āĻ°āĻžāĻ° āĻĒāĻ°ā§‡ āĻĒā§āĻ°āĻžāĻ¯āĻŧ 20 āĻœāĻŋāĻŦāĻŋ, āĻ†āĻ¨āĻĒā§āĻ¯āĻžāĻ• āĻ•āĻ°āĻžāĻ° āĻĒāĻ°ā§‡ āĻ¸āĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻĄā§‡āĻŸāĻž 240 āĻ—āĻŋāĻ—āĻžāĻŦāĻžāĻ‡āĻŸ āĻĒāĻ°ā§āĻ¯āĻ¨ā§āĻ¤ āĻ¨ā§‡āĻ¯āĻŧāĨ¤ āĻ†āĻ¯āĻŧā§‹āĻœāĻ•āĻ°āĻž āĻ¨āĻŋāĻļā§āĻšāĻŋāĻ¤ āĻ•āĻ°ā§‡āĻ›ā§‡āĻ¨ āĻ¯ā§‡ āĻ‰āĻ­āĻ¯āĻŧ āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖ āĻāĻ•āĻ‡ āĻ…āĻ™ā§āĻ•āĻ¨ āĻĒā§āĻ¨āĻ°ā§āĻ¤ā§āĻĒāĻžāĻĻāĻ¨ āĻ•āĻ°ā§‡āĻ›ā§‡, āĻ¯āĻžāĻ° āĻ…āĻ°ā§āĻĨ āĻ¸āĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖāĻŸāĻŋ āĻ…āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧ āĻ›āĻŋāĻ˛āĨ¤ āĻ¯āĻžāĻ‡ āĻšā§‹āĻ• āĻ¨āĻž āĻ•ā§‡āĻ¨, āĻ—ā§āĻ°āĻžāĻĢāĻŋāĻ• āĻĢāĻžāĻ‡āĻ˛ā§‡ āĻŦāĻž āĻ…ā§āĻ¯āĻžāĻ°ā§‡ āĻ†āĻ•āĻžāĻ°ā§‡ 50 āĻŽāĻŋāĻ˛āĻŋāĻ¯āĻŧāĻ¨ āĻ›āĻŦāĻŋ āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖ āĻ•āĻ°āĻž āĻ…āĻŦāĻŋāĻ˛āĻŽā§āĻŦā§‡ āĻ…āĻ˛āĻžāĻ­āĻœāĻ¨āĻ• āĻŦāĻ˛ā§‡ āĻŦāĻŋāĻŦā§‡āĻšāĻŋāĻ¤ āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛ āĻāĻŦāĻ‚ āĻ†āĻŽāĻ°āĻž āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖāĻžāĻ—āĻžāĻ° āĻĨā§‡āĻ•ā§‡ āĻ¸āĻŽāĻ¸ā§āĻ¤ CSV āĻĢāĻžāĻ‡āĻ˛ āĻāĻ•āĻ¤ā§āĻ°āĻŋāĻ¤ āĻ•āĻ°āĻžāĻ° āĻ¸āĻŋāĻĻā§āĻ§āĻžāĻ¨ā§āĻ¤ āĻ¨āĻŋāĻ¯āĻŧā§‡āĻ›āĻŋāĨ¤ train_simplified.zip āĻĒā§āĻ°āĻ¤āĻŋāĻŸāĻŋ āĻŦā§āĻ¯āĻžāĻšā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧ āĻ†āĻ•āĻžāĻ°ā§‡āĻ° āĻ›āĻŦāĻŋāĻ—ā§āĻ˛āĻŋāĻ° āĻĒāĻ°āĻŦāĻ°ā§āĻ¤ā§€ āĻĒā§āĻ°āĻœāĻ¨ā§āĻŽā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ā§‡ "āĻ‰āĻĄāĻŧāĻ˛ā§‡"āĨ¤

āĻāĻ•āĻŸāĻŋ āĻ­āĻžāĻ˛-āĻĒā§āĻ°āĻŽāĻžāĻŖāĻŋāĻ¤ āĻ¸āĻŋāĻ¸ā§āĻŸā§‡āĻŽ āĻĄāĻŋāĻŦāĻŋāĻāĻŽāĻāĻ¸ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻŦā§‡āĻ›ā§‡ āĻ¨ā§‡āĻ“āĻ¯āĻŧāĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛ MonetDB, āĻ¯ā§‡āĻŽāĻ¨ āĻāĻ•āĻŸāĻŋ āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ R āĻāĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ MonetDBLite. āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœāĻŸāĻŋāĻ¤ā§‡ āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ āĻ¸āĻžāĻ°ā§āĻ­āĻžāĻ°ā§‡āĻ° āĻāĻ•āĻŸāĻŋ āĻāĻŽāĻŦā§‡āĻĄā§‡āĻĄ āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖ āĻ°āĻ¯āĻŧā§‡āĻ›ā§‡ āĻāĻŦāĻ‚ āĻāĻŸāĻŋ āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻāĻ•āĻŸāĻŋ R āĻ¸ā§‡āĻļāĻ¨ āĻĨā§‡āĻ•ā§‡ āĻ¸āĻ°āĻžāĻ¸āĻ°āĻŋ āĻ¸āĻžāĻ°ā§āĻ­āĻžāĻ°āĻŸāĻŋ āĻ¨āĻŋāĻ¤ā§‡ āĻāĻŦāĻ‚ āĻ¸ā§‡āĻ–āĻžāĻ¨ā§‡ āĻāĻŸāĻŋāĻ° āĻ¸āĻžāĻĨā§‡ āĻ•āĻžāĻœ āĻ•āĻ°āĻ¤ā§‡ āĻĻā§‡āĻ¯āĻŧāĨ¤ āĻāĻ•āĻŸāĻŋ āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻž āĻāĻŦāĻ‚ āĻāĻŸāĻŋāĻ° āĻ¸āĻžāĻĨā§‡ āĻ¸āĻ‚āĻ¯ā§‹āĻ— āĻ•āĻ°āĻž āĻāĻ•āĻŸāĻŋ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻĻāĻŋāĻ¯āĻŧā§‡ āĻ¸āĻžā§āĻšāĻžāĻ˛āĻŋāĻ¤ āĻšāĻ¯āĻŧ:

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

āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻĻā§āĻŸāĻŋ āĻŸā§‡āĻŦāĻŋāĻ˛ āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻŦā§‡: āĻāĻ•āĻŸāĻŋ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻĄā§‡āĻŸāĻžāĻ° āĻœāĻ¨ā§āĻ¯, āĻ…āĻ¨ā§āĻ¯āĻŸāĻŋ āĻĄāĻžāĻ‰āĻ¨āĻ˛ā§‹āĻĄ āĻ•āĻ°āĻž āĻĢāĻžāĻ‡āĻ˛āĻ—ā§āĻ˛āĻŋāĻ° āĻĒāĻ°āĻŋāĻˇā§‡āĻŦāĻž āĻ¸āĻ‚āĻ•ā§āĻ°āĻžāĻ¨ā§āĻ¤ āĻ¤āĻĨā§āĻ¯ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ (āĻ•āĻŋāĻ›ā§ āĻ­ā§āĻ˛ āĻšāĻ˛ā§‡ āĻĻāĻ°āĻ•āĻžāĻ°ā§€ āĻāĻŦāĻ‚ āĻŦā§‡āĻļ āĻ•āĻ¯āĻŧā§‡āĻ•āĻŸāĻŋ āĻĢāĻžāĻ‡āĻ˛ āĻĄāĻžāĻ‰āĻ¨āĻ˛ā§‹āĻĄ āĻ•āĻ°āĻžāĻ° āĻĒāĻ°ā§‡ āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻŸāĻŋ āĻĒā§āĻ¨āĻ°āĻžāĻ¯āĻŧ āĻļā§āĻ°ā§ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻŦā§‡):

āĻŸā§‡āĻŦāĻŋāĻ˛ āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻž āĻšāĻšā§āĻ›ā§‡

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

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

āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ā§‡ āĻĄā§‡āĻŸāĻž āĻ˛ā§‹āĻĄ āĻ•āĻ°āĻžāĻ° āĻĻā§āĻ°ā§āĻ¤āĻ¤āĻŽ āĻ‰āĻĒāĻžāĻ¯āĻŧ āĻ›āĻŋāĻ˛ āĻāĻ¸āĻ•āĻŋāĻ‰āĻāĻ˛ - āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻ¸āĻ°āĻžāĻ¸āĻ°āĻŋ CSV āĻĢāĻžāĻ‡āĻ˛ āĻ•āĻĒāĻŋ āĻ•āĻ°āĻž COPY OFFSET 2 INTO tablename FROM path USING DELIMITERS ',','n','"' NULL AS '' BEST EFFORTāĻ¯ā§‡āĻ–āĻžāĻ¨ā§‡ tablename - āĻŸā§‡āĻŦāĻŋāĻ˛ā§‡āĻ° āĻ¨āĻžāĻŽ āĻāĻŦāĻ‚ path - āĻĢāĻžāĻ‡āĻ˛ā§‡āĻ° āĻĒāĻĨāĨ¤ āĻ†āĻ°ā§āĻ•āĻžāĻ‡āĻ­ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻ•āĻžāĻœ āĻ•āĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ, āĻāĻŸāĻŋ āĻŦāĻŋāĻ˛ā§āĻŸ-āĻ‡āĻ¨ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ†āĻŦāĻŋāĻˇā§āĻ•āĻžāĻ° āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛ unzip āĻ‡āĻ¨ R āĻ†āĻ°ā§āĻ•āĻžāĻ‡āĻ­ āĻĨā§‡āĻ•ā§‡ āĻ…āĻ¨ā§‡āĻ• āĻĢāĻžāĻ‡āĻ˛ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻ¸āĻ āĻŋāĻ•āĻ­āĻžāĻŦā§‡ āĻ•āĻžāĻœ āĻ•āĻ°ā§‡ āĻ¨āĻž, āĻ¤āĻžāĻ‡ āĻ†āĻŽāĻ°āĻž āĻ¸āĻŋāĻ¸ā§āĻŸā§‡āĻŽāĻŸāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡āĻ›āĻŋ unzip (āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻŸāĻžāĻ° āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ getOption("unzip")).

āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ā§‡ āĻ˛ā§‡āĻ–āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻĢāĻžāĻ‚āĻļāĻ¨

#' @title ИСвĐģĐĩŅ‡ĐĩĐŊиĐĩ и СаĐŗŅ€ŅƒĐˇĐēĐ° Ņ„Đ°ĐšĐģОв
#'
#' @description
#' ИСвĐģĐĩŅ‡ĐĩĐŊиĐĩ CSV-Ņ„Đ°ĐšĐģОв иС ZIP-Đ°Ņ€Ņ…ива и СаĐŗŅ€ŅƒĐˇĐēĐ° иŅ… в йаСŅƒ Đ´Đ°ĐŊĐŊŅ‹Ņ…
#'
#' @param con ОбŅŠĐĩĐēŅ‚ ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊиŅ Đē йаСĐĩ Đ´Đ°ĐŊĐŊŅ‹Ņ… (ĐēĐģĐ°ŅŅ `MonetDBEmbeddedConnection`).
#' @param tablename НазваĐŊиĐĩ Ņ‚Đ°ĐąĐģиŅ†Ņ‹ в йаСĐĩ Đ´Đ°ĐŊĐŊŅ‹Ņ….
#' @oaram zipfile ПŅƒŅ‚ŅŒ Đē ZIP-Đ°Ņ€Ņ…ивŅƒ.
#' @oaram filename ИĐŧŅ Ņ„Đ°ĐšĐģĐ° вĐŊŅƒŅ€Đ¸ ZIP-Đ°Ņ€Ņ…ива.
#' @param preprocess ФŅƒĐŊĐēŅ†Đ¸Ņ ĐŋŅ€ĐĩдОйŅ€Đ°ĐąĐžŅ‚Đēи, ĐēĐžŅ‚ĐžŅ€Đ°Ņ ĐąŅƒĐ´ĐĩŅ‚ ĐŋŅ€Đ¸ĐŧĐĩĐŊĐĩĐŊĐ° иСвĐģĐĩŅ‡Ņ‘ĐŊĐŊĐžĐŧŅƒ Ņ„Đ°ĐšĐģŅƒ.
#'   ДоĐģĐļĐŊĐ° ĐŋŅ€Đ¸ĐŊиĐŧĐ°Ņ‚ŅŒ ОдиĐŊ Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚ `data` (ОйŅŠĐĩĐēŅ‚ `data.table`).
#'
#' @return `TRUE`.
#'
upload_file <- function(con, tablename, zipfile, filename, preprocess = NULL) {
  # ПŅ€ĐžĐ˛ĐĩŅ€ĐēĐ° Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Ов
  checkmate::assert_class(con, "MonetDBEmbeddedConnection")
  checkmate::assert_string(tablename)
  checkmate::assert_string(filename)
  checkmate::assert_true(DBI::dbExistsTable(con, tablename))
  checkmate::assert_file_exists(zipfile, access = "r", extension = "zip")
  checkmate::assert_function(preprocess, args = c("data"), null.ok = TRUE)

  # ИСвĐģĐĩŅ‡ĐĩĐŊиĐĩ Ņ„Đ°ĐšĐģĐ°
  path <- file.path(tempdir(), filename)
  unzip(zipfile, files = filename, exdir = tempdir(), 
        junkpaths = TRUE, unzip = getOption("unzip"))
  on.exit(unlink(file.path(path)))

  # ПŅ€Đ¸ĐŧĐĩĐŊŅĐĩĐŧ Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ ĐŋŅ€ĐĩдОйŅ€Đ°ĐąĐžŅ‚Đēи
  if (!is.null(preprocess)) {
    .data <- data.table::fread(file = path)
    .data <- preprocess(data = .data)
    data.table::fwrite(x = .data, file = path, append = FALSE)
    rm(.data)
  }

  # ЗаĐŋŅ€ĐžŅ Đē БД ĐŊĐ° иĐŧĐŋĐžŅ€Ņ‚ CSV
  sql <- sprintf(
    "COPY OFFSET 2 INTO %s FROM '%s' USING DELIMITERS ',','n','"' NULL AS '' BEST EFFORT",
    tablename, path
  )
  # ВŅ‹ĐŋĐžĐģĐŊĐĩĐŊиĐĩ СаĐŋŅ€ĐžŅĐ° Đē БД
  DBI::dbExecute(con, sql)

  # ДобавĐģĐĩĐŊиĐĩ СаĐŋиŅĐ¸ Ой ŅƒŅĐŋĐĩŅˆĐŊОК СаĐŗŅ€ŅƒĐˇĐēĐĩ в ŅĐģŅƒĐļĐĩĐąĐŊŅƒŅŽ Ņ‚Đ°ĐąĐģиŅ†Ņƒ
  DBI::dbExecute(con, sprintf("INSERT INTO upload_log(file_name, uploaded) VALUES('%s', true)",
                              filename))

  return(invisible(TRUE))
}

āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ā§‡ āĻ˛ā§‡āĻ–āĻžāĻ° āĻ†āĻ—ā§‡ āĻŸā§‡āĻŦāĻŋāĻ˛āĻŸāĻŋāĻ•ā§‡ āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻ•āĻ°āĻ¤ā§‡ āĻšāĻ˛ā§‡, āĻ¯ā§āĻ•ā§āĻ¤āĻŋāĻ¤ā§‡ āĻĒāĻžāĻ¸ āĻ•āĻ°āĻžāĻ‡ āĻ¯āĻĨā§‡āĻˇā§āĻŸ preprocess āĻĢāĻžāĻ‚āĻļāĻ¨ āĻ¯āĻž āĻĄā§‡āĻŸāĻž āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ°āĻŋāĻ¤ āĻ•āĻ°āĻŦā§‡āĨ¤

āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ā§‡ āĻ•ā§āĻ°āĻŽāĻžāĻ¨ā§āĻ¸āĻžāĻ°ā§‡ āĻĄā§‡āĻŸāĻž āĻ˛ā§‹āĻĄ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ•ā§‹āĻĄ:

āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ā§‡ āĻ¤āĻĨā§āĻ¯ āĻ˛ā§‡āĻ–āĻž

# ĐĄĐŋиŅĐžĐē Ņ„Đ°ĐšĐģОв Đ´ĐģŅ СаĐŋиŅĐ¸
files <- unzip(zipfile, list = TRUE)$Name

# ĐĄĐŋиŅĐžĐē иŅĐēĐģŅŽŅ‡ĐĩĐŊиК, ĐĩŅĐģи Ņ‡Đ°ŅŅ‚ŅŒ Ņ„Đ°ĐšĐģОв ŅƒĐļĐĩ ĐąŅ‹ĐģĐ° СаĐŗŅ€ŅƒĐļĐĩĐŊĐ°
to_skip <- DBI::dbGetQuery(con, "SELECT file_name FROM upload_log")[[1L]]
files <- setdiff(files, to_skip)

if (length(files) > 0L) {
  # ЗаĐŋŅƒŅĐēĐ°ĐĩĐŧ Ņ‚Đ°ĐšĐŧĐĩŅ€
  tictoc::tic()
  # ПŅ€ĐžĐŗŅ€ĐĩŅŅ йаŅ€
  pb <- txtProgressBar(min = 0L, max = length(files), style = 3)
  for (i in seq_along(files)) {
    upload_file(con = con, tablename = "doodles", 
                zipfile = zipfile, filename = files[i])
    setTxtProgressBar(pb, i)
  }
  close(pb)
  # ОŅŅ‚Đ°ĐŊавĐģиваĐĩĐŧ Ņ‚Đ°ĐšĐŧĐĩŅ€
  tictoc::toc()
}

# 526.141 sec elapsed - ĐēĐžĐŋиŅ€ĐžĐ˛Đ°ĐŊиĐĩ SSD->SSD
# 558.879 sec elapsed - ĐēĐžĐŋиŅ€ĐžĐ˛Đ°ĐŊиĐĩ USB->SSD

āĻŦā§āĻ¯āĻŦāĻšā§ƒāĻ¤ āĻĄā§āĻ°āĻžāĻ‡āĻ­ā§‡āĻ° āĻ—āĻ¤āĻŋāĻ° āĻŦā§ˆāĻļāĻŋāĻˇā§āĻŸā§āĻ¯ā§‡āĻ° āĻ‰āĻĒāĻ° āĻ¨āĻŋāĻ°ā§āĻ­āĻ° āĻ•āĻ°ā§‡ āĻĄā§‡āĻŸāĻž āĻ˛ā§‹āĻĄāĻŋāĻ‚ āĻ¸āĻŽāĻ¯āĻŧ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻŋāĻ¤ āĻšāĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĨ¤ āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ•ā§āĻˇā§‡āĻ¤ā§āĻ°ā§‡, āĻāĻ•āĻŸāĻŋ SSD-āĻāĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻŦāĻž āĻāĻ•āĻŸāĻŋ āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ āĻĄā§āĻ°āĻžāĻ‡āĻ­ (āĻ¸ā§‹āĻ°ā§āĻ¸ āĻĢāĻžāĻ‡āĻ˛) āĻĨā§‡āĻ•ā§‡ SSD (DB) āĻĒāĻĄāĻŧāĻ¤ā§‡ āĻāĻŦāĻ‚ āĻ˛āĻŋāĻ–āĻ¤ā§‡ 10 āĻŽāĻŋāĻ¨āĻŋāĻŸā§‡āĻ°āĻ“ āĻ•āĻŽ āĻ¸āĻŽāĻ¯āĻŧ āĻ˛āĻžāĻ—ā§‡ā§ˇ

āĻāĻ•āĻŸāĻŋ āĻĒā§‚āĻ°ā§āĻŖāĻ¸āĻ‚āĻ–ā§āĻ¯āĻž āĻļā§āĻ°ā§‡āĻŖā§€āĻ° āĻ˛ā§‡āĻŦā§‡āĻ˛ āĻāĻŦāĻ‚ āĻāĻ•āĻŸāĻŋ āĻ¸ā§‚āĻšāĻ• āĻ•āĻ˛āĻžāĻŽ āĻ¸āĻš āĻāĻ•āĻŸāĻŋ āĻ•āĻ˛āĻžāĻŽ āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻ¤ā§‡ āĻ†āĻ°āĻ“ āĻ•āĻ¯āĻŧā§‡āĻ• āĻ¸ā§‡āĻ•ā§‡āĻ¨ā§āĻĄ āĻ¸āĻŽāĻ¯āĻŧ āĻ˛āĻžāĻ—ā§‡ (ORDERED INDEX) āĻ˛āĻžāĻ‡āĻ¨ āĻ¨āĻŽā§āĻŦāĻ° āĻ¸āĻš āĻ¯āĻžāĻ° āĻĻā§āĻŦāĻžāĻ°āĻž āĻŦā§āĻ¯āĻžāĻš āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻĒāĻ°ā§āĻ¯āĻŦā§‡āĻ•ā§āĻˇāĻŖāĻ—ā§āĻ˛āĻŋ āĻ¨āĻŽā§āĻ¨āĻž āĻ•āĻ°āĻž āĻšāĻŦā§‡:

āĻ…āĻ¤āĻŋāĻ°āĻŋāĻ•ā§āĻ¤ āĻ•āĻ˛āĻžāĻŽ āĻāĻŦāĻ‚ āĻ¸ā§‚āĻšāĻ• āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻž

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

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

āĻĢā§āĻ˛āĻžāĻ‡āĻ¤ā§‡ āĻāĻ•āĻŸāĻŋ āĻŦā§āĻ¯āĻžāĻš āĻ¤ā§ˆāĻ°āĻŋāĻ° āĻ¸āĻŽāĻ¸ā§āĻ¯āĻž āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ā§‡āĻ° āĻœāĻ¨ā§āĻ¯, āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻŸā§‡āĻŦāĻŋāĻ˛ āĻĨā§‡āĻ•ā§‡ āĻāĻ˛ā§‹āĻŽā§‡āĻ˛ā§‹ āĻ¸āĻžāĻ°āĻŋ āĻŦā§‡āĻ° āĻ•āĻ°āĻžāĻ° āĻ¸āĻ°ā§āĻŦā§‹āĻšā§āĻš āĻ—āĻ¤āĻŋ āĻ…āĻ°ā§āĻœāĻ¨ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻŦā§‡ doodles. āĻāĻ° āĻœāĻ¨ā§āĻ¯ āĻ†āĻŽāĻ°āĻž 3āĻŸāĻŋ āĻ•ā§ŒāĻļāĻ˛ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡āĻ›āĻŋāĨ¤ āĻĒā§āĻ°āĻĨāĻŽāĻŸāĻŋ āĻ›āĻŋāĻ˛ āĻĒāĻ°ā§āĻ¯āĻŦā§‡āĻ•ā§āĻˇāĻŖ āĻ†āĻ‡āĻĄāĻŋ āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖ āĻ•āĻ°ā§‡ āĻāĻŽāĻ¨ āĻ§āĻ°āĻ¨ā§‡āĻ° āĻŽāĻžāĻ¤ā§āĻ°āĻžāĻ° āĻŽāĻžāĻ¤ā§āĻ°āĻž āĻ•āĻŽāĻžāĻ¨ā§‹āĨ¤ āĻ†āĻ¸āĻ˛ āĻĄā§‡āĻŸāĻž āĻ¸ā§‡āĻŸā§‡, āĻ†āĻ‡āĻĄāĻŋ āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧ āĻĒā§āĻ°āĻ•āĻžāĻ° bigint, āĻ•āĻŋāĻ¨ā§āĻ¤ā§ āĻĒāĻ°ā§āĻ¯āĻŦā§‡āĻ•ā§āĻˇāĻŖā§‡āĻ° āĻ¸āĻ‚āĻ–ā§āĻ¯āĻž āĻ¤āĻžāĻĻā§‡āĻ° āĻļāĻ¨āĻžāĻ•ā§āĻ¤āĻ•āĻžāĻ°ā§€āĻ•ā§‡, āĻ…āĻ°ā§āĻĄāĻŋāĻ¨ā§āĻ¯āĻžāĻ˛ āĻ¸āĻ‚āĻ–ā§āĻ¯āĻžāĻ° āĻ¸āĻŽāĻžāĻ¨, āĻĒā§āĻ°āĻ•āĻžāĻ°ā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻŽāĻžāĻĒāĻ¸āĻ‡ āĻ•āĻ°āĻž āĻ¸āĻŽā§āĻ­āĻŦ āĻ•āĻ°ā§‡ āĻ¤ā§‹āĻ˛ā§‡ int. āĻāĻ‡ āĻ•ā§āĻˇā§‡āĻ¤ā§āĻ°ā§‡ āĻ…āĻ¨ā§āĻ¸āĻ¨ā§āĻ§āĻžāĻ¨ āĻ…āĻ¨ā§‡āĻ• āĻĻā§āĻ°ā§āĻ¤āĨ¤ āĻĻā§āĻŦāĻŋāĻ¤ā§€āĻ¯āĻŧ āĻ•ā§ŒāĻļāĻ˛āĻŸāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛ ORDERED INDEX — āĻ†āĻŽāĻ°āĻž āĻāĻ‡ āĻ¸āĻŋāĻĻā§āĻ§āĻžāĻ¨ā§āĻ¤ā§‡ āĻāĻ¸ā§‡āĻ›āĻŋ āĻ…āĻ­āĻŋāĻœā§āĻžāĻ¤āĻžāĻ—āĻ¤āĻ­āĻžāĻŦā§‡, āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻ‰āĻĒāĻ˛āĻŦā§āĻ§ā§‡āĻ° āĻŽāĻ§ā§āĻ¯ āĻĻāĻŋāĻ¯āĻŧā§‡ āĻšāĻ˛ā§‡āĻ›āĻŋ āĻ…āĻĒāĻļāĻ¨. āĻ¤ā§ƒāĻ¤ā§€āĻ¯āĻŧāĻŸāĻŋ āĻ›āĻŋāĻ˛ āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻŸāĻžāĻ°āĻžāĻ‡āĻœāĻĄ āĻĒā§āĻ°āĻļā§āĻ¨ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻžāĨ¤ āĻĒāĻĻā§āĻ§āĻ¤āĻŋāĻ° āĻ¸āĻžāĻ°āĻŽāĻ°ā§āĻŽ āĻšāĻ˛ āĻ•āĻŽāĻžāĻ¨ā§āĻĄāĻŸāĻŋ āĻāĻ•āĻŦāĻžāĻ° āĻ•āĻžāĻ°ā§āĻ¯āĻ•āĻ° āĻ•āĻ°āĻž PREPARE āĻāĻ•āĻ‡ āĻ§āĻ°āĻŖā§‡āĻ° āĻĒā§āĻ°āĻļā§āĻ¨ā§‡āĻ° āĻāĻ•āĻŸāĻŋ āĻ—ā§āĻšā§āĻ› āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻāĻ•āĻŸāĻŋ āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤ āĻ…āĻ­āĻŋāĻŦā§āĻ¯āĻ•ā§āĻ¤āĻŋāĻ° āĻĒāĻ°āĻŦāĻ°ā§āĻ¤ā§€ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°ā§‡āĻ° āĻ¸āĻžāĻĨā§‡, āĻ•āĻŋāĻ¨ā§āĻ¤ā§ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦā§‡ āĻāĻ•āĻŸāĻŋ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻ¤ā§āĻ˛āĻ¨āĻž āĻ•āĻ°āĻžāĻ° āĻ•ā§āĻˇā§‡āĻ¤ā§āĻ°ā§‡ āĻāĻ•āĻŸāĻŋ āĻ¸ā§āĻŦāĻŋāĻ§āĻž āĻ°āĻ¯āĻŧā§‡āĻ›ā§‡ SELECT āĻĒāĻ°āĻŋāĻ¸āĻ‚āĻ–ā§āĻ¯āĻžāĻ¨āĻ—āĻ¤ āĻ¤ā§āĻ°ā§āĻŸāĻŋāĻ° āĻ¸ā§€āĻŽāĻžāĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻĒāĻ°āĻŋāĻŖāĻ¤ āĻšāĻ¯āĻŧā§‡āĻ›ā§‡āĨ¤

āĻĄā§‡āĻŸāĻž āĻ†āĻĒāĻ˛ā§‹āĻĄ āĻ•āĻ°āĻžāĻ° āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻŸāĻŋ 450 MB āĻāĻ° āĻŦā§‡āĻļāĻŋ RAM āĻ–āĻ°āĻš āĻ•āĻ°ā§‡ āĻ¨āĻžāĨ¤ āĻ…āĻ°ā§āĻĨāĻžā§Ž, āĻŦāĻ°ā§āĻŖāĻŋāĻ¤ āĻĒāĻĻā§āĻ§āĻ¤āĻŋāĻ° āĻ¸āĻžāĻšāĻžāĻ¯ā§āĻ¯ā§‡ āĻ†āĻĒāĻ¨āĻŋ āĻĒā§āĻ°āĻžāĻ¯āĻŧ āĻ¯ā§‡āĻ•ā§‹āĻ¨ā§‹ āĻŦāĻžāĻœā§‡āĻŸ āĻšāĻžāĻ°ā§āĻĄāĻ“āĻ¯āĻŧā§āĻ¯āĻžāĻ°ā§‡ āĻĻāĻļ āĻ—āĻŋāĻ—āĻžāĻŦāĻžāĻ‡āĻŸ āĻ“āĻœāĻ¨ā§‡āĻ° āĻĄā§‡āĻŸāĻžāĻ¸ā§‡āĻŸāĻ—ā§āĻ˛āĻŋāĻ•ā§‡ āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ¨ā§āĻ¤āĻ° āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°āĻŦā§‡āĻ¨, āĻ¯āĻžāĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻ•āĻŋāĻ›ā§ āĻāĻ•āĻ•-āĻŦā§‹āĻ°ā§āĻĄ āĻĄāĻŋāĻ­āĻžāĻ‡āĻ¸ āĻ°āĻ¯āĻŧā§‡āĻ›ā§‡, āĻ¯āĻž āĻŦā§‡āĻļ āĻšāĻŽā§ŽāĻ•āĻžāĻ°āĨ¤

āĻ¯āĻž āĻŦāĻžāĻ•āĻŋ āĻĨāĻžāĻ•ā§‡ āĻ¤āĻž āĻšāĻ˛ (āĻāĻ˛ā§‹āĻŽā§‡āĻ˛ā§‹) āĻĄā§‡āĻŸāĻž āĻĒā§āĻ¨āĻ°ā§āĻĻā§āĻ§āĻžāĻ°ā§‡āĻ° āĻ—āĻ¤āĻŋ āĻĒāĻ°āĻŋāĻŽāĻžāĻĒ āĻ•āĻ°āĻž āĻāĻŦāĻ‚ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āĻ¨ āĻ†āĻ•āĻžāĻ°ā§‡āĻ° āĻŦā§āĻ¯āĻžāĻšā§‡āĻ° āĻ¨āĻŽā§āĻ¨āĻž āĻ¨ā§‡āĻ“āĻ¯āĻŧāĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻ¸ā§āĻ•ā§‡āĻ˛āĻŋāĻ‚ āĻŽā§‚āĻ˛ā§āĻ¯āĻžāĻ¯āĻŧāĻ¨ āĻ•āĻ°āĻž:

āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ āĻŦā§‡āĻžā§āĻšāĻŽāĻžāĻ°ā§āĻ•

library(ggplot2)

set.seed(0)
# ПодĐēĐģŅŽŅ‡ĐĩĐŊиĐĩ Đē йаСĐĩ Đ´Đ°ĐŊĐŊŅ‹Ņ…
con <- DBI::dbConnect(MonetDBLite::MonetDBLite(), Sys.getenv("DBDIR"))

# ФŅƒĐŊĐēŅ†Đ¸Ņ Đ´ĐģŅ ĐŋОдĐŗĐžŅ‚ОвĐēи СаĐŋŅ€ĐžŅĐ° ĐŊĐ° ŅŅ‚ĐžŅ€ĐžĐŊĐĩ ŅĐĩŅ€Đ˛ĐĩŅ€Đ°
prep_sql <- function(batch_size) {
  sql <- sprintf("PREPARE SELECT id FROM doodles WHERE id IN (%s)",
                 paste(rep("?", batch_size), collapse = ","))
  res <- DBI::dbSendQuery(con, sql)
  return(res)
}

# ФŅƒĐŊĐēŅ†Đ¸Ņ Đ´ĐģŅ иСвĐģĐĩŅ‡ĐĩĐŊиŅ Đ´Đ°ĐŊĐŊŅ‹Ņ…
fetch_data <- function(rs, batch_size) {
  ids <- sample(seq_len(n), batch_size)
  res <- DBI::dbFetch(DBI::dbBind(rs, as.list(ids)))
  return(res)
}

# ПŅ€ĐžĐ˛ĐĩĐ´ĐĩĐŊиĐĩ СаĐŧĐĩŅ€Đ°
res_bench <- bench::press(
  batch_size = 2^(4:10),
  {
    rs <- prep_sql(batch_size)
    bench::mark(
      fetch_data(rs, batch_size),
      min_iterations = 50L
    )
  }
)
# ПаŅ€Đ°ĐŧĐĩŅ‚Ņ€Ņ‹ ĐąĐĩĐŊŅ‡ĐŧĐ°Ņ€ĐēĐ°
cols <- c("batch_size", "min", "median", "max", "itr/sec", "total_time", "n_itr")
res_bench[, cols]

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

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

DBI::dbDisconnect(con, shutdown = TRUE)

āĻ•ā§āĻ‡āĻ• āĻĄā§āĻ° āĻĄā§āĻĄāĻ˛ āĻ¸ā§āĻŦā§€āĻ•ā§ƒāĻ¤āĻŋ: āĻ•āĻŋāĻ­āĻžāĻŦā§‡ R, C++ āĻāĻŦāĻ‚ āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻŦāĻ¨ā§āĻ§ā§āĻ¤ā§āĻŦ āĻ•āĻ°āĻž āĻ¯āĻžāĻ¯āĻŧ

2. āĻŦā§āĻ¯āĻžāĻš āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤āĻŋ

āĻ¸āĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻŦā§āĻ¯āĻžāĻš āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤āĻŋ āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¨āĻŋāĻŽā§āĻ¨āĻ˛āĻŋāĻ–āĻŋāĻ¤ āĻĒāĻĻāĻ•ā§āĻˇā§‡āĻĒ āĻ¨āĻŋāĻ¯āĻŧā§‡ āĻ—āĻ āĻŋāĻ¤:

  1. āĻŦāĻŋāĻ¨ā§āĻĻā§āĻ° āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ™ā§āĻ• āĻ¸āĻš āĻ¸ā§āĻŸā§āĻ°āĻŋāĻ‚āĻ—ā§āĻ˛āĻŋāĻ° āĻ­ā§‡āĻ•ā§āĻŸāĻ° āĻ§āĻžāĻ°āĻŖāĻ•āĻžāĻ°ā§€ āĻŦā§‡āĻļ āĻ•āĻ¯āĻŧā§‡āĻ•āĻŸāĻŋ JSON āĻĒāĻžāĻ°ā§āĻ¸ āĻ•āĻ°āĻž āĻšāĻšā§āĻ›ā§‡āĨ¤
  2. āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧ āĻ†āĻ•āĻžāĻ°ā§‡āĻ° āĻāĻ•āĻŸāĻŋ āĻšāĻŋāĻ¤ā§āĻ°ā§‡āĻ° āĻŦāĻŋāĻ¨ā§āĻĻā§āĻ—ā§āĻ˛āĻŋāĻ° āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ™ā§āĻ•ā§‡āĻ° āĻ‰āĻĒāĻ° āĻ­āĻŋāĻ¤ā§āĻ¤āĻŋ āĻ•āĻ°ā§‡ āĻ°āĻ™āĻŋāĻ¨ āĻ˛āĻžāĻ‡āĻ¨ āĻ†āĻāĻ•āĻž (āĻ‰āĻĻāĻžāĻšāĻ°āĻŖāĻ¸ā§āĻŦāĻ°ā§‚āĻĒ, 256×256 āĻŦāĻž 128×128)āĨ¤
  3. āĻĢāĻ˛āĻ¸ā§āĻŦāĻ°ā§‚āĻĒ āĻšāĻŋāĻ¤ā§āĻ°āĻ—ā§āĻ˛āĻŋāĻ•ā§‡ āĻāĻ•āĻŸāĻŋ āĻŸā§‡āĻ¨āĻ¸āĻ°ā§‡ āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻ•āĻ°āĻž āĻšāĻšā§āĻ›ā§‡āĨ¤

āĻĒāĻžāĻ‡āĻĨāĻ¨ āĻ•āĻžāĻ°ā§āĻ¨ā§‡āĻ˛ā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻĒā§āĻ°āĻ¤āĻŋāĻ¯ā§‹āĻ—āĻŋāĻ¤āĻžāĻ° āĻ…āĻ‚āĻļ āĻšāĻŋāĻ¸āĻžāĻŦā§‡, āĻ¸āĻŽāĻ¸ā§āĻ¯āĻžāĻŸāĻŋ āĻĒā§āĻ°āĻžāĻĨāĻŽāĻŋāĻ•āĻ­āĻžāĻŦā§‡ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛ OpenCV. R-āĻāĻ° āĻ¸āĻŦāĻšā§‡āĻ¯āĻŧā§‡ āĻ¸āĻšāĻœ āĻāĻŦāĻ‚ āĻ¸āĻŦāĻšā§‡āĻ¯āĻŧā§‡ āĻ¸ā§āĻ¸ā§āĻĒāĻˇā§āĻŸ āĻ…ā§āĻ¯āĻžāĻ¨āĻžāĻ˛āĻ—āĻ—ā§āĻ˛āĻŋāĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻāĻ•āĻŸāĻŋ āĻĻā§‡āĻ–āĻ¤ā§‡ āĻāĻ‡āĻ°āĻ•āĻŽ āĻšāĻŦā§‡:

R-āĻ JSON āĻĨā§‡āĻ•ā§‡ āĻŸā§‡āĻ¨āĻ¸āĻ° āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ•āĻ°āĻž

r_process_json_str <- function(json, line.width = 3, 
                               color = TRUE, scale = 1) {
  # ПаŅ€ŅĐ¸ĐŊĐŗ JSON
  coords <- jsonlite::fromJSON(json, simplifyMatrix = FALSE)
  tmp <- tempfile()
  # ĐŖĐ´Đ°ĐģŅĐĩĐŧ вŅ€ĐĩĐŧĐĩĐŊĐŊŅ‹Đš Ņ„Đ°ĐšĐģ ĐŋĐž СавĐĩŅ€ŅˆĐĩĐŊиŅŽ Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸
  on.exit(unlink(tmp))
  png(filename = tmp, width = 256 * scale, height = 256 * scale, pointsize = 1)
  # ПŅƒŅŅ‚ОК ĐŗŅ€Đ°Ņ„иĐē
  plot.new()
  # РаСĐŧĐĩŅ€ ĐžĐēĐŊĐ° ĐŗŅ€Đ°Ņ„иĐēĐ°
  plot.window(xlim = c(256 * scale, 0), ylim = c(256 * scale, 0))
  # ĐĻвĐĩŅ‚Đ° ĐģиĐŊиК
  cols <- if (color) rainbow(length(coords)) else "#000000"
  for (i in seq_along(coords)) {
    lines(x = coords[[i]][[1]] * scale, y = coords[[i]][[2]] * scale, 
          col = cols[i], lwd = line.width)
  }
  dev.off()
  # ПŅ€ĐĩОйŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊиĐĩ иСОйŅ€Đ°ĐļĐĩĐŊиŅ в 3-Ņ… ĐŧĐĩŅ€ĐŊŅ‹Đš ĐŧĐ°ŅŅĐ¸Đ˛
  res <- png::readPNG(tmp)
  return(res)
}

r_process_json_vector <- function(x, ...) {
  res <- lapply(x, r_process_json_str, ...)
  # ОбŅŠĐĩдиĐŊĐĩĐŊиĐĩ 3-Ņ… ĐŧĐĩŅ€ĐŊŅ‹Ņ… ĐŧĐ°ŅŅĐ¸Đ˛ĐžĐ˛ ĐēĐ°Ņ€Ņ‚иĐŊĐžĐē в 4-Ņ… ĐŧĐĩŅ€ĐŊŅ‹Đš в Ņ‚ĐĩĐŊСОŅ€
  res <- do.call(abind::abind, c(res, along = 0))
  return(res)
}

āĻĄā§āĻ°āĻ¯āĻŧāĻŋāĻ‚ āĻ¸ā§āĻŸā§āĻ¯āĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ R āĻŸā§āĻ˛ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻ¸āĻžā§āĻšāĻžāĻ˛āĻŋāĻ¤ āĻšāĻ¯āĻŧ āĻāĻŦāĻ‚ RAM-āĻ¤ā§‡ āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŋāĻ¤ āĻāĻ•āĻŸāĻŋ āĻ…āĻ¸ā§āĻĨāĻžāĻ¯āĻŧā§€ PNG-āĻ¤ā§‡ āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŋāĻ¤ āĻšāĻ¯āĻŧ (āĻ˛āĻŋāĻ¨āĻžāĻ•ā§āĻ¸ā§‡, āĻ…āĻ¸ā§āĻĨāĻžāĻ¯āĻŧā§€ R āĻĄāĻŋāĻ°ā§‡āĻ•ā§āĻŸāĻ°āĻŋāĻ—ā§āĻ˛āĻŋ āĻĄāĻŋāĻ°ā§‡āĻ•ā§āĻŸāĻ°āĻŋāĻ¤ā§‡ āĻ…āĻŦāĻ¸ā§āĻĨāĻŋāĻ¤āĨ¤ /tmp, RAM āĻ āĻŽāĻžāĻ‰āĻ¨ā§āĻŸ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›ā§‡)āĨ¤ āĻāĻ‡ āĻĢāĻžāĻ‡āĻ˛āĻŸāĻŋ āĻ¤āĻžāĻ°āĻĒāĻ° 0 āĻĨā§‡āĻ•ā§‡ 1 āĻĒāĻ°ā§āĻ¯āĻ¨ā§āĻ¤ āĻ¸āĻ‚āĻ–ā§āĻ¯āĻž āĻ¸āĻš āĻāĻ•āĻŸāĻŋ āĻ¤ā§āĻ°āĻŋāĻŽāĻžāĻ¤ā§āĻ°āĻŋāĻ• āĻ…ā§āĻ¯āĻžāĻ°ā§‡ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻĒāĻĄāĻŧāĻž āĻšāĻ¯āĻŧā§ˇ āĻāĻŸāĻŋ āĻ—ā§āĻ°ā§āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ āĻ•āĻžāĻ°āĻŖ āĻāĻ•āĻŸāĻŋ āĻ†āĻ°āĻ“ āĻĒā§āĻ°āĻšāĻ˛āĻŋāĻ¤ BMP āĻšā§‡āĻ•ā§āĻ¸ āĻ°āĻ™ā§‡āĻ° āĻ•ā§‹āĻĄ āĻ¸āĻš āĻāĻ•āĻŸāĻŋ āĻ•āĻžāĻāĻšāĻž āĻ…ā§āĻ¯āĻžāĻ°ā§‡āĻ¤ā§‡ āĻĒāĻĄāĻŧāĻž āĻšāĻŦā§‡ā§ˇ

āĻ†āĻ¸ā§āĻ¨ āĻĢāĻ˛āĻžāĻĢāĻ˛ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž āĻ•āĻ°āĻž āĻ¯āĻžāĻ•:

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

āĻ•ā§āĻ‡āĻ• āĻĄā§āĻ° āĻĄā§āĻĄāĻ˛ āĻ¸ā§āĻŦā§€āĻ•ā§ƒāĻ¤āĻŋ: āĻ•āĻŋāĻ­āĻžāĻŦā§‡ R, C++ āĻāĻŦāĻ‚ āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻŦāĻ¨ā§āĻ§ā§āĻ¤ā§āĻŦ āĻ•āĻ°āĻž āĻ¯āĻžāĻ¯āĻŧ

āĻŦā§āĻ¯āĻžāĻš āĻ¨āĻŋāĻœā§‡āĻ‡ āĻ¨āĻŋāĻŽā§āĻ¨āĻ˛āĻŋāĻ–āĻŋāĻ¤ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻ—āĻ āĻŋāĻ¤ āĻšāĻŦā§‡:

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

āĻāĻ‡ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨āĻŸāĻŋ āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ•āĻžāĻ›ā§‡ āĻ¸āĻ°ā§āĻŦā§‹āĻ¤ā§āĻ¤āĻŽ āĻŦāĻ˛ā§‡ āĻŽāĻ¨ā§‡ āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛, āĻ¯ā§‡āĻšā§‡āĻ¤ā§ āĻŦāĻĄāĻŧ āĻŦā§āĻ¯āĻžāĻš āĻ—āĻ āĻ¨ā§‡ āĻāĻ•āĻŸāĻŋ āĻ…āĻļāĻžāĻ˛ā§€āĻ¨āĻ­āĻžāĻŦā§‡ āĻĻā§€āĻ°ā§āĻ˜ āĻ¸āĻŽāĻ¯āĻŧ āĻ˛āĻžāĻ—ā§‡ āĻāĻŦāĻ‚ āĻ†āĻŽāĻ°āĻž āĻāĻ•āĻŸāĻŋ āĻļāĻ•ā§āĻ¤āĻŋāĻļāĻžāĻ˛ā§€ āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ¸āĻšāĻ•āĻ°ā§āĻŽā§€āĻĻā§‡āĻ° āĻ…āĻ­āĻŋāĻœā§āĻžāĻ¤āĻžāĻ° āĻ¸ā§āĻŦāĻŋāĻ§āĻž āĻ¨ā§‡āĻ“āĻ¯āĻŧāĻžāĻ° āĻ¸āĻŋāĻĻā§āĻ§āĻžāĻ¨ā§āĻ¤ āĻ¨āĻŋāĻ¯āĻŧā§‡āĻ›āĻŋāĨ¤ OpenCV. āĻ¸ā§‡āĻ‡ āĻ¸āĻŽāĻ¯āĻŧā§‡ R-āĻāĻ° āĻœāĻ¨ā§āĻ¯ āĻ•ā§‹āĻ¨āĻ“ āĻ°ā§‡āĻĄāĻŋāĻŽā§‡āĻĄ āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ āĻ›āĻŋāĻ˛ āĻ¨āĻž (āĻāĻ–āĻ¨ āĻ¨ā§‡āĻ‡), āĻ¤āĻžāĻ‡ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧ āĻ•āĻžāĻ°ā§āĻ¯āĻ•āĻžāĻ°āĻŋāĻ¤āĻžāĻ° āĻāĻ•āĻŸāĻŋ āĻ¨ā§āĻ¯ā§‚āĻ¨āĻ¤āĻŽ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ C++ āĻ āĻ˛ā§‡āĻ–āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛ R āĻ•ā§‹āĻĄ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻāĻ•ā§€āĻ•āĻ°āĻŖā§‡āĻ° āĻ¸āĻžāĻĨā§‡ Rcpp.

āĻ¸āĻŽāĻ¸ā§āĻ¯āĻž āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ā§‡āĻ° āĻœāĻ¨ā§āĻ¯, āĻ¨āĻŋāĻŽā§āĻ¨āĻ˛āĻŋāĻ–āĻŋāĻ¤ āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ āĻāĻŦāĻ‚ āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛:

  1. OpenCV āĻ‡āĻŽā§‡āĻœ āĻāĻŦāĻ‚ āĻ…āĻ™ā§āĻ•āĻ¨ āĻ˛āĻžāĻ‡āĻ¨ āĻ¸āĻ™ā§āĻ—ā§‡ āĻ•āĻžāĻœ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯. āĻŦā§āĻ¯āĻŦāĻšā§ƒāĻ¤ āĻĒā§āĻ°āĻŋ-āĻ‡āĻ¨āĻ¸ā§āĻŸāĻ˛ āĻ•āĻ°āĻž āĻ¸āĻŋāĻ¸ā§āĻŸā§‡āĻŽ āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋ āĻāĻŦāĻ‚ āĻšā§‡āĻĄāĻžāĻ° āĻĢāĻžāĻ‡āĻ˛, āĻ¸ā§‡āĻ‡āĻ¸āĻžāĻĨā§‡ āĻĄāĻžāĻ‡āĻ¨āĻžāĻŽāĻŋāĻ• āĻ˛āĻŋāĻ™ā§āĻ•āĻŋāĻ‚āĨ¤

  2. āĻāĻ•ā§āĻ¸āĻŸā§‡āĻ¨āĻ¸āĻ° āĻŦāĻšā§āĻŽāĻžāĻ¤ā§āĻ°āĻŋāĻ• āĻ…ā§āĻ¯āĻžāĻ°ā§‡ āĻāĻŦāĻ‚ āĻŸā§‡āĻ¨āĻ¸āĻ°ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻ•āĻžāĻœ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯āĨ¤ āĻ†āĻŽāĻ°āĻž āĻāĻ•āĻ‡ āĻ¨āĻžāĻŽā§‡āĻ° R āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœā§‡ āĻ…āĻ¨ā§āĻ¤āĻ°ā§āĻ­ā§āĻ•ā§āĻ¤ āĻšā§‡āĻĄāĻžāĻ° āĻĢāĻžāĻ‡āĻ˛ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡āĻ›āĻŋāĨ¤ āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋ āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻŦāĻšā§āĻŽāĻžāĻ¤ā§āĻ°āĻŋāĻ• āĻ…ā§āĻ¯āĻžāĻ°ā§‡āĻ—ā§āĻ˛āĻŋāĻ° āĻ¸āĻžāĻĨā§‡ āĻ•āĻžāĻœ āĻ•āĻ°āĻ¤ā§‡ āĻĻā§‡āĻ¯āĻŧ, āĻ‰āĻ­āĻ¯āĻŧ āĻ¸āĻžāĻ°āĻŋ āĻĒā§āĻ°āĻ§āĻžāĻ¨ āĻāĻŦāĻ‚ āĻ•āĻ˛āĻžāĻŽ āĻĒā§āĻ°āĻ§āĻžāĻ¨ āĻ•ā§āĻ°āĻŽā§‡āĨ¤

  3. ndjson JSON āĻĒāĻžāĻ°ā§āĻ¸ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯āĨ¤ āĻāĻ‡ āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž āĻšāĻ¯āĻŧ āĻāĻ•ā§āĻ¸āĻŸā§‡āĻ¨āĻ¸āĻ° āĻ¸ā§āĻŦāĻ¯āĻŧāĻ‚āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻ­āĻžāĻŦā§‡ āĻ¯āĻĻāĻŋ āĻāĻŸāĻŋ āĻĒā§āĻ°āĻ•āĻ˛ā§āĻĒā§‡ āĻ‰āĻĒāĻ¸ā§āĻĨāĻŋāĻ¤ āĻĨāĻžāĻ•ā§‡āĨ¤

  4. RcppThread JSON āĻĨā§‡āĻ•ā§‡ āĻāĻ•āĻŸāĻŋ āĻ­ā§‡āĻ•ā§āĻŸāĻ°ā§‡āĻ° āĻŽāĻžāĻ˛ā§āĻŸāĻŋ-āĻĨā§āĻ°ā§‡āĻĄā§‡āĻĄ āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ•āĻ°āĻŖ āĻ¸āĻ‚āĻ—āĻ āĻŋāĻ¤ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯āĨ¤ āĻāĻ‡ āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ āĻĻā§āĻŦāĻžāĻ°āĻž āĻĒā§āĻ°āĻĻāĻ¤ā§āĻ¤ āĻšā§‡āĻĄāĻžāĻ° āĻĢāĻžāĻ‡āĻ˛ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›ā§‡. āĻ†āĻ°ā§‹ āĻœāĻ¨āĻĒā§āĻ°āĻŋāĻ¯āĻŧ āĻĨā§‡āĻ•ā§‡ Rcpp āĻ¸āĻŽāĻžāĻ¨ā§āĻ¤āĻ°āĻžāĻ˛ āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ, āĻ…āĻ¨ā§āĻ¯āĻžāĻ¨ā§āĻ¯ āĻœāĻŋāĻ¨āĻŋāĻ¸ā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡, āĻāĻ•āĻŸāĻŋ āĻ…āĻ¨ā§āĻ¤āĻ°ā§āĻ¨āĻŋāĻ°ā§āĻŽāĻŋāĻ¤ āĻ˛ā§āĻĒ āĻŦāĻžāĻ§āĻž āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ†āĻ›ā§‡āĨ¤

āĻāĻŸāĻŋ āĻ¯ā§‡ āĻŽā§‚āĻ˛ā§āĻ¯āĻŦāĻžāĻ¨ āĻāĻ•ā§āĻ¸āĻŸā§‡āĻ¨āĻ¸āĻ° āĻāĻŸāĻŋ āĻāĻ•āĻŸāĻŋ āĻ—āĻĄāĻ¸ā§‡āĻ¨ā§āĻĄ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻĒāĻ°āĻŋāĻŖāĻ¤ āĻšāĻ¯āĻŧā§‡āĻ›ā§‡: āĻāĻŸāĻŋāĻ° āĻŦā§āĻ¯āĻžāĻĒāĻ• āĻ•āĻžāĻ°ā§āĻ¯āĻ•āĻžāĻ°āĻŋāĻ¤āĻž āĻāĻŦāĻ‚ āĻ‰āĻšā§āĻš āĻ•āĻžāĻ°ā§āĻ¯āĻ•āĻžāĻ°āĻŋāĻ¤āĻž āĻ›āĻžāĻĄāĻŧāĻžāĻ“, āĻāĻ° āĻŦāĻŋāĻ•āĻžāĻļāĻ•āĻžāĻ°ā§€āĻ°āĻž āĻŦā§‡āĻļ āĻĒā§āĻ°āĻ¤āĻŋāĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻļā§€āĻ˛ āĻšāĻ¯āĻŧā§‡ āĻ‰āĻ ā§‡āĻ›ā§‡ āĻāĻŦāĻ‚ āĻ…āĻŦāĻŋāĻ˛āĻŽā§āĻŦā§‡ āĻāĻŦāĻ‚ āĻŦāĻŋāĻļāĻĻāĻ­āĻžāĻŦā§‡ āĻĒā§āĻ°āĻļā§āĻ¨ā§‡āĻ° āĻ‰āĻ¤ā§āĻ¤āĻ° āĻĻāĻŋāĻ¯āĻŧā§‡āĻ›ā§‡āĨ¤ āĻ¤āĻžāĻĻā§‡āĻ° āĻ¸āĻžāĻšāĻžāĻ¯ā§āĻ¯ā§‡, āĻ“āĻĒā§‡āĻ¨āĻ¸āĻŋāĻ­āĻŋ āĻŽā§āĻ¯āĻžāĻŸā§āĻ°āĻŋāĻ•ā§āĻ¸ā§‡āĻ° āĻāĻ•ā§āĻ¸āĻŸā§‡āĻ¨āĻ¸āĻ° āĻŸā§‡āĻ¨āĻ¸āĻ°ā§‡ āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ•āĻ°āĻž āĻ¸āĻŽā§āĻ­āĻŦ āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛, āĻ¸ā§‡āĻ‡āĻ¸āĻžāĻĨā§‡ 3-āĻŽāĻžāĻ¤ā§āĻ°āĻŋāĻ• āĻ‡āĻŽā§‡āĻœ āĻŸā§‡āĻ¨āĻ¸āĻ°āĻ—ā§āĻ˛āĻŋāĻ•ā§‡ āĻ¸āĻ āĻŋāĻ• āĻŽāĻžāĻ¤ā§āĻ°āĻžāĻ° (āĻŦā§āĻ¯āĻžāĻš āĻ¨āĻŋāĻœā§‡āĻ‡) 4-āĻŽāĻžāĻ¤ā§āĻ°āĻŋāĻ• āĻŸā§‡āĻ¨āĻ¸āĻ°ā§‡ āĻāĻ•āĻ¤ā§āĻ°āĻŋāĻ¤ āĻ•āĻ°āĻžāĻ° āĻ‰āĻĒāĻžāĻ¯āĻŧāĨ¤

Rcpp, xtensor āĻāĻŦāĻ‚ RcppThread āĻļā§‡āĻ–āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ‰āĻĒāĻ•āĻ°āĻŖ

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

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

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

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

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

āĻ¸āĻŋāĻ¸ā§āĻŸā§‡āĻŽ āĻĢāĻžāĻ‡āĻ˛āĻ—ā§āĻ˛āĻŋ āĻāĻŦāĻ‚ āĻ¸āĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡ āĻ‡āĻ¨āĻ¸ā§āĻŸāĻ˛ āĻ•āĻ°āĻž āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋāĻ° āĻ¸āĻžāĻĨā§‡ āĻ—āĻ¤āĻŋāĻļā§€āĻ˛ āĻ˛āĻŋāĻ™ā§āĻ•āĻŋāĻ‚ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻāĻŽāĻ¨ āĻĢāĻžāĻ‡āĻ˛āĻ—ā§āĻ˛āĻŋ āĻ•āĻŽā§āĻĒāĻžāĻ‡āĻ˛ āĻ•āĻ°āĻ¤ā§‡, āĻ†āĻŽāĻ°āĻž āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœā§‡ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻ— āĻ•āĻ°āĻž āĻĒā§āĻ˛āĻžāĻ—āĻ‡āĻ¨ āĻĒāĻĻā§āĻ§āĻ¤āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡āĻ›āĻŋ Rcpp. āĻ¸ā§āĻŦāĻ¯āĻŧāĻ‚āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻ­āĻžāĻŦā§‡ āĻĒāĻžāĻĨ āĻāĻŦāĻ‚ āĻĒāĻ¤āĻžāĻ•āĻž āĻ–ā§āĻāĻœā§‡ āĻĒā§‡āĻ¤ā§‡, āĻ†āĻŽāĻ°āĻž āĻāĻ•āĻŸāĻŋ āĻœāĻ¨āĻĒā§āĻ°āĻŋāĻ¯āĻŧ āĻ˛āĻŋāĻ¨āĻžāĻ•ā§āĻ¸ āĻ‡āĻ‰āĻŸāĻŋāĻ˛āĻŋāĻŸāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡āĻ›āĻŋ pkg-config.

OpenCV āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ Rcpp āĻĒā§āĻ˛āĻžāĻ—āĻ‡āĻ¨ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨

Rcpp::registerPlugin("opencv", function() {
  # ВозĐŧĐžĐļĐŊŅ‹Đĩ ĐŊаСваĐŊиŅ ĐŋĐ°ĐēĐĩŅ‚Đ°
  pkg_config_name <- c("opencv", "opencv4")
  # БиĐŊĐ°Ņ€ĐŊŅ‹Đš Ņ„Đ°ĐšĐģ ŅƒŅ‚иĐģиŅ‚Ņ‹ pkg-config
  pkg_config_bin <- Sys.which("pkg-config")
  # ПŅ€ĐžĐ˛Ņ€ĐĩĐēĐ° ĐŊĐ°ĐģиŅ‡Đ¸Ņ ŅƒŅ‚иĐģиŅ‚Ņ‹ в ŅĐ¸ŅŅ‚ĐĩĐŧĐĩ
  checkmate::assert_file_exists(pkg_config_bin, access = "x")
  # ПŅ€ĐžĐ˛ĐĩŅ€ĐēĐ° ĐŊĐ°ĐģиŅ‡Đ¸Ņ Ņ„Đ°ĐšĐģĐ° ĐŊĐ°ŅŅ‚Ņ€ĐžĐĩĐē OpenCV Đ´ĐģŅ pkg-config
  check <- sapply(pkg_config_name, 
                  function(pkg) system(paste(pkg_config_bin, pkg)))
  if (all(check != 0)) {
    stop("OpenCV config for the pkg-config not found", call. = FALSE)
  }

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

āĻĒā§āĻ˛āĻžāĻ—āĻ‡āĻ¨ā§‡āĻ° āĻ…āĻĒāĻžāĻ°ā§‡āĻļāĻ¨ā§‡āĻ° āĻĢāĻ˛āĻ¸ā§āĻŦāĻ°ā§‚āĻĒ, āĻ¸āĻ‚āĻ•āĻ˛āĻ¨ āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻšāĻ˛āĻžāĻ•āĻžāĻ˛ā§€āĻ¨ āĻ¨āĻŋāĻŽā§āĻ¨āĻ˛āĻŋāĻ–āĻŋāĻ¤ āĻŽāĻžāĻ¨āĻ—ā§āĻ˛āĻŋ āĻĒā§āĻ°āĻ¤āĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻŋāĻ¤ āĻšāĻŦā§‡:

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

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

JSON āĻĒāĻžāĻ°ā§āĻ¸ āĻ•āĻ°āĻžāĻ° āĻāĻŦāĻ‚ āĻŽāĻĄā§‡āĻ˛ā§‡ āĻŸā§āĻ°āĻžāĻ¨ā§āĻ¸āĻŽāĻŋāĻļāĻ¨ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻŦā§āĻ¯āĻžāĻš āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ•ā§‹āĻĄ āĻ¸ā§āĻĒāĻ¯āĻŧāĻ˛āĻžāĻ°ā§‡āĻ° āĻ…āĻ§ā§€āĻ¨ā§‡ āĻĻā§‡āĻ“āĻ¯āĻŧāĻž āĻšāĻ¯āĻŧā§‡āĻ›ā§‡āĨ¤ āĻĒā§āĻ°āĻĨāĻŽā§‡, āĻšā§‡āĻĄāĻžāĻ° āĻĢāĻžāĻ‡āĻ˛āĻ—ā§āĻ˛āĻŋ āĻ…āĻ¨ā§āĻ¸āĻ¨ā§āĻ§āĻžāĻ¨ āĻ•āĻ°āĻ¤ā§‡ āĻāĻ•āĻŸāĻŋ āĻ¸ā§āĻĨāĻžāĻ¨ā§€āĻ¯āĻŧ āĻĒā§āĻ°āĻ•āĻ˛ā§āĻĒ āĻĄāĻŋāĻ°ā§‡āĻ•ā§āĻŸāĻ°āĻŋ āĻ¯ā§‹āĻ— āĻ•āĻ°ā§āĻ¨ (ndjson āĻāĻ° āĻœāĻ¨ā§āĻ¯ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨):

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

C++ āĻ āĻŸā§‡āĻ¨āĻ¸āĻ° āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻĨā§‡āĻ•ā§‡ JSON āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨

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

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

// ХиĐŊĐžĐŊиĐŧŅ‹ Đ´ĐģŅ Ņ‚иĐŋОв
using RcppThread::parallelFor;
using json = nlohmann::json;
using points = xt::xtensor<double,2>;     // ИСвĐģĐĩŅ‡Ņ‘ĐŊĐŊŅ‹Đĩ иС JSON ĐēООŅ€Đ´Đ¸ĐŊĐ°Ņ‚Ņ‹ Ņ‚ĐžŅ‡ĐĩĐē
using strokes = std::vector<points>;      // ИСвĐģĐĩŅ‡Ņ‘ĐŊĐŊŅ‹Đĩ иС JSON ĐēООŅ€Đ´Đ¸ĐŊĐ°Ņ‚Ņ‹ Ņ‚ĐžŅ‡ĐĩĐē
using xtensor3d = xt::xtensor<double, 3>; // ĐĸĐĩĐŊСОŅ€ Đ´ĐģŅ Ņ…Ņ€Đ°ĐŊĐĩĐŊиŅ ĐŧĐ°Ņ‚Ņ€Đ¸Ņ†Ņ‹ иСООйŅ€Đ°ĐļĐĩĐŊиŅ
using xtensor4d = xt::xtensor<double, 4>; // ĐĸĐĩĐŊСОŅ€ Đ´ĐģŅ Ņ…Ņ€Đ°ĐŊĐĩĐŊиŅ ĐŧĐŊĐžĐļĐĩŅŅ‚ва иСОйŅ€Đ°ĐļĐĩĐŊиК
using rtensor3d = xt::rtensor<double, 3>; // ОбŅ‘Ņ€Ņ‚ĐēĐ° Đ´ĐģŅ ŅĐēŅĐŋĐžŅ€Ņ‚Đ° в R
using rtensor4d = xt::rtensor<double, 4>; // ОбŅ‘Ņ€Ņ‚ĐēĐ° Đ´ĐģŅ ŅĐēŅĐŋĐžŅ€Ņ‚Đ° в R

// ĐĄŅ‚Đ°Ņ‚иŅ‡ĐĩŅĐēиĐĩ ĐēĐžĐŊŅŅ‚Đ°ĐŊŅ‚Ņ‹
// РаСĐŧĐĩŅ€ иСОйŅ€Đ°ĐļĐĩĐŊиŅ в ĐŋиĐēŅĐĩĐģŅŅ…
const static int SIZE = 256;
// ĐĸиĐŋ ĐģиĐŊии
// ĐĄĐŧ. https://en.wikipedia.org/wiki/Pixel_connectivity#2-dimensional
const static int LINE_TYPE = cv::LINE_4;
// ĐĸĐžĐģŅ‰Đ¸ĐŊĐ° ĐģиĐŊии в ĐŋиĐēŅĐĩĐģŅŅ…
const static int LINE_WIDTH = 3;
// АĐģĐŗĐžŅ€Đ¸Ņ‚Đŧ Ņ€ĐĩŅĐ°ĐšĐˇĐ°
// https://docs.opencv.org/3.1.0/da/d54/group__imgproc__transform.html#ga5bb5a1fea74ea38e1a5445ca803ff121
const static int RESIZE_TYPE = cv::INTER_LINEAR;

// ШайĐģĐžĐŊ Đ´ĐģŅ ĐēĐžĐŊвĐĩŅ€Ņ‚иŅ€ĐžĐ˛Đ°ĐŊиŅ OpenCV-ĐŧĐ°Ņ‚Ņ€Đ¸Ņ†Ņ‹ в Ņ‚ĐĩĐŊСОŅ€
template <typename T, int NCH, typename XT=xt::xtensor<T,3,xt::layout_type::column_major>>
XT to_xt(const cv::Mat_<cv::Vec<T, NCH>>& src) {
  // РаСĐŧĐĩŅ€ĐŊĐžŅŅ‚ŅŒ Ņ†ĐĩĐģĐĩвОĐŗĐž Ņ‚ĐĩĐŊСОŅ€Đ°
  std::vector<int> shape = {src.rows, src.cols, NCH};
  // ОбŅ‰ĐĩĐĩ ĐēĐžĐģиŅ‡ĐĩŅŅ‚вО ŅĐģĐĩĐŧĐĩĐŊŅ‚Ов в ĐŧĐ°ŅŅĐ¸Đ˛Đĩ
  size_t size = src.total() * NCH;
  // ПŅ€ĐĩОйŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊиĐĩ cv::Mat в xt::xtensor
  XT res = xt::adapt((T*) src.data, size, xt::no_ownership(), shape);
  return res;
}

// ПŅ€ĐĩОйŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊиĐĩ JSON в ŅĐŋиŅĐžĐē ĐēООŅ€Đ´Đ¸ĐŊĐ°Ņ‚ Ņ‚ĐžŅ‡ĐĩĐē
strokes parse_json(const std::string& x) {
  auto j = json::parse(x);
  // Đ ĐĩСŅƒĐģŅŒŅ‚Đ°Ņ‚ ĐŋĐ°Ņ€ŅĐ¸ĐŊĐŗĐ° Đ´ĐžĐģĐļĐĩĐŊ ĐąŅ‹Ņ‚ŅŒ ĐŧĐ°ŅŅĐ¸Đ˛ĐžĐŧ
  if (!j.is_array()) {
    throw std::runtime_error("'x' must be JSON array.");
  }
  strokes res;
  res.reserve(j.size());
  for (const auto& a: j) {
    // КаĐļĐ´Ņ‹Đš ŅĐģĐĩĐŧĐĩĐŊŅ‚ ĐŧĐ°ŅŅĐ¸Đ˛Đ° Đ´ĐžĐģĐļĐĩĐŊ ĐąŅ‹Ņ‚ŅŒ 2-ĐŧĐĩŅ€ĐŊŅ‹Đŧ ĐŧĐ°ŅŅĐ¸Đ˛ĐžĐŧ
    if (!a.is_array() || a.size() != 2) {
      throw std::runtime_error("'x' must include only 2d arrays.");
    }
    // ИСвĐģĐĩŅ‡ĐĩĐŊиĐĩ вĐĩĐēŅ‚ĐžŅ€Đ° Ņ‚ĐžŅ‡ĐĩĐē
    auto p = a.get<points>();
    res.push_back(p);
  }
  return res;
}

// ОŅ‚Ņ€Đ¸ŅĐžĐ˛ĐēĐ° ĐģиĐŊиК
// ĐĻвĐĩŅ‚Đ° HSV
cv::Mat ocv_draw_lines(const strokes& x, bool color = true) {
  // ИŅŅ…ОдĐŊŅ‹Đš Ņ‚иĐŋ ĐŧĐ°Ņ‚Ņ€Đ¸Ņ†Ņ‹
  auto stype = color ? CV_8UC3 : CV_8UC1;
  // ИŅ‚ĐžĐŗОвŅ‹Đš Ņ‚иĐŋ ĐŧĐ°Ņ‚Ņ€Đ¸Ņ†Ņ‹
  auto dtype = color ? CV_32FC3 : CV_32FC1;
  auto bg = color ? cv::Scalar(0, 0, 255) : cv::Scalar(255);
  auto col = color ? cv::Scalar(0, 255, 220) : cv::Scalar(0);
  cv::Mat img = cv::Mat(SIZE, SIZE, stype, bg);
  // КоĐģиŅ‡ĐĩŅŅ‚вО ĐģиĐŊиК
  size_t n = x.size();
  for (const auto& s: x) {
    // КоĐģиŅ‡ĐĩŅŅ‚вО Ņ‚ĐžŅ‡ĐĩĐē в ĐģиĐŊии
    size_t n_points = s.shape()[1];
    for (size_t i = 0; i < n_points - 1; ++i) {
      // ĐĸĐžŅ‡ĐēĐ° ĐŊĐ°Ņ‡Đ°ĐģĐ° ŅˆŅ‚Ņ€Đ¸Ņ…Đ°
      cv::Point from(s(0, i), s(1, i));
      // ĐĸĐžŅ‡ĐēĐ° ĐžĐēĐžĐŊŅ‡Đ°ĐŊиŅ ŅˆŅ‚Ņ€Đ¸Ņ…Đ°
      cv::Point to(s(0, i + 1), s(1, i + 1));
      // ОŅ‚Ņ€Đ¸ŅĐžĐ˛ĐēĐ° ĐģиĐŊии
      cv::line(img, from, to, col, LINE_WIDTH, LINE_TYPE);
    }
    if (color) {
      // МĐĩĐŊŅĐĩĐŧ Ņ†Đ˛ĐĩŅ‚ ĐģиĐŊии
      col[0] += 180 / n;
    }
  }
  if (color) {
    // МĐĩĐŊŅĐĩĐŧ Ņ†Đ˛ĐĩŅ‚ОвОĐĩ ĐŋŅ€ĐĩĐ´ŅŅ‚авĐģĐĩĐŊиĐĩ ĐŊĐ° RGB
    cv::cvtColor(img, img, cv::COLOR_HSV2RGB);
  }
  // МĐĩĐŊŅĐĩĐŧ Ņ„ĐžŅ€ĐŧĐ°Ņ‚ ĐŋŅ€ĐĩĐ´ŅŅ‚авĐģĐĩĐŊиŅ ĐŊĐ° float32 Ņ диаĐŋаСОĐŊĐžĐŧ [0, 1]
  img.convertTo(img, dtype, 1 / 255.0);
  return img;
}

// ОбŅ€Đ°ĐąĐžŅ‚ĐēĐ° JSON и ĐŋĐžĐģŅƒŅ‡ĐĩĐŊиĐĩ Ņ‚ĐĩĐŊСОŅ€Đ° Ņ Đ´Đ°ĐŊĐŊŅ‹Đŧи иСОйŅ€Đ°ĐļĐĩĐŊиŅ
xtensor3d process(const std::string& x, double scale = 1.0, bool color = true) {
  auto p = parse_json(x);
  auto img = ocv_draw_lines(p, color);
  if (scale != 1) {
    cv::Mat out;
    cv::resize(img, out, cv::Size(), scale, scale, RESIZE_TYPE);
    cv::swap(img, out);
    out.release();
  }
  xtensor3d arr = color ? to_xt<double,3>(img) : to_xt<double,1>(img);
  return arr;
}

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

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

āĻāĻ‡ āĻ•ā§‹āĻĄ āĻĢāĻžāĻ‡āĻ˛ā§‡ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻ•āĻ°āĻž āĻ‰āĻšāĻŋāĻ¤ src/cv_xt.cpp āĻāĻŦāĻ‚ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻĻāĻŋāĻ¯āĻŧā§‡ āĻ•āĻŽā§āĻĒāĻžāĻ‡āĻ˛ āĻ•āĻ°ā§āĻ¨ Rcpp::sourceCpp(file = "src/cv_xt.cpp", env = .GlobalEnv); āĻ•āĻžāĻœā§‡āĻ° āĻœāĻ¨ā§āĻ¯āĻ“ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ nlohmann/json.hpp āĻĨā§‡āĻ•ā§‡ āĻ­āĻžāĻ¨ā§āĻĄāĻžāĻ°. āĻ•ā§‹āĻĄāĻŸāĻŋ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āĻ¨ āĻĢāĻžāĻ‚āĻļāĻ¨ā§‡ āĻŦāĻŋāĻ­āĻ•ā§āĻ¤:

  • to_xt — āĻāĻ•āĻŸāĻŋ āĻšāĻŋāĻ¤ā§āĻ° āĻŽā§āĻ¯āĻžāĻŸā§āĻ°āĻŋāĻ•ā§āĻ¸ āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻŸā§‡āĻŽāĻĒā§āĻ˛ā§‡āĻŸā§‡āĻĄ āĻĢāĻžāĻ‚āĻļāĻ¨ (cv::Mat) āĻāĻ•āĻŸāĻŋ āĻŸā§‡āĻ¨āĻ¸āĻ°ā§‡ xt::xtensor;

  • parse_json — āĻĢāĻžāĻ‚āĻļāĻ¨āĻŸāĻŋ āĻāĻ•āĻŸāĻŋ JSON āĻ¸ā§āĻŸā§āĻ°āĻŋāĻ‚ āĻĒāĻžāĻ°ā§āĻ¸ āĻ•āĻ°ā§‡, āĻĒāĻ¯āĻŧā§‡āĻ¨ā§āĻŸā§‡āĻ° āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ™ā§āĻ• āĻŦā§‡āĻ° āĻ•āĻ°ā§‡, āĻāĻ•āĻŸāĻŋ āĻ­ā§‡āĻ•ā§āĻŸāĻ°ā§‡ āĻĒā§āĻ¯āĻžāĻ• āĻ•āĻ°ā§‡;

  • ocv_draw_lines — āĻŦāĻŋāĻ¨ā§āĻĻā§āĻ° āĻĢāĻ˛āĻžāĻĢāĻ˛ āĻ­ā§‡āĻ•ā§āĻŸāĻ° āĻĨā§‡āĻ•ā§‡, āĻŦāĻšā§ āĻ°āĻ™ā§‡āĻ° āĻ°ā§‡āĻ–āĻž āĻ†āĻāĻ•ā§‡;

  • process — āĻ‰āĻĒāĻ°ā§‡āĻ° āĻĢāĻžāĻ‚āĻļāĻ¨āĻ—ā§āĻ˛āĻŋāĻ•ā§‡ āĻāĻ•āĻ¤ā§āĻ°āĻŋāĻ¤ āĻ•āĻ°ā§‡ āĻāĻŦāĻ‚ āĻĢāĻ˛āĻ¸ā§āĻŦāĻ°ā§‚āĻĒ āĻšāĻŋāĻ¤ā§āĻ°āĻŸāĻŋ āĻ¸ā§āĻ•ā§‡āĻ˛ āĻ•āĻ°āĻžāĻ° āĻ•ā§āĻˇāĻŽāĻ¤āĻžāĻ“ āĻ¯ā§‹āĻ— āĻ•āĻ°ā§‡;

  • cpp_process_json_str - āĻĢāĻžāĻ‚āĻļāĻ¨ āĻ‰āĻĒāĻ° āĻŽā§‹āĻĄāĻŧāĻžāĻ¨ā§‹ process, āĻ¯āĻž āĻāĻ•āĻŸāĻŋ R- āĻ…āĻŦāĻœā§‡āĻ•ā§āĻŸā§‡ āĻĢāĻ˛āĻžāĻĢāĻ˛ āĻ°āĻĒā§āĻ¤āĻžāĻ¨āĻŋ āĻ•āĻ°ā§‡ (āĻŦāĻšā§āĻŽāĻžāĻ¤ā§āĻ°āĻŋāĻ• āĻ…ā§āĻ¯āĻžāĻ°ā§‡);

  • cpp_process_json_vector - āĻĢāĻžāĻ‚āĻļāĻ¨ āĻ‰āĻĒāĻ° āĻŽā§‹āĻĄāĻŧāĻžāĻ¨ā§‹ cpp_process_json_str, āĻ¯āĻž āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻŽāĻžāĻ˛ā§āĻŸāĻŋ-āĻĨā§āĻ°ā§‡āĻĄā§‡āĻĄ āĻŽā§‹āĻĄā§‡ āĻāĻ•āĻŸāĻŋ āĻ¸ā§āĻŸā§āĻ°āĻŋāĻ‚ āĻ­ā§‡āĻ•ā§āĻŸāĻ° āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ•āĻ°āĻ¤ā§‡ āĻĻā§‡āĻ¯āĻŧāĨ¤

āĻŦāĻšā§ āĻ°āĻ™ā§‡āĻ° āĻ°ā§‡āĻ–āĻž āĻ†āĻāĻ•āĻ¤ā§‡, HSV āĻ°āĻ™ā§‡āĻ° āĻŽāĻĄā§‡āĻ˛ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛, āĻ¤āĻžāĻ°āĻĒāĻ°ā§‡ RGB-āĻ¤ā§‡ āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛āĨ¤ āĻ†āĻ¸ā§āĻ¨ āĻĢāĻ˛āĻžāĻĢāĻ˛ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž āĻ•āĻ°āĻž āĻ¯āĻžāĻ•:

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

āĻ•ā§āĻ‡āĻ• āĻĄā§āĻ° āĻĄā§āĻĄāĻ˛ āĻ¸ā§āĻŦā§€āĻ•ā§ƒāĻ¤āĻŋ: āĻ•āĻŋāĻ­āĻžāĻŦā§‡ R, C++ āĻāĻŦāĻ‚ āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻŦāĻ¨ā§āĻ§ā§āĻ¤ā§āĻŦ āĻ•āĻ°āĻž āĻ¯āĻžāĻ¯āĻŧ
R āĻāĻŦāĻ‚ C++ āĻ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ā§‡āĻ° āĻ—āĻ¤āĻŋāĻ° āĻ¤ā§āĻ˛āĻ¨āĻž

res_bench <- bench::mark(
  r_process_json_str(tmp_data[4, drawing], scale = 0.5),
  cpp_process_json_str(tmp_data[4, drawing], scale = 0.5),
  check = FALSE,
  min_iterations = 100
)
# ПаŅ€Đ°ĐŧĐĩŅ‚Ņ€Ņ‹ ĐąĐĩĐŊŅ‡ĐŧĐ°Ņ€ĐēĐ°
cols <- c("expression", "min", "median", "max", "itr/sec", "total_time", "n_itr")
res_bench[, cols]

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

library(ggplot2)
# ПŅ€ĐžĐ˛ĐĩĐ´ĐĩĐŊиĐĩ СаĐŧĐĩŅ€Đ°
res_bench <- bench::press(
  batch_size = 2^(4:10),
  {
    .data <- tmp_data[sample(seq_len(.N), batch_size), drawing]
    bench::mark(
      r_process_json_vector(.data, scale = 0.5),
      cpp_process_json_vector(.data,  scale = 0.5),
      min_iterations = 50,
      check = FALSE
    )
  }
)

res_bench[, cols]

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

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

āĻ•ā§āĻ‡āĻ• āĻĄā§āĻ° āĻĄā§āĻĄāĻ˛ āĻ¸ā§āĻŦā§€āĻ•ā§ƒāĻ¤āĻŋ: āĻ•āĻŋāĻ­āĻžāĻŦā§‡ R, C++ āĻāĻŦāĻ‚ āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻŦāĻ¨ā§āĻ§ā§āĻ¤ā§āĻŦ āĻ•āĻ°āĻž āĻ¯āĻžāĻ¯āĻŧ

āĻ†āĻĒāĻ¨āĻŋ āĻĻā§‡āĻ–āĻ¤ā§‡ āĻĒāĻžāĻšā§āĻ›ā§‡āĻ¨, āĻ—āĻ¤āĻŋ āĻŦā§ƒāĻĻā§āĻ§āĻŋ āĻ–ā§āĻŦāĻ‡ āĻ¤āĻžā§ŽāĻĒāĻ°ā§āĻ¯āĻĒā§‚āĻ°ā§āĻŖ āĻšāĻ¯āĻŧā§‡ āĻ‰āĻ ā§‡āĻ›ā§‡, āĻāĻŦāĻ‚ R āĻ•ā§‹āĻĄāĻ•ā§‡ āĻ¸āĻŽāĻžāĻ¨ā§āĻ¤āĻ°āĻžāĻ˛ āĻ•āĻ°ā§‡ C++ āĻ•ā§‹āĻĄā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻ§āĻ°āĻž āĻ¸āĻŽā§āĻ­āĻŦ āĻ¨āĻ¯āĻŧāĨ¤

3. āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ āĻĨā§‡āĻ•ā§‡ āĻŦā§āĻ¯āĻžāĻš āĻ†āĻ¨āĻ˛ā§‹āĻĄ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻ•āĻžāĻ°ā§€

R-āĻāĻ° āĻ°â€ā§āĻ¯āĻžāĻŽā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻŽāĻžāĻ¨āĻžāĻ¨āĻ¸āĻ‡ āĻĄā§‡āĻŸāĻž āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ•āĻ°āĻŖā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻ¸ā§-āĻ¯ā§‹āĻ—ā§āĻ¯ āĻ–ā§āĻ¯āĻžāĻ¤āĻŋ āĻ°āĻ¯āĻŧā§‡āĻ›ā§‡, āĻ¯āĻ–āĻ¨ āĻĒāĻžāĻ‡āĻĨāĻ¨āĻŸāĻŋ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻŽā§‚āĻ˛āĻ• āĻĄā§‡āĻŸāĻž āĻĒā§āĻ°āĻ¸ā§‡āĻ¸āĻŋāĻ‚ āĻĻā§āĻŦāĻžāĻ°āĻž āĻ†āĻ°āĻ“ āĻŦā§ˆāĻļāĻŋāĻˇā§āĻŸā§āĻ¯āĻ¯ā§āĻ•ā§āĻ¤, āĻ¯āĻž āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻ¸āĻšāĻœā§‡ āĻāĻŦāĻ‚ āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ•āĻ­āĻžāĻŦā§‡ āĻ†āĻ‰āĻŸ-āĻ…āĻĢ-āĻ•ā§‹āĻ° āĻ—āĻŖāĻ¨āĻžāĻ—ā§āĻ˛āĻŋ (āĻŦāĻžāĻšā§āĻ¯āĻŋāĻ• āĻŽā§‡āĻŽāĻ°āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻ—āĻŖāĻ¨āĻž) āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ•āĻ°āĻ¤ā§‡ āĻĻā§‡āĻ¯āĻŧāĨ¤ āĻŦāĻ°ā§āĻŖāĻŋāĻ¤ āĻ¸āĻŽāĻ¸ā§āĻ¯āĻžāĻ° āĻĒā§āĻ°ā§‡āĻ•ā§āĻˇāĻžāĻĒāĻŸā§‡ āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻ•ā§āĻ˛āĻžāĻ¸āĻŋāĻ• āĻāĻŦāĻ‚ āĻĒā§āĻ°āĻžāĻ¸āĻ™ā§āĻ—āĻŋāĻ• āĻ‰āĻĻāĻžāĻšāĻ°āĻŖ āĻšāĻ˛ āĻ—āĻ­ā§€āĻ° āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ• āĻ¯āĻž āĻ—ā§āĻ°ā§‡āĻĄāĻŋāĻ¯āĻŧā§‡āĻ¨ā§āĻŸ āĻĄāĻŋāĻ¸ā§‡āĻ¨ā§āĻŸ āĻĒāĻĻā§āĻ§āĻ¤āĻŋāĻ¤ā§‡ āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŋāĻ¤ āĻšāĻ¯āĻŧ āĻāĻŦāĻ‚ āĻĒā§āĻ°āĻ¤āĻŋāĻŸāĻŋ āĻ§āĻžāĻĒā§‡ āĻ—ā§āĻ°ā§‡āĻĄāĻŋāĻ¯āĻŧā§‡āĻ¨ā§āĻŸā§‡āĻ° āĻ†āĻ¨ā§āĻŽāĻžāĻ¨āĻŋāĻ• āĻāĻ•āĻŸāĻŋ āĻ›ā§‹āĻŸ āĻ…āĻ‚āĻļ āĻĒāĻ°ā§āĻ¯āĻŦā§‡āĻ•ā§āĻˇāĻŖ āĻŦāĻž āĻŽāĻŋāĻ¨āĻŋ-āĻŦā§āĻ¯āĻžāĻš āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡āĨ¤

āĻĒāĻžāĻ‡āĻĨāĻ¨ā§‡ āĻ˛ā§‡āĻ–āĻž āĻĄāĻŋāĻĒ āĻ˛āĻžāĻ°ā§āĻ¨āĻŋāĻ‚ āĻĢā§āĻ°ā§‡āĻŽāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•āĻ—ā§āĻ˛āĻŋāĻ¤ā§‡ āĻŦāĻŋāĻļā§‡āĻˇ āĻ•ā§āĻ˛āĻžāĻ¸ āĻ°āĻ¯āĻŧā§‡āĻ›ā§‡ āĻ¯āĻž āĻĄā§‡āĻŸāĻžāĻ° āĻ‰āĻĒāĻ° āĻ­āĻŋāĻ¤ā§āĻ¤āĻŋ āĻ•āĻ°ā§‡ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻ•āĻžāĻ°ā§€āĻ—ā§āĻ˛āĻŋāĻ•ā§‡ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻ— āĻ•āĻ°ā§‡: āĻŸā§‡āĻŦāĻŋāĻ˛, āĻĢā§‹āĻ˛ā§āĻĄāĻžāĻ°ā§‡ āĻ›āĻŦāĻŋ, āĻŦāĻžāĻ‡āĻ¨āĻžāĻ°āĻŋ āĻĢāĻ°ā§āĻŽā§āĻ¯āĻžāĻŸ āĻ‡āĻ¤ā§āĻ¯āĻžāĻĻāĻŋāĨ¤ āĻ†āĻĒāĻ¨āĻŋ āĻ¤ā§ˆāĻ°āĻŋ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāĻ—ā§āĻ˛āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨ āĻŦāĻž āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻŸ āĻ•āĻžāĻœā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻ¨āĻŋāĻœā§‡āĻ° āĻ˛āĻŋāĻ–āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨āĨ¤ R-āĻ āĻ†āĻŽāĻ°āĻž āĻĒāĻžāĻ‡āĻĨāĻ¨ āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋāĻ° āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻŦā§ˆāĻļāĻŋāĻˇā§āĻŸā§āĻ¯ā§‡āĻ° āĻ¸ā§āĻŦāĻŋāĻ§āĻž āĻ¨āĻŋāĻ¤ā§‡ āĻĒāĻžāĻ°āĻŋ keras āĻāĻ•āĻ‡ āĻ¨āĻžāĻŽā§‡āĻ° āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻāĻ° āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āĻ¨ āĻŦā§āĻ¯āĻžāĻ•āĻāĻ¨ā§āĻĄ āĻ¸āĻš, āĻ¯āĻž āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœā§‡āĻ° āĻ‰āĻĒāĻ°ā§‡ āĻ•āĻžāĻœ āĻ•āĻ°ā§‡ āĻ°ā§‡āĻŸāĻŋāĻ•ā§āĻ˛ā§‡āĻŸ. āĻĒāĻ°ā§‡āĻ°āĻŸāĻŋ āĻāĻ•āĻŸāĻŋ āĻĒā§ƒāĻĨāĻ• āĻĻā§€āĻ°ā§āĻ˜ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ā§‡āĻ° āĻĻāĻžāĻŦāĻŋ āĻ°āĻžāĻ–ā§‡; āĻāĻŸāĻŋ āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° R āĻĨā§‡āĻ•ā§‡ āĻĒāĻžāĻ‡āĻĨāĻ¨ āĻ•ā§‹āĻĄ āĻšāĻžāĻ˛āĻžāĻ¨ā§‹āĻ° āĻ…āĻ¨ā§āĻŽāĻ¤āĻŋ āĻĻā§‡āĻ¯āĻŧ āĻ¨āĻž, āĻ¤āĻŦā§‡ āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ R āĻāĻŦāĻ‚ Python āĻ¸ā§‡āĻļāĻ¨ā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻŦāĻ¸ā§āĻ¤ā§ āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ¨ā§āĻ¤āĻ° āĻ•āĻ°āĻžāĻ° āĻ…āĻ¨ā§āĻŽāĻ¤āĻŋ āĻĻā§‡āĻ¯āĻŧ, āĻ¸ā§āĻŦāĻ¯āĻŧāĻ‚āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻ­āĻžāĻŦā§‡ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧ āĻ§āĻ°āĻ¨ā§‡āĻ° āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻ¸āĻŽā§āĻĒāĻžāĻĻāĻ¨ āĻ•āĻ°ā§‡āĨ¤

āĻ†āĻŽāĻ°āĻž MonetDBLite āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ RAM āĻ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻĄā§‡āĻŸāĻž āĻ¸āĻžā§āĻšāĻ¯āĻŧ āĻ•āĻ°āĻžāĻ° āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧāĻ¤āĻž āĻĨā§‡āĻ•ā§‡ āĻĒāĻ°āĻŋāĻ¤ā§āĻ°āĻžāĻŖ āĻĒā§‡āĻ¯āĻŧā§‡āĻ›āĻŋ, āĻ¸āĻŽāĻ¸ā§āĻ¤ "āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•" āĻ•āĻžāĻœ āĻĒāĻžāĻ‡āĻĨāĻ¨ā§‡āĻ° āĻ†āĻ¸āĻ˛ āĻ•ā§‹āĻĄ āĻĻā§āĻŦāĻžāĻ°āĻž āĻ¸āĻžā§āĻšāĻžāĻ˛āĻŋāĻ¤ āĻšāĻŦā§‡, āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ•ā§‡āĻŦāĻ˛ āĻĄā§‡āĻŸāĻžāĻ° āĻ‰āĻĒāĻ°ā§‡ āĻāĻ•āĻŸāĻŋ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻ•āĻžāĻ°ā§€ āĻ˛āĻŋāĻ–āĻ¤ā§‡ āĻšāĻŦā§‡, āĻ¯ā§‡āĻšā§‡āĻ¤ā§ āĻ•āĻŋāĻ›ā§āĻ‡ āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤ āĻ¨ā§‡āĻ‡āĨ¤ R āĻŦāĻž Python āĻšāĻ¯āĻŧ āĻāĻ‡ āĻ§āĻ°āĻ¨ā§‡āĻ° āĻĒāĻ°āĻŋāĻ¸ā§āĻĨāĻŋāĻ¤āĻŋāĻ° āĻœāĻ¨ā§āĻ¯āĨ¤ āĻāĻŸāĻŋāĻ° āĻœāĻ¨ā§āĻ¯ āĻŽā§‚āĻ˛āĻ¤ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻĻā§āĻŸāĻŋ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧāĻ¤āĻž āĻ°āĻ¯āĻŧā§‡āĻ›ā§‡: āĻāĻŸāĻŋ āĻ…āĻŦāĻļā§āĻ¯āĻ‡ āĻāĻ•āĻŸāĻŋ āĻ…āĻ¨ā§āĻ¤āĻšā§€āĻ¨ āĻ˛ā§āĻĒā§‡ āĻŦā§āĻ¯āĻžāĻšāĻ—ā§āĻ˛āĻŋ āĻĢāĻŋāĻ°āĻŋāĻ¯āĻŧā§‡ āĻ†āĻ¨āĻ¤ā§‡ āĻšāĻŦā§‡ āĻāĻŦāĻ‚ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻ—ā§āĻ˛āĻŋāĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻāĻŸāĻŋāĻ° āĻ…āĻŦāĻ¸ā§āĻĨāĻž āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻŦā§‡ (āĻ†āĻ° āĻāĻ° āĻĒāĻ°āĻŦāĻ°ā§āĻ¤ā§€āĻŸāĻŋ āĻŦāĻ¨ā§āĻ§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻ¸āĻŦāĻšā§‡āĻ¯āĻŧā§‡ āĻ¸āĻšāĻœ āĻ‰āĻĒāĻžāĻ¯āĻŧā§‡ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻ— āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›ā§‡)āĨ¤ āĻĒā§‚āĻ°ā§āĻŦā§‡, āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻ•āĻžāĻ°ā§€āĻ° āĻ­āĻŋāĻ¤āĻ°ā§‡ R āĻ…ā§āĻ¯āĻžāĻ°ā§‡āĻ—ā§āĻ˛āĻŋāĻ•ā§‡ āĻ¸ā§āĻ¸ā§āĻĒāĻˇā§āĻŸāĻ­āĻžāĻŦā§‡ āĻ¨āĻŽā§āĻĒāĻŋ āĻ…ā§āĻ¯āĻžāĻ°ā§‡āĻ¤ā§‡ āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻ•āĻ°āĻžāĻ° āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ āĻ›āĻŋāĻ˛, āĻ¤āĻŦā§‡ āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœā§‡āĻ° āĻŦāĻ°ā§āĻ¤āĻŽāĻžāĻ¨ āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖ 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 āĻāĻŦāĻ‚ āĻ˛āĻŋāĻ™ā§āĻ•ā§‡āĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§‡ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ - āĻāĻ‡ āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ "āĻšāĻŋāĻĒāĻ¸" āĻ›āĻžāĻĄāĻŧāĻž āĻĄā§‡āĻŸāĻž.āĻŸā§āĻ¯āĻžāĻŦāĻ˛ R-āĻ āĻ•ā§‹āĻ¨āĻ“ āĻ‰āĻ˛ā§āĻ˛ā§‡āĻ–āĻ¯ā§‹āĻ—ā§āĻ¯ āĻĒāĻ°āĻŋāĻŽāĻžāĻŖ āĻĄā§‡āĻŸāĻž āĻ¨āĻŋāĻ¯āĻŧā§‡ āĻ•āĻžāĻ°ā§āĻ¯āĻ•āĻ°āĻ­āĻžāĻŦā§‡ āĻ•āĻžāĻœ āĻ•āĻ°āĻž āĻ•āĻ˛ā§āĻĒāĻ¨āĻž āĻ•āĻ°āĻž āĻŦā§‡āĻļ āĻ•āĻ āĻŋāĻ¨āĨ¤

āĻāĻ•āĻŸāĻŋ Core i5 āĻ˛ā§āĻ¯āĻžāĻĒāĻŸāĻĒā§‡ āĻ—āĻ¤āĻŋ āĻĒāĻ°āĻŋāĻŽāĻžāĻĒā§‡āĻ° āĻĢāĻ˛āĻžāĻĢāĻ˛ āĻ¨āĻŋāĻŽā§āĻ¨āĻ°ā§‚āĻĒ:

āĻ‡āĻŸāĻžāĻ°ā§‡āĻŸāĻ° āĻŦā§‡āĻžā§āĻšāĻŽāĻžāĻ°ā§āĻ•

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

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

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

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

# ИĐŊĐ´ĐĩĐēŅŅ‹ Đ´ĐģŅ ОйŅƒŅ‡Đ°ŅŽŅ‰ĐĩĐš вŅ‹ĐąĐžŅ€Đēи
train_ind <- sample(ind, floor(length(ind) * 0.995))
# ИĐŊĐ´ĐĩĐēŅŅ‹ Đ´ĐģŅ ĐŋŅ€ĐžĐ˛ĐĩŅ€ĐžŅ‡ĐŊОК вŅ‹ĐąĐžŅ€Đēи
val_ind <- ind[-train_ind]
rm(ind)
# КоŅŅ„Ņ„иŅ†Đ¸ĐĩĐŊŅ‚ ĐŧĐ°ŅŅˆŅ‚айа
scale <- 0.5

# ПŅ€ĐžĐ˛ĐĩĐ´ĐĩĐŊиĐĩ СаĐŧĐĩŅ€Đ°
res_bench <- bench::press(
  batch_size = 2^(4:10),
  {
    it1 <- train_generator(
      db_connection = con,
      samples_index = train_ind,
      num_classes = num_classes,
      batch_size = batch_size,
      scale = scale
    )
    bench::mark(
      it1(),
      min_iterations = 50L
    )
  }
)
# ПаŅ€Đ°ĐŧĐĩŅ‚Ņ€Ņ‹ ĐąĐĩĐŊŅ‡ĐŧĐ°Ņ€ĐēĐ°
cols <- c("batch_size", "min", "median", "max", "itr/sec", "total_time", "n_itr")
res_bench[, cols]

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

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

DBI::dbDisconnect(con, shutdown = TRUE)

āĻ•ā§āĻ‡āĻ• āĻĄā§āĻ° āĻĄā§āĻĄāĻ˛ āĻ¸ā§āĻŦā§€āĻ•ā§ƒāĻ¤āĻŋ: āĻ•āĻŋāĻ­āĻžāĻŦā§‡ R, C++ āĻāĻŦāĻ‚ āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻŦāĻ¨ā§āĻ§ā§āĻ¤ā§āĻŦ āĻ•āĻ°āĻž āĻ¯āĻžāĻ¯āĻŧ

āĻ†āĻĒāĻ¨āĻžāĻ° āĻ¯āĻĻāĻŋ āĻĒāĻ°ā§āĻ¯āĻžāĻĒā§āĻ¤ āĻĒāĻ°āĻŋāĻŽāĻžāĻŖā§‡ RAM āĻĨāĻžāĻ•ā§‡ āĻ¤āĻŦā§‡ āĻ†āĻĒāĻ¨āĻŋ āĻāĻ‡ āĻāĻ•āĻ‡ RAM āĻ āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ¨ā§āĻ¤āĻ° āĻ•āĻ°ā§‡ āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ā§‡āĻ° āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ•āĻ˛āĻžāĻĒāĻ•ā§‡ āĻ—ā§āĻ°ā§āĻ¤ā§āĻŦ āĻ¸āĻšāĻ•āĻžāĻ°ā§‡ āĻĻā§āĻ°ā§āĻ¤ āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨ (āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ•āĻžāĻœā§‡āĻ° āĻœāĻ¨ā§āĻ¯ 32 āĻœāĻŋāĻŦāĻŋ āĻ¯āĻĨā§‡āĻˇā§āĻŸ)āĨ¤ āĻ˛āĻŋāĻ¨āĻžāĻ•ā§āĻ¸ā§‡, āĻĒāĻžāĻ°ā§āĻŸāĻŋāĻļāĻ¨āĻŸāĻŋ āĻĄāĻŋāĻĢāĻ˛ā§āĻŸāĻ°ā§‚āĻĒā§‡ āĻŽāĻžāĻ‰āĻ¨ā§āĻŸ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧ /dev/shm, RAM āĻ•ā§āĻˇāĻŽāĻ¤āĻžāĻ° āĻ…āĻ°ā§āĻ§ā§‡āĻ• āĻĒāĻ°ā§āĻ¯āĻ¨ā§āĻ¤ āĻĻāĻ–āĻ˛ āĻ•āĻ°ā§‡āĨ¤ āĻ†āĻĒāĻ¨āĻŋ āĻ¸āĻŽā§āĻĒāĻžāĻĻāĻ¨āĻž āĻ•āĻ°ā§‡ āĻ†āĻ°āĻ“ āĻšāĻžāĻ‡āĻ˛āĻžāĻ‡āĻŸ āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨ /etc/fstabāĻāĻ•āĻŸāĻŋ āĻ°ā§‡āĻ•āĻ°ā§āĻĄ āĻĒā§‡āĻ¤ā§‡ tmpfs /dev/shm tmpfs defaults,size=25g 0 0. āĻ°āĻŋāĻŦā§āĻŸ āĻ•āĻ°āĻ¤ā§‡ āĻ­ā§āĻ˛āĻŦā§‡āĻ¨ āĻ¨āĻž āĻāĻŦāĻ‚ āĻ•āĻŽāĻžāĻ¨ā§āĻĄāĻŸāĻŋ āĻšāĻžāĻ˛āĻŋāĻ¯āĻŧā§‡ āĻĢāĻ˛āĻžāĻĢāĻ˛āĻŸāĻŋ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž āĻ•āĻ°ā§āĻ¨ df -h.

āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻžāĻ° āĻĄā§‡āĻŸāĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻ•āĻžāĻ°ā§€ āĻ…āĻ¨ā§‡āĻ• āĻ¸āĻšāĻœ āĻĻā§‡āĻ–āĻžāĻ¯āĻŧ, āĻ¯ā§‡āĻšā§‡āĻ¤ā§ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻžāĻ° āĻĄā§‡āĻŸāĻžāĻ¸ā§‡āĻŸ āĻ¸āĻŽā§āĻĒā§‚āĻ°ā§āĻŖāĻ°ā§‚āĻĒā§‡ RAM-āĻ¤ā§‡ āĻĢāĻŋāĻŸ āĻ•āĻ°ā§‡:

āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻžāĻ° āĻ¤āĻĨā§āĻ¯ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻ•āĻžāĻ°ā§€

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

  # ПŅ€ĐžĐ˛ĐĩŅ€ĐēĐ° Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Ов
  checkmate::assert_data_table(dt)
  checkmate::assert_count(batch_size)
  checkmate::assert_number(scale, lower = 0.001, upper = 5)
  checkmate::assert_flag(color)
  checkmate::assert_flag(imagenet_preproc)

  # ПŅ€ĐžŅŅ‚авĐģŅĐĩĐŧ ĐŊĐžĐŧĐĩŅ€Đ° йаŅ‚Ņ‡ĐĩĐš
  dt[, batch := (.I - 1L) %/% batch_size + 1L]
  data.table::setkey(dt, batch)
  i <- 1
  max_i <- dt[, max(batch)]

  # ЗаĐŧŅ‹ĐēĐ°ĐŊиĐĩ
  function() {
    batch_x <- cpp_process_json_vector(dt[batch == i, drawing], 
                                       scale = scale, color = color)
    if (imagenet_preproc) {
      # ШĐēĐ°ĐģиŅ€ĐžĐ˛Đ°ĐŊиĐĩ c иĐŊŅ‚ĐĩŅ€Đ˛Đ°ĐģĐ° [0, 1] ĐŊĐ° иĐŊŅ‚ĐĩŅ€Đ˛Đ°Đģ [-1, 1]
      batch_x <- (batch_x - 0.5) * 2
    }
    result <- list(batch_x)
    i <<- i + 1
    return(result)
  }
}

4. āĻŽāĻĄā§‡āĻ˛ āĻ†āĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āĻšāĻžāĻ° āĻ¨āĻŋāĻ°ā§āĻŦāĻžāĻšāĻ¨

āĻĒā§āĻ°āĻĨāĻŽ āĻŦā§āĻ¯āĻŦāĻšā§ƒāĻ¤ āĻ¸ā§āĻĨāĻžāĻĒāĻ¤ā§āĻ¯ āĻ›āĻŋāĻ˛ āĻŽā§‹āĻŦāĻžāĻ‡āĻ˛āĻ¨ā§‡āĻŸ v1, āĻ¯āĻžāĻ° āĻŦā§ˆāĻļāĻŋāĻˇā§āĻŸā§āĻ¯ āĻ†āĻ˛ā§‹āĻšāĻ¨āĻž āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›ā§‡ āĻāĻ‡ āĻŦāĻžāĻ°ā§āĻ¤āĻž āĻāĻŸāĻž āĻŽāĻžāĻ¨ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻ…āĻ¨ā§āĻ¤āĻ°ā§āĻ­ā§āĻ•ā§āĻ¤ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧ keras āĻāĻŦāĻ‚, āĻ¤āĻĻāĻ¨ā§āĻ¸āĻžāĻ°ā§‡, R-āĻāĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻ‡ āĻ¨āĻžāĻŽā§‡āĻ° āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœā§‡ āĻ‰āĻĒāĻ˛āĻŦā§āĻ§āĨ¤ āĻ•āĻŋāĻ¨ā§āĻ¤ā§ āĻāĻ•āĻ•-āĻšā§āĻ¯āĻžāĻ¨ā§‡āĻ˛ āĻšāĻŋāĻ¤ā§āĻ°āĻ—ā§āĻ˛āĻŋāĻ° āĻ¸āĻžāĻĨā§‡ āĻāĻŸāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻžāĻ° āĻšā§‡āĻˇā§āĻŸāĻž āĻ•āĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ, āĻāĻ•āĻŸāĻŋ āĻ…āĻĻā§āĻ­ā§āĻ¤ āĻœāĻŋāĻ¨āĻŋāĻ¸ āĻĻā§‡āĻ–āĻž āĻ—ā§‡āĻ˛: āĻ‡āĻ¨āĻĒā§āĻŸ āĻŸā§‡āĻ¨āĻ¸āĻ°ā§‡āĻ° āĻ¸āĻ°ā§āĻŦāĻĻāĻž āĻŽāĻžāĻ¤ā§āĻ°āĻž āĻĨāĻžāĻ•āĻ¤ā§‡ āĻšāĻŦā§‡ (batch, height, width, 3), āĻ…āĻ°ā§āĻĨāĻžā§Ž āĻšā§āĻ¯āĻžāĻ¨ā§‡āĻ˛ā§‡āĻ° āĻ¸āĻ‚āĻ–ā§āĻ¯āĻž āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ āĻ•āĻ°āĻž āĻ¯āĻžāĻŦā§‡ āĻ¨āĻžāĨ¤ āĻĒāĻžāĻ‡āĻĨāĻ¨ā§‡ āĻāĻ‡ āĻ§āĻ°āĻ¨ā§‡āĻ° āĻ•ā§‹āĻ¨ āĻ¸ā§€āĻŽāĻžāĻŦāĻĻā§āĻ§āĻ¤āĻž āĻ¨ā§‡āĻ‡, āĻ¤āĻžāĻ‡ āĻ†āĻŽāĻ°āĻž āĻŽā§‚āĻ˛ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§āĻŸāĻŋ āĻ…āĻ¨ā§āĻ¸āĻ°āĻŖ āĻ•āĻ°ā§‡ (āĻ•ā§‡āĻ°āĻžāĻ¸ āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖā§‡ āĻĄā§āĻ°āĻĒāĻ†āĻ‰āĻŸ āĻ›āĻžāĻĄāĻŧāĻž) āĻāĻ‡ āĻ†āĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āĻšāĻžāĻ°āĻŸāĻŋāĻ° āĻ¨āĻŋāĻœāĻ¸ā§āĻŦ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ›ā§āĻŸā§‡ āĻāĻ¸ā§‡āĻ›āĻŋ āĻāĻŦāĻ‚ āĻ˛āĻŋāĻ–ā§‡āĻ›āĻŋāĻ˛āĻžāĻŽ:

āĻŽā§‹āĻŦāĻžāĻ‡āĻ˛āĻ¨ā§‡āĻŸ v1 āĻ†āĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āĻšāĻžāĻ°

library(keras)

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

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

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

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

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

  inputs <- layer_input(shape = input_shape)

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

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

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

    return(model)
}

āĻāĻ‡ āĻĒāĻĻā§āĻ§āĻ¤āĻŋāĻ° āĻ…āĻ¸ā§āĻŦāĻŋāĻ§āĻžāĻ—ā§āĻ˛āĻŋ āĻ¸ā§āĻ¸ā§āĻĒāĻˇā§āĻŸāĨ¤ āĻ†āĻŽāĻŋ āĻ…āĻ¨ā§‡āĻ• āĻŽāĻĄā§‡āĻ˛ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž āĻ•āĻ°āĻ¤ā§‡ āĻšāĻžāĻ‡, āĻ•āĻŋāĻ¨ā§āĻ¤ā§ āĻŦāĻŋāĻĒāĻ°ā§€āĻ¤ā§‡, āĻ†āĻŽāĻŋ āĻĒā§āĻ°āĻ¤āĻŋāĻŸāĻŋ āĻ†āĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āĻšāĻžāĻ° āĻŽā§āĻ¯āĻžāĻ¨ā§āĻ¯āĻŧāĻžāĻ˛āĻŋ āĻĒā§āĻ¨āĻ°āĻžāĻ¯āĻŧ āĻ˛āĻŋāĻ–āĻ¤ā§‡ āĻšāĻžāĻ‡ āĻ¨āĻžāĨ¤ āĻ†āĻŽāĻ°āĻž āĻ‡āĻŽā§‡āĻœāĻ¨ā§‡āĻŸā§‡ ​​āĻĒā§āĻ°āĻžāĻ•-āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŋāĻ¤ āĻŽāĻĄā§‡āĻ˛ā§‡āĻ° āĻ“āĻœāĻ¨ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻžāĻ° āĻ¸ā§āĻ¯ā§‹āĻ— āĻĨā§‡āĻ•ā§‡āĻ“ āĻŦāĻžā§āĻšāĻŋāĻ¤ āĻ›āĻŋāĻ˛āĻžāĻŽāĨ¤ āĻ¯āĻĨāĻžāĻ°ā§€āĻ¤āĻŋ, āĻĄāĻ•ā§āĻŽā§‡āĻ¨ā§āĻŸā§‡āĻļāĻ¨ āĻ…āĻ§ā§āĻ¯āĻ¯āĻŧāĻ¨ āĻ¸āĻžāĻšāĻžāĻ¯ā§āĻ¯ āĻ•āĻ°ā§‡āĻ›ā§‡. āĻĢāĻžāĻ‚āĻļāĻ¨ get_config() āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻ¸āĻŽā§āĻĒāĻžāĻĻāĻ¨āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ‰āĻĒāĻ¯ā§āĻ•ā§āĻ¤ āĻāĻ•āĻŸāĻŋ āĻĢāĻ°ā§āĻŽā§‡ āĻŽāĻĄā§‡āĻ˛ā§‡āĻ° āĻāĻ•āĻŸāĻŋ āĻŦāĻŋāĻŦāĻ°āĻŖ āĻĒā§‡āĻ¤ā§‡ āĻ…āĻ¨ā§āĻŽāĻ¤āĻŋ āĻĻā§‡āĻ¯āĻŧ (base_model_conf$layers - āĻāĻ•āĻŸāĻŋ āĻ¨āĻŋāĻ¯āĻŧāĻŽāĻŋāĻ¤ R āĻ¤āĻžāĻ˛āĻŋāĻ•āĻž), āĻāĻŦāĻ‚ āĻĢāĻžāĻ‚āĻļāĻ¨ from_config() āĻāĻ•āĻŸāĻŋ āĻŽāĻĄā§‡āĻ˛ āĻ…āĻŦāĻœā§‡āĻ•ā§āĻŸā§‡ āĻŦāĻŋāĻĒāĻ°ā§€āĻ¤ āĻ°ā§‚āĻĒāĻžāĻ¨ā§āĻ¤āĻ° āĻ¸āĻŽā§āĻĒāĻžāĻĻāĻ¨ āĻ•āĻ°ā§‡:

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

āĻāĻ–āĻ¨ āĻ¸āĻ°āĻŦāĻ°āĻžāĻš āĻ•āĻ°āĻž āĻ¯ā§‡āĻ•ā§‹āĻ¨ā§‹ āĻāĻ•āĻŸāĻŋ āĻĒāĻžāĻ“āĻ¯āĻŧāĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻ¸āĻžāĻ°ā§āĻŦāĻœāĻ¨ā§€āĻ¨ āĻĢāĻžāĻ‚āĻļāĻ¨ āĻ˛ā§‡āĻ–āĻž āĻ•āĻ āĻŋāĻ¨ āĻ¨āĻ¯āĻŧ keras āĻ‡āĻŽā§‡āĻœāĻ¨ā§‡āĻŸā§‡ ​​āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŋāĻ¤ āĻ“āĻœāĻ¨ āĻ¸āĻš āĻŦāĻž āĻ›āĻžāĻĄāĻŧāĻž āĻŽāĻĄā§‡āĻ˛:

āĻ°ā§‡āĻĄāĻŋāĻŽā§‡āĻĄ āĻ†āĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āĻšāĻžāĻ° āĻ˛ā§‹āĻĄ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻĢāĻžāĻ‚āĻļāĻ¨

get_model <- function(name = "mobilenet_v2",
                      input_shape = NULL,
                      weights = "imagenet",
                      pooling = "avg",
                      num_classes = NULL,
                      optimizer = keras::optimizer_adam(lr = 0.002),
                      loss = "categorical_crossentropy",
                      metrics = NULL,
                      color = TRUE,
                      compile = FALSE) {
  # ПŅ€ĐžĐ˛ĐĩŅ€ĐēĐ° Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Ов
  checkmate::assert_string(name)
  checkmate::assert_integerish(input_shape, lower = 1, upper = 256, len = 3)
  checkmate::assert_count(num_classes)
  checkmate::assert_flag(color)
  checkmate::assert_flag(compile)

  # ПоĐģŅƒŅ‡Đ°ĐĩĐŧ ОйŅŠĐĩĐēŅ‚ иС ĐŋĐ°ĐēĐĩŅ‚Đ° keras
  model_fun <- get0(paste0("application_", name), envir = asNamespace("keras"))
  # ПŅ€ĐžĐ˛ĐĩŅ€ĐēĐ° ĐŊĐ°ĐģиŅ‡Đ¸Ņ ОйŅŠĐĩĐēŅ‚Đ° в ĐŋĐ°ĐēĐĩŅ‚Đĩ
  if (is.null(model_fun)) {
    stop("Model ", shQuote(name), " not found.", call. = FALSE)
  }

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

  # ЕŅĐģи иСОйŅ€Đ°ĐļĐĩĐŊиĐĩ ĐŊĐĩ Ņ†Đ˛ĐĩŅ‚ĐŊĐžĐĩ, ĐŧĐĩĐŊŅĐĩĐŧ Ņ€Đ°ĐˇĐŧĐĩŅ€ĐŊĐžŅŅ‚ŅŒ вŅ…Ода
  if (!color) {
    base_model_conf <- keras::get_config(base_model)
    base_model_conf$layers[[1]]$config$batch_input_shape[[4]] <- 1L
    base_model <- keras::from_config(base_model_conf)
  }

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

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

  return(model)
}

āĻāĻ•āĻ•-āĻšā§āĻ¯āĻžāĻ¨ā§‡āĻ˛ āĻ›āĻŦāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ, āĻ•ā§‹āĻ¨ā§‹ āĻĒā§‚āĻ°ā§āĻŦāĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŋāĻ¤ āĻ“āĻœāĻ¨ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž āĻšāĻ¯āĻŧ āĻ¨āĻžāĨ¤ āĻāĻŸāĻŋ āĻ āĻŋāĻ• āĻ•āĻ°āĻž āĻ¯ā§‡āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡: āĻĢāĻžāĻ‚āĻļāĻ¨ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ get_weights() R āĻ…ā§āĻ¯āĻžāĻ°ā§‡āĻ—ā§āĻ˛āĻŋāĻ° āĻāĻ•āĻŸāĻŋ āĻ¤āĻžāĻ˛āĻŋāĻ•āĻžāĻ° āĻ†āĻ•āĻžāĻ°ā§‡ āĻŽāĻĄā§‡āĻ˛ā§‡āĻ° āĻ“āĻœāĻ¨āĻ—ā§āĻ˛āĻŋ āĻĒāĻžāĻ¨, āĻāĻ‡ āĻ¤āĻžāĻ˛āĻŋāĻ•āĻžāĻ° āĻĒā§āĻ°āĻĨāĻŽ āĻ‰āĻĒāĻžāĻĻāĻžāĻ¨āĻŸāĻŋāĻ° āĻŽāĻžāĻ¤ā§āĻ°āĻž āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ āĻ•āĻ°ā§āĻ¨ (āĻāĻ•āĻŸāĻŋ āĻ°āĻ™ā§‡āĻ° āĻšā§āĻ¯āĻžāĻ¨ā§‡āĻ˛ āĻ¨āĻŋāĻ¯āĻŧā§‡ āĻŦāĻž āĻ¤āĻŋāĻ¨āĻŸāĻŋāĻ° āĻ—āĻĄāĻŧ āĻ•āĻ°ā§‡), āĻāĻŦāĻ‚ āĻ¤āĻžāĻ°āĻĒāĻ° āĻĢāĻžāĻ‚āĻļāĻ¨ āĻ¸āĻš āĻŽāĻĄā§‡āĻ˛āĻŸāĻŋāĻ¤ā§‡ āĻ“āĻœāĻ¨āĻ—ā§āĻ˛āĻŋ āĻ†āĻŦāĻžāĻ° āĻ˛ā§‹āĻĄ āĻ•āĻ°ā§āĻ¨ set_weights(). āĻ†āĻŽāĻ°āĻž āĻ•āĻ–āĻ¨āĻ‡ āĻāĻ‡ āĻ•āĻžāĻ°ā§āĻ¯āĻ•āĻžāĻ°āĻŋāĻ¤āĻž āĻ¯ā§‹āĻ— āĻ•āĻ°āĻŋāĻ¨āĻŋ, āĻ•āĻžāĻ°āĻŖ āĻāĻ‡ āĻĒāĻ°ā§āĻ¯āĻžāĻ¯āĻŧā§‡ āĻāĻŸāĻŋ āĻ‡āĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§‡āĻ‡ āĻ¸ā§āĻĒāĻˇā§āĻŸ āĻ›āĻŋāĻ˛ āĻ¯ā§‡ āĻ°āĻ™āĻŋāĻ¨ āĻ›āĻŦāĻŋāĻ—ā§āĻ˛āĻŋāĻ° āĻ¸āĻžāĻĨā§‡ āĻ•āĻžāĻœ āĻ•āĻ°āĻž āĻ†āĻ°āĻ“ āĻ‰āĻ¤ā§āĻĒāĻžāĻĻāĻ¨āĻļā§€āĻ˛āĨ¤

āĻ†āĻŽāĻ°āĻž āĻŽā§‹āĻŦāĻžāĻ‡āĻ˛āĻ¨ā§‡āĻŸ āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖ 1 āĻāĻŦāĻ‚ 2, āĻ¸ā§‡āĻ‡āĻ¸āĻžāĻĨā§‡ resnet34 āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻŦā§‡āĻļāĻŋāĻ°āĻ­āĻžāĻ— āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž āĻšāĻžāĻ˛āĻŋāĻ¯āĻŧā§‡āĻ›āĻŋāĨ¤ SE-ResNeXt-āĻāĻ° āĻŽāĻ¤ā§‹ āĻ†āĻ°āĻ“ āĻ†āĻ§ā§āĻ¨āĻŋāĻ• āĻ¸ā§āĻĨāĻžāĻĒāĻ¤ā§āĻ¯ āĻāĻ‡ āĻĒā§āĻ°āĻ¤āĻŋāĻ¯ā§‹āĻ—āĻŋāĻ¤āĻžāĻ¯āĻŧ āĻ­āĻžāĻ˛ā§‹ āĻĒāĻžāĻ°āĻĢāĻ°ā§āĻŽ āĻ•āĻ°ā§‡āĻ›ā§‡āĨ¤ āĻĻā§āĻ°ā§āĻ­āĻžāĻ—ā§āĻ¯āĻŦāĻļāĻ¤, āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ¨āĻŋāĻˇā§āĻĒāĻ¤ā§āĻ¤āĻŋāĻ¤ā§‡ āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤-āĻ¤ā§ˆāĻ°āĻŋ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ›āĻŋāĻ˛ āĻ¨āĻž, āĻāĻŦāĻ‚ āĻ†āĻŽāĻ°āĻž āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ¨āĻŋāĻœāĻ¸ā§āĻŦ āĻ˛āĻŋāĻ–āĻŋāĻ¨āĻŋ (āĻ¤āĻŦā§‡ āĻ†āĻŽāĻ°āĻž āĻ…āĻŦāĻļā§āĻ¯āĻ‡ āĻ˛āĻŋāĻ–āĻŦ)āĨ¤

5. āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸā§‡āĻ° āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻŸāĻžāĻ°āĻžāĻ‡āĻœā§‡āĻļāĻ¨

āĻ¸ā§āĻŦāĻŋāĻ§āĻžāĻ° āĻœāĻ¨ā§āĻ¯, āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖ āĻļā§āĻ°ā§ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻ•ā§‹āĻĄ āĻāĻ•āĻŸāĻŋ āĻāĻ•āĻ• āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻĄāĻŋāĻœāĻžāĻ‡āĻ¨ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛, āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻŸāĻžāĻ°āĻžāĻ‡āĻœāĻĄ āĻĄāĻ•āĻĒā§āĻŸ āĻ¨āĻŋāĻŽā§āĻ¨āĻ°ā§‚āĻĒ:

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

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

āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ āĻĄāĻ•āĻĒā§āĻŸ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻĒā§āĻ°āĻ¤āĻŋāĻ¨āĻŋāĻ§āĻŋāĻ¤ā§āĻŦ āĻ•āĻ°ā§‡ http://docopt.org/ R āĻāĻ° āĻœāĻ¨ā§āĻ¯āĨ¤ āĻāĻ° āĻ¸āĻžāĻšāĻžāĻ¯ā§āĻ¯ā§‡, āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸāĻ—ā§āĻ˛āĻŋ āĻ¸āĻšāĻœ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻ¸āĻš āĻšāĻžāĻ˛ā§ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧ Rscript bin/train_nn.R -m resnet50 -c -d /home/andrey/doodle_db āĻŦāĻž ./bin/train_nn.R -m resnet50 -c -d /home/andrey/doodle_db, āĻ¯āĻĻāĻŋ āĻĢāĻžāĻ‡āĻ˛ train_nn.R āĻāĻ•ā§āĻ¸āĻŋāĻ•āĻŋāĻ‰āĻŸā§‡āĻŦāĻ˛ (āĻāĻ‡ āĻ•āĻŽāĻžāĻ¨ā§āĻĄāĻŸāĻŋ āĻŽāĻĄā§‡āĻ˛āĻŸāĻŋāĻ•ā§‡ āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖ āĻĻā§‡āĻ“āĻ¯āĻŧāĻž āĻļā§āĻ°ā§ āĻ•āĻ°āĻŦā§‡ resnet50 128x128 āĻĒāĻŋāĻ•ā§āĻ¸ā§‡āĻ˛ āĻĒāĻ°āĻŋāĻŽāĻžāĻĒā§‡āĻ° āĻ¤āĻŋāĻ¨ āĻ°āĻ™ā§‡āĻ° āĻ›āĻŦāĻŋāĻ¤ā§‡, āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ āĻ…āĻŦāĻļā§āĻ¯āĻ‡ āĻĢā§‹āĻ˛ā§āĻĄāĻžāĻ°ā§‡ āĻ…āĻŦāĻ¸ā§āĻĨāĻŋāĻ¤ āĻšāĻŦā§‡ /home/andrey/doodle_db) āĻ†āĻĒāĻ¨āĻŋ āĻ¤āĻžāĻ˛āĻŋāĻ•āĻžāĻ¯āĻŧ āĻļā§‡āĻ–āĻžāĻ° āĻ—āĻ¤āĻŋ, āĻ…āĻĒā§āĻŸāĻŋāĻŽāĻžāĻ‡āĻœāĻžāĻ° āĻŸāĻžāĻ‡āĻĒ āĻāĻŦāĻ‚ āĻ…āĻ¨ā§āĻ¯ āĻ•ā§‹āĻ¨ āĻ•āĻžāĻ¸ā§āĻŸāĻŽāĻžāĻ‡āĻœāĻ¯ā§‹āĻ—ā§āĻ¯ āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻŸāĻžāĻ° āĻ¯ā§‹āĻ— āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨āĨ¤ āĻĒā§āĻ°āĻ•āĻžāĻļāĻ¨āĻžāĻ° āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤āĻŋāĻ° āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ¯āĻŧ āĻĻā§‡āĻ–āĻž āĻ—ā§‡āĻ˛ āĻ¯ā§‡ āĻ¸ā§āĻĨāĻžāĻĒāĻ¤ā§āĻ¯ mobilenet_v2 āĻŦāĻ°ā§āĻ¤āĻŽāĻžāĻ¨ āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖ āĻĨā§‡āĻ•ā§‡ keras R āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°ā§‡ āĻ¨āĻž āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨ R āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœā§‡ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨āĻ—ā§āĻ˛āĻŋ āĻŦāĻŋāĻŦā§‡āĻšāĻ¨āĻžāĻ¯āĻŧ āĻ¨āĻž āĻ¨ā§‡āĻ“āĻ¯āĻŧāĻžāĻ° āĻ•āĻžāĻ°āĻŖā§‡, āĻ†āĻŽāĻ°āĻž āĻ¤āĻžāĻĻā§‡āĻ° āĻāĻŸāĻŋ āĻ āĻŋāĻ• āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ…āĻĒā§‡āĻ•ā§āĻˇāĻž āĻ•āĻ°āĻ›āĻŋā§ˇ

āĻāĻ‡ āĻĒāĻĻā§āĻ§āĻ¤āĻŋāĻŸāĻŋ RStudio-āĻ¤ā§‡ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸāĻ—ā§āĻ˛āĻŋāĻ° āĻ†āĻ°āĻ“ āĻĒā§āĻ°āĻĨāĻžāĻ—āĻ¤ āĻ˛āĻžā§āĻšā§‡āĻ° āĻ¤ā§āĻ˛āĻ¨āĻžāĻ¯āĻŧ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āĻ¨ āĻŽāĻĄā§‡āĻ˛ā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻžāĻ—ā§āĻ˛āĻŋāĻ•ā§‡ āĻ‰āĻ˛ā§āĻ˛ā§‡āĻ–āĻ¯ā§‹āĻ—ā§āĻ¯āĻ­āĻžāĻŦā§‡ āĻ¤ā§āĻŦāĻ°āĻžāĻ¨ā§āĻŦāĻŋāĻ¤ āĻ•āĻ°āĻž āĻ¸āĻŽā§āĻ­āĻŦ āĻ•āĻ°ā§‡āĻ›ā§‡ (āĻ†āĻŽāĻ°āĻž āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœāĻŸāĻŋāĻ•ā§‡ āĻāĻ•āĻŸāĻŋ āĻ¸āĻŽā§āĻ­āĻžāĻŦā§āĻ¯ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻ¨ā§‹āĻŸ āĻ•āĻ°āĻŋ tfruns) āĻ¤āĻŦā§‡ āĻĒā§āĻ°āĻ§āĻžāĻ¨ āĻ¸ā§āĻŦāĻŋāĻ§āĻž āĻšāĻ˛ āĻāĻ° āĻœāĻ¨ā§āĻ¯ āĻ†āĻ° āĻ¸ā§āĻŸā§āĻĄāĻŋāĻ“ āĻ‡āĻ¨āĻ¸ā§āĻŸāĻ˛ āĻ¨āĻž āĻ•āĻ°ā§‡āĻ‡ āĻĄāĻ•āĻžāĻ°ā§‡ āĻŦāĻž āĻ•ā§‡āĻŦāĻ˛ āĻ¸āĻžāĻ°ā§āĻ­āĻžāĻ°ā§‡ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸāĻ—ā§āĻ˛āĻŋ āĻ¸āĻšāĻœā§‡ āĻĒāĻ°āĻŋāĻšāĻžāĻ˛āĻ¨āĻž āĻ•āĻ°āĻžāĻ° āĻ•ā§āĻˇāĻŽāĻ¤āĻžāĨ¤

6. āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸā§‡āĻ° āĻĄāĻ•āĻžāĻ°āĻžāĻ‡āĻœā§‡āĻļāĻ¨

āĻ†āĻŽāĻ°āĻž āĻĻāĻ˛ā§‡āĻ° āĻ¸āĻĻāĻ¸ā§āĻ¯āĻĻā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖ āĻŽāĻĄā§‡āĻ˛ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻŦāĻ‚ āĻ•ā§āĻ˛āĻžāĻ‰āĻĄā§‡ āĻĻā§āĻ°ā§āĻ¤ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻĒāĻ°āĻŋāĻŦā§‡āĻļā§‡āĻ° āĻŦāĻšāĻ¨āĻ¯ā§‹āĻ—ā§āĻ¯āĻ¤āĻž āĻ¨āĻŋāĻļā§āĻšāĻŋāĻ¤ āĻ•āĻ°āĻ¤ā§‡ āĻĄāĻ•āĻžāĻ° āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡āĻ›āĻŋāĨ¤ āĻ†āĻĒāĻ¨āĻŋ āĻāĻ‡ āĻ¸āĻ°āĻžā§āĻœāĻžāĻŽāĻŸāĻŋāĻ° āĻ¸āĻžāĻĨā§‡ āĻĒāĻ°āĻŋāĻšāĻŋāĻ¤ āĻšāĻ¤ā§‡ āĻļā§āĻ°ā§ āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨, āĻ¯āĻž āĻāĻ•āĻŸāĻŋ āĻ†āĻ° āĻĒā§āĻ°ā§‹āĻ—ā§āĻ°āĻžāĻŽāĻžāĻ°ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻ¤ā§āĻ˛āĻ¨āĻžāĻŽā§‚āĻ˛āĻ•āĻ­āĻžāĻŦā§‡ āĻ…āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• āĻāĻ‡ āĻĒā§āĻ°āĻ•āĻžāĻļāĻ¨āĻž āĻ¸āĻŋāĻ°āĻŋāĻœ āĻŦāĻž āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ•ā§‹āĻ°ā§āĻ¸.

āĻĄāĻ•āĻžāĻ° āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻ¸ā§āĻ•ā§āĻ°ā§āĻ¯āĻžāĻš āĻĨā§‡āĻ•ā§‡ āĻ†āĻĒāĻ¨āĻžāĻ° āĻ¨āĻŋāĻœā§‡āĻ° āĻ›āĻŦāĻŋ āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻ¤ā§‡ āĻāĻŦāĻ‚ āĻ†āĻĒāĻ¨āĻžāĻ° āĻ¨āĻŋāĻœā§‡āĻ° āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻžāĻ° āĻ­āĻŋāĻ¤ā§āĻ¤āĻŋ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻ…āĻ¨ā§āĻ¯āĻžāĻ¨ā§āĻ¯ āĻ›āĻŦāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻ¤ā§‡ āĻĻā§‡āĻ¯āĻŧāĨ¤ āĻ‰āĻĒāĻ˛āĻŦā§āĻ§ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāĻ—ā§āĻ˛āĻŋ āĻŦāĻŋāĻļā§āĻ˛ā§‡āĻˇāĻŖ āĻ•āĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ, āĻ†āĻŽāĻ°āĻž āĻ‰āĻĒāĻ¸āĻ‚āĻšāĻžāĻ°ā§‡ āĻĒā§ŒāĻāĻ›ā§‡āĻ›āĻŋ āĻ¯ā§‡ NVIDIA, CUDA + cuDNN āĻĄā§āĻ°āĻžāĻ‡āĻ­āĻžāĻ° āĻāĻŦāĻ‚ āĻĒāĻžāĻ‡āĻĨāĻ¨ āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋāĻ—ā§āĻ˛āĻŋ āĻ‡āĻ¨āĻ¸ā§āĻŸāĻ˛ āĻ•āĻ°āĻž āĻ›āĻŦāĻŋāĻŸāĻŋāĻ° āĻāĻ•āĻŸāĻŋ āĻŽā§‹āĻŸāĻžāĻŽā§āĻŸāĻŋ āĻŦāĻŋāĻļāĻžāĻ˛ āĻ…āĻ‚āĻļ, āĻāĻŦāĻ‚ āĻ†āĻŽāĻ°āĻž āĻāĻ•āĻŸāĻŋ āĻ­āĻŋāĻ¤ā§āĻ¤āĻŋ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻ…āĻĢāĻŋāĻ¸āĻŋāĻ¯āĻŧāĻžāĻ˛ āĻ›āĻŦāĻŋāĻŸāĻŋ āĻ¨ā§‡āĻ“āĻ¯āĻŧāĻžāĻ° āĻ¸āĻŋāĻĻā§āĻ§āĻžāĻ¨ā§āĻ¤ āĻ¨āĻŋāĻ¯āĻŧā§‡āĻ›āĻŋāĨ¤ tensorflow/tensorflow:1.12.0-gpu, āĻ¸ā§‡āĻ–āĻžāĻ¨ā§‡ āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧ R āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ āĻ¯ā§‹āĻ— āĻ•āĻ°āĻž āĻšāĻšā§āĻ›ā§‡āĨ¤

āĻšā§‚āĻĄāĻŧāĻžāĻ¨ā§āĻ¤ āĻĄāĻ•āĻžāĻ° āĻĢāĻžāĻ‡āĻ˛āĻŸāĻŋ āĻĻā§‡āĻ–āĻ¤ā§‡ āĻāĻ‡āĻ°āĻ•āĻŽ āĻ›āĻŋāĻ˛:

Dockerfile

FROM tensorflow/tensorflow:1.12.0-gpu

MAINTAINER Artem Klevtsov <[email protected]>

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

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

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

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

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

WORKDIR /app

VOLUME /db
VOLUME /app

CMD bash

āĻ¸ā§āĻŦāĻŋāĻ§āĻžāĻ° āĻœāĻ¨ā§āĻ¯, āĻŦā§āĻ¯āĻŦāĻšā§ƒāĻ¤ āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœāĻ—ā§āĻ˛āĻŋ āĻ­ā§‡āĻ°āĻŋāĻ¯āĻŧā§‡āĻŦāĻ˛ā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻ°āĻžāĻ–āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛; āĻ˛āĻŋāĻ–āĻŋāĻ¤ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸāĻ—ā§āĻ˛āĻŋāĻ° āĻŦā§‡āĻļāĻŋāĻ°āĻ­āĻžāĻ— āĻ…āĻ‚āĻļ āĻ¸āĻŽāĻžāĻŦā§‡āĻļā§‡āĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻĒāĻžāĻ¤ā§āĻ°ā§‡ āĻ…āĻ¨ā§āĻ˛āĻŋāĻĒāĻŋ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧāĨ¤ āĻ†āĻŽāĻ°āĻž āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻļā§‡āĻ˛āĻ“ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ āĻ•āĻ°ā§‡āĻ›āĻŋ /bin/bash āĻŦāĻŋāĻˇāĻ¯āĻŧāĻŦāĻ¸ā§āĻ¤ā§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°ā§‡āĻ° āĻ¸āĻšāĻœāĻ¤āĻžāĻ° āĻœāĻ¨ā§āĻ¯ /etc/os-release. āĻāĻŸāĻŋ āĻ•ā§‹āĻĄā§‡ OS āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻŸ āĻ•āĻ°āĻžāĻ° āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ āĻāĻĄāĻŧāĻžāĻ¯āĻŧāĨ¤

āĻ…āĻ¤āĻŋāĻ°āĻŋāĻ•ā§āĻ¤āĻ­āĻžāĻŦā§‡, āĻāĻ•āĻŸāĻŋ āĻ›ā§‹āĻŸ āĻŦā§āĻ¯āĻžāĻļ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸ āĻ˛ā§‡āĻ–āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛ āĻ¯āĻž āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āĻ¨ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻ¸āĻš āĻāĻ•āĻŸāĻŋ āĻ§āĻžāĻ°āĻ• āĻšāĻžāĻ˛ā§ āĻ•āĻ°āĻ¤ā§‡ āĻĻā§‡āĻ¯āĻŧāĨ¤ āĻ‰āĻĻāĻžāĻšāĻ°āĻŖāĻ¸ā§āĻŦāĻ°ā§‚āĻĒ, āĻāĻ—ā§āĻ˛āĻŋ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸ āĻšāĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡ āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖā§‡āĻ° āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸ āĻšāĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡ āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•āĻ—ā§āĻ˛āĻŋ āĻ¯āĻž āĻĒā§‚āĻ°ā§āĻŦā§‡ āĻ•āĻ¨ā§āĻŸā§‡āĻ‡āĻ¨āĻžāĻ°ā§‡āĻ° āĻ­āĻŋāĻ¤āĻ°ā§‡ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛, āĻ…āĻĨāĻŦāĻž āĻĄāĻŋāĻŦāĻžāĻ—āĻŋāĻ‚ āĻāĻŦāĻ‚ āĻ•āĻ¨ā§āĻŸā§‡āĻ‡āĻ¨āĻžāĻ°ā§‡āĻ° āĻ…āĻĒāĻžāĻ°ā§‡āĻļāĻ¨ āĻĒāĻ°ā§āĻ¯āĻŦā§‡āĻ•ā§āĻˇāĻŖā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻļā§‡āĻ˛:

āĻ•āĻ¨ā§āĻŸā§‡āĻ‡āĻ¨āĻžāĻ° āĻšāĻžāĻ˛ā§ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸ

#!/bin/sh

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

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

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

āĻ¯āĻĻāĻŋ āĻāĻ‡ āĻŦā§āĻ¯āĻžāĻļ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸāĻŸāĻŋ āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻŸāĻžāĻ° āĻ›āĻžāĻĄāĻŧāĻžāĻ‡ āĻšāĻžāĻ˛āĻžāĻ¨ā§‹ āĻšāĻ¯āĻŧ, āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸāĻŸāĻŋ āĻ•āĻ¨ā§āĻŸā§‡āĻ‡āĻ¨āĻžāĻ°ā§‡āĻ° āĻ­āĻŋāĻ¤āĻ°ā§‡ āĻ•āĻ˛ āĻ•āĻ°āĻž āĻšāĻŦā§‡ train_nn.R āĻĄāĻŋāĻĢāĻ˛ā§āĻŸ āĻŽāĻžāĻ¨ āĻ¸āĻš; āĻ¯āĻĻāĻŋ āĻĒā§āĻ°āĻĨāĻŽ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāĻ¨āĻ—āĻ¤ āĻ¯ā§āĻ•ā§āĻ¤āĻŋ "bash" āĻšāĻ¯āĻŧ, āĻ¤āĻžāĻšāĻ˛ā§‡ āĻ•āĻ¨ā§āĻŸā§‡āĻ‡āĻ¨āĻžāĻ°āĻŸāĻŋ āĻāĻ•āĻŸāĻŋ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻļā§‡āĻ˛ āĻĻāĻŋāĻ¯āĻŧā§‡ āĻ‡āĻ¨ā§āĻŸāĻžāĻ°ā§‡āĻ•ā§āĻŸāĻŋāĻ­āĻ­āĻžāĻŦā§‡ āĻļā§āĻ°ā§ āĻšāĻŦā§‡āĨ¤ āĻ…āĻ¨ā§āĻ¯ āĻ¸āĻŦ āĻ•ā§āĻˇā§‡āĻ¤ā§āĻ°ā§‡, āĻ…āĻŦāĻ¸ā§āĻĨāĻžāĻ¨āĻ—āĻ¤ āĻ†āĻ°ā§āĻ—ā§āĻŽā§‡āĻ¨ā§āĻŸā§‡āĻ° āĻŽāĻžāĻ¨ āĻĒā§āĻ°āĻ¤āĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻŋāĻ¤ āĻšāĻ¯āĻŧ: CMD="Rscript /app/train_nn.R $@".

āĻāĻŸāĻŋ āĻ˛āĻ•ā§āĻˇāĻŖā§€āĻ¯āĻŧ āĻ¯ā§‡ āĻ‰āĻ¤ā§āĻ¸ āĻĄā§‡āĻŸāĻž āĻāĻŦāĻ‚ āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ āĻ¸āĻš āĻĄāĻŋāĻ°ā§‡āĻ•ā§āĻŸāĻ°āĻŋāĻ—ā§āĻ˛āĻŋāĻ° āĻĒāĻžāĻļāĻžāĻĒāĻžāĻļāĻŋ āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŋāĻ¤ āĻŽāĻĄā§‡āĻ˛āĻ—ā§āĻ˛āĻŋ āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻĄāĻŋāĻ°ā§‡āĻ•ā§āĻŸāĻ°āĻŋāĻ—ā§āĻ˛āĻŋ āĻšā§‹āĻ¸ā§āĻŸ āĻ¸āĻŋāĻ¸ā§āĻŸā§‡āĻŽ āĻĨā§‡āĻ•ā§‡ āĻ•āĻ¨ā§āĻŸā§‡āĻ‡āĻ¨āĻžāĻ°ā§‡āĻ° āĻ­āĻŋāĻ¤āĻ°ā§‡ āĻŽāĻžāĻ‰āĻ¨ā§āĻŸ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›ā§‡, āĻ¯āĻž āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻ…āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧ āĻŽā§āĻ¯āĻžāĻ¨āĻŋāĻĒā§āĻ˛ā§‡āĻļāĻ¨ āĻ›āĻžāĻĄāĻŧāĻžāĻ‡ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸāĻ—ā§āĻ˛āĻŋāĻ° āĻĢāĻ˛āĻžāĻĢāĻ˛āĻ—ā§āĻ˛āĻŋ āĻ…ā§āĻ¯āĻžāĻ•ā§āĻ¸ā§‡āĻ¸ āĻ•āĻ°āĻ¤ā§‡ āĻĻā§‡āĻ¯āĻŧāĨ¤

7. Google āĻ•ā§āĻ˛āĻžāĻ‰āĻĄā§‡ āĻāĻ•āĻžāĻ§āĻŋāĻ• GPU āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž

āĻĒā§āĻ°āĻ¤āĻŋāĻ¯ā§‹āĻ—āĻŋāĻ¤āĻžāĻ° āĻ…āĻ¨ā§āĻ¯āĻ¤āĻŽ āĻŦā§ˆāĻļāĻŋāĻˇā§āĻŸā§āĻ¯ āĻ›āĻŋāĻ˛ āĻ–ā§āĻŦ āĻ•ā§‹āĻ˛āĻžāĻšāĻ˛āĻĒā§‚āĻ°ā§āĻŖ āĻĄā§‡āĻŸāĻž (āĻļāĻŋāĻ°ā§‹āĻ¨āĻžāĻŽ āĻ›āĻŦāĻŋ āĻĻā§‡āĻ–ā§āĻ¨, ODS āĻ¸ā§āĻ˛ā§āĻ¯āĻžāĻ• āĻĨā§‡āĻ•ā§‡ @Leigh.plt āĻĨā§‡āĻ•ā§‡ āĻ§āĻžāĻ° āĻ•āĻ°āĻž)āĨ¤ āĻŦāĻĄāĻŧ āĻŦā§āĻ¯āĻžāĻšāĻ—ā§āĻ˛āĻŋ āĻāĻŸāĻŋāĻ•ā§‡ āĻŽā§‹āĻ•āĻžāĻŦā§‡āĻ˛āĻžāĻ¯āĻŧ āĻ¸āĻšāĻžāĻ¯āĻŧāĻ¤āĻž āĻ•āĻ°ā§‡ āĻāĻŦāĻ‚ 1 GPU āĻ¸āĻš āĻāĻ•āĻŸāĻŋ āĻĒāĻŋāĻ¸āĻŋāĻ¤ā§‡ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž-āĻ¨āĻŋāĻ°ā§€āĻ•ā§āĻˇāĻžāĻ° āĻĒāĻ°ā§‡, āĻ†āĻŽāĻ°āĻž āĻ•ā§āĻ˛āĻžāĻ‰āĻĄā§‡ āĻŦā§‡āĻļ āĻ•āĻ¯āĻŧā§‡āĻ•āĻŸāĻŋ GPU-āĻ¤ā§‡ āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖā§‡āĻ° āĻŽāĻĄā§‡āĻ˛āĻ—ā§āĻ˛āĻŋ āĻ†āĻ¯āĻŧāĻ¤ā§āĻ¤ āĻ•āĻ°āĻžāĻ° āĻ¸āĻŋāĻĻā§āĻ§āĻžāĻ¨ā§āĻ¤ āĻ¨āĻŋāĻ¯āĻŧā§‡āĻ›āĻŋāĨ¤ āĻŦā§āĻ¯āĻŦāĻšā§ƒāĻ¤ GoogleCloud (āĻŦā§‡āĻ¸āĻŋāĻ• āĻ­āĻžāĻ˛ āĻ—āĻžāĻ‡āĻĄ) āĻ‰āĻĒāĻ˛āĻŦā§āĻ§ āĻ•āĻ¨āĻĢāĻŋāĻ—āĻžāĻ°ā§‡āĻļāĻ¨ā§‡āĻ° āĻŦā§ƒāĻšā§Ž āĻ¨āĻŋāĻ°ā§āĻŦāĻžāĻšāĻ¨, āĻ¯ā§āĻ•ā§āĻ¤āĻŋāĻ¸āĻ™ā§āĻ—āĻ¤ āĻŽā§‚āĻ˛ā§āĻ¯ āĻāĻŦāĻ‚ $300 āĻŦā§‹āĻ¨āĻžāĻ¸ā§‡āĻ° āĻ•āĻžāĻ°āĻŖā§‡āĨ¤ āĻ˛ā§‹āĻ­ā§‡āĻ° āĻœāĻ¨ā§āĻ¯, āĻ†āĻŽāĻŋ āĻāĻ•āĻŸāĻŋ SSD āĻāĻŦāĻ‚ āĻāĻ• āĻŸāĻ¨ RAM āĻ¸āĻš āĻāĻ•āĻŸāĻŋ 4xV100 āĻ‡āĻ¨ā§āĻ¸āĻŸā§āĻ¯āĻžāĻ¨ā§āĻ¸ āĻ…āĻ°ā§āĻĄāĻžāĻ° āĻ•āĻ°ā§‡āĻ›āĻŋ āĻāĻŦāĻ‚ āĻāĻŸāĻŋ āĻāĻ•āĻŸāĻŋ āĻŦāĻĄāĻŧ āĻ­ā§āĻ˛ āĻ›āĻŋāĻ˛ā§ˇ āĻāĻ‡ āĻœāĻžāĻ¤ā§€āĻ¯āĻŧ āĻŽā§‡āĻļāĻŋāĻ¨ āĻĻā§āĻ°ā§āĻ¤ āĻ…āĻ°ā§āĻĨ āĻ–ā§‡āĻ¯āĻŧā§‡ āĻĢā§‡āĻ˛ā§‡; āĻ†āĻĒāĻ¨āĻŋ āĻĒā§āĻ°āĻŽāĻžāĻŖāĻŋāĻ¤ āĻĒāĻžāĻ‡āĻĒāĻ˛āĻžāĻ‡āĻ¨ āĻ›āĻžāĻĄāĻŧāĻžāĻ‡ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž-āĻ¨āĻŋāĻ°ā§€āĻ•ā§āĻˇāĻžāĻ¯āĻŧ āĻ¯ā§‡āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨āĨ¤ āĻļāĻŋāĻ•ā§āĻˇāĻžāĻ—āĻ¤ āĻ‰āĻĻā§āĻĻā§‡āĻļā§āĻ¯ā§‡, K80 āĻ¨ā§‡āĻ“āĻ¯āĻŧāĻž āĻ­āĻžāĻ˛āĨ¤ āĻ•āĻŋāĻ¨ā§āĻ¤ā§ āĻĒā§āĻ°āĻšā§āĻ° āĻĒāĻ°āĻŋāĻŽāĻžāĻŖā§‡ āĻ°â€Œā§āĻ¯āĻžāĻŽ āĻ•āĻžāĻœā§‡ āĻāĻ¸ā§‡āĻ›ā§‡ - āĻ•ā§āĻ˛āĻžāĻ‰āĻĄ āĻāĻ¸āĻāĻ¸āĻĄāĻŋ āĻ¤āĻžāĻ° āĻ•āĻ°ā§āĻŽāĻ•ā§āĻˇāĻŽāĻ¤āĻž āĻĻā§āĻŦāĻžāĻ°āĻž āĻĒā§āĻ°āĻ­āĻžāĻŦāĻŋāĻ¤ āĻ•āĻ°ā§‡āĻ¨āĻŋ, āĻ¤āĻžāĻ‡ āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ¨ā§āĻ¤āĻ° āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛ dev/shm.

āĻ¸āĻ°ā§āĻŦāĻžāĻ§āĻŋāĻ• āĻ†āĻ—ā§āĻ°āĻšā§‡āĻ° āĻŦāĻŋāĻˇāĻ¯āĻŧ āĻšāĻ˛ āĻāĻ•āĻžāĻ§āĻŋāĻ• GPU āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻĻāĻžāĻ¯āĻŧā§€ āĻ•ā§‹āĻĄ āĻ–āĻŖā§āĻĄāĨ¤ āĻĒā§āĻ°āĻĨāĻŽāĻ¤, āĻ¸āĻŋāĻĒāĻŋāĻ‡āĻ‰āĻ¤ā§‡ āĻāĻ•āĻŸāĻŋ āĻ•āĻ¨āĻŸā§‡āĻ•ā§āĻ¸āĻŸ āĻŽā§āĻ¯āĻžāĻ¨ā§‡āĻœāĻžāĻ° āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ āĻŽāĻĄā§‡āĻ˛āĻŸāĻŋ āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›ā§‡, āĻ āĻŋāĻ• āĻĒāĻžāĻ‡āĻĨāĻ¨ā§‡āĻ° āĻŽāĻ¤ā§‹:

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

āĻ¤āĻžāĻ°āĻĒāĻ°ā§‡ āĻ†āĻ¨āĻ•āĻŽā§āĻĒāĻžāĻ‡āĻ˛ āĻ•āĻ°āĻž (āĻāĻŸāĻŋ āĻ—ā§āĻ°ā§āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ) āĻŽāĻĄā§‡āĻ˛āĻŸāĻŋ āĻāĻ•āĻŸāĻŋ āĻĒā§āĻ°āĻĻāĻ¤ā§āĻ¤ āĻ¸āĻ‚āĻ–ā§āĻ¯āĻ• āĻ‰āĻĒāĻ˛āĻŦā§āĻ§ GPU-āĻ¤ā§‡ āĻ…āĻ¨ā§āĻ˛āĻŋāĻĒāĻŋ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧ āĻāĻŦāĻ‚ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻ¤āĻžāĻ° āĻĒāĻ°ā§‡ āĻāĻŸāĻŋ āĻ¸āĻ‚āĻ•āĻ˛āĻŋāĻ¤ āĻšāĻ¯āĻŧ:

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

āĻļā§‡āĻˇāĻŸāĻŋ āĻŦā§āĻ¯āĻ¤ā§€āĻ¤ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻ¸ā§āĻ¤āĻ° āĻšāĻŋāĻŽāĻžāĻ¯āĻŧāĻŋāĻ¤ āĻ•āĻ°āĻžāĻ° āĻ•ā§āĻ˛āĻžāĻ¸āĻŋāĻ• āĻ•ā§ŒāĻļāĻ˛, āĻļā§‡āĻˇ āĻ¸ā§āĻ¤āĻ°āĻŸāĻŋāĻ•ā§‡ āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖ āĻĻā§‡āĻ“āĻ¯āĻŧāĻž, āĻŦā§‡āĻļ āĻ•āĻ¯āĻŧā§‡āĻ•āĻŸāĻŋ GPU-āĻāĻ° āĻœāĻ¨ā§āĻ¯ āĻ¸āĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻŽāĻĄā§‡āĻ˛āĻŸāĻŋāĻ•ā§‡ āĻ†āĻ¨āĻĢā§āĻ°āĻŋāĻœ āĻ•āĻ°āĻž āĻāĻŦāĻ‚ āĻĒā§āĻ¨āĻ°āĻžāĻ¯āĻŧ āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖ āĻĻā§‡āĻ“āĻ¯āĻŧāĻž āĻ¸āĻŽā§āĻ­āĻŦ āĻšāĻ¯āĻŧāĻ¨āĻŋā§ˇ

āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ›āĻžāĻĄāĻŧāĻžāĻ‡ āĻĒāĻ°ā§āĻ¯āĻŦā§‡āĻ•ā§āĻˇāĻŖ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛āĨ¤ āĻŸā§‡āĻ¨āĻ¸āĻ°āĻŦā§‹āĻ°ā§āĻĄ, āĻ˛āĻ— āĻ°ā§‡āĻ•āĻ°ā§āĻĄāĻŋāĻ‚ āĻāĻŦāĻ‚ āĻĒā§āĻ°āĻ¤āĻŋāĻŸāĻŋ āĻ¯ā§āĻ—ā§‡āĻ° āĻĒāĻ°ā§‡ āĻ¤āĻĨā§āĻ¯āĻĒā§‚āĻ°ā§āĻŖ āĻ¨āĻžāĻŽ āĻ¸āĻš āĻŽāĻĄā§‡āĻ˛ āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ¨āĻŋāĻœā§‡āĻĻā§‡āĻ°āĻ•ā§‡ āĻ¸ā§€āĻŽāĻžāĻŦāĻĻā§āĻ§ āĻ•āĻ°āĻž:

āĻ•āĻ˛āĻŦā§āĻ¯āĻžāĻ•

# ШайĐģĐžĐŊ иĐŧĐĩĐŊи Ņ„Đ°ĐšĐģĐ° ĐģĐžĐŗĐ°
log_file_tmpl <- file.path("logs", sprintf(
  "%s_%d_%dch_%s.csv",
  model_name,
  dim_size,
  channels,
  format(Sys.time(), "%Y%m%d%H%M%OS")
))
# ШайĐģĐžĐŊ иĐŧĐĩĐŊи Ņ„Đ°ĐšĐģĐ° ĐŧОдĐĩĐģи
model_file_tmpl <- file.path("models", sprintf(
  "%s_%d_%dch_{epoch:02d}_{val_loss:.2f}.h5",
  model_name,
  dim_size,
  channels
))

callbacks_list <- list(
  keras::callback_csv_logger(
    filename = log_file_tmpl
  ),
  keras::callback_early_stopping(
    monitor = "val_loss",
    min_delta = 1e-4,
    patience = 8,
    verbose = 1,
    mode = "min"
  ),
  keras::callback_reduce_lr_on_plateau(
    monitor = "val_loss",
    factor = 0.5, # ŅƒĐŧĐĩĐŊŅŒŅˆĐ°ĐĩĐŧ lr в 2 Ņ€Đ°ĐˇĐ°
    patience = 4,
    verbose = 1,
    min_delta = 1e-4,
    mode = "min"
  ),
  keras::callback_model_checkpoint(
    filepath = model_file_tmpl,
    monitor = "val_loss",
    save_best_only = FALSE,
    save_weights_only = FALSE,
    mode = "min"
  )
)

8. āĻāĻ•āĻŸāĻŋ āĻ‰āĻĒāĻ¸āĻ‚āĻšāĻžāĻ°ā§‡āĻ° āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤ā§‡

āĻ†āĻŽāĻ°āĻž āĻ¯ā§‡ āĻ¸āĻŽāĻ¸ā§āĻ¯āĻžāĻ° āĻ¸āĻŽā§āĻŽā§āĻ–ā§€āĻ¨ āĻšāĻ¯āĻŧā§‡āĻ›āĻŋ āĻ¤āĻžāĻ° āĻāĻ•āĻŸāĻŋ āĻ¸āĻ‚āĻ–ā§āĻ¯āĻž āĻāĻ–āĻ¨āĻ“ āĻ•āĻžāĻŸāĻŋāĻ¯āĻŧā§‡ āĻ‰āĻ āĻ¤ā§‡ āĻĒāĻžāĻ°āĻŋāĻ¨āĻŋ:

  • в keras āĻ¸āĻ°ā§āĻŦā§‹āĻ¤ā§āĻ¤āĻŽ āĻļā§‡āĻ–āĻžāĻ° āĻšāĻžāĻ° (āĻ…ā§āĻ¯āĻžāĻ¨āĻžāĻ˛āĻ— lr_finder āĻ—ā§āĻ°āĻ¨ā§āĻĨāĻžāĻ—āĻžāĻ°ā§‡ quick.ai); āĻ•āĻŋāĻ›ā§ āĻĒā§āĻ°āĻšā§‡āĻˇā§āĻŸāĻžāĻ° āĻ¸āĻžāĻĨā§‡, āĻ¤ā§ƒāĻ¤ā§€āĻ¯āĻŧ āĻĒāĻ•ā§āĻˇā§‡āĻ° āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨āĻ•ā§‡ R-āĻ āĻĒā§‹āĻ°ā§āĻŸ āĻ•āĻ°āĻž āĻ¸āĻŽā§āĻ­āĻŦ, āĻ‰āĻĻāĻžāĻšāĻ°āĻŖāĻ¸ā§āĻŦāĻ°ā§‚āĻĒ, āĻāĻ‡;
  • āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āĻ¤ā§€ āĻĒāĻ¯āĻŧā§‡āĻ¨ā§āĻŸā§‡āĻ° āĻĢāĻ˛āĻ¸ā§āĻŦāĻ°ā§‚āĻĒ, āĻŦā§‡āĻļ āĻ•āĻ¯āĻŧā§‡āĻ•āĻŸāĻŋ GPU āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻ¸āĻ āĻŋāĻ• āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖā§‡āĻ° āĻ—āĻ¤āĻŋ āĻ¨āĻŋāĻ°ā§āĻŦāĻžāĻšāĻ¨ āĻ•āĻ°āĻž āĻ¸āĻŽā§āĻ­āĻŦ āĻ›āĻŋāĻ˛ āĻ¨āĻž;
  • āĻ†āĻ§ā§āĻ¨āĻŋāĻ• āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ• āĻ†āĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āĻšāĻžāĻ°ā§‡āĻ° āĻ…āĻ­āĻžāĻŦ āĻ°āĻ¯āĻŧā§‡āĻ›ā§‡, āĻŦāĻŋāĻļā§‡āĻˇ āĻ•āĻ°ā§‡ āĻ¯ā§‡āĻ—ā§āĻ˛āĻŋ āĻ‡āĻŽā§‡āĻœāĻ¨ā§‡āĻŸā§‡ ​​āĻĒā§āĻ°āĻžāĻ•-āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŋāĻ¤;
  • āĻ•ā§‹āĻ¨ āĻāĻ• āĻšāĻ•ā§āĻ° āĻ¨ā§€āĻ¤āĻŋ āĻāĻŦāĻ‚ āĻŦā§ˆāĻˇāĻŽā§āĻ¯āĻŽā§‚āĻ˛āĻ• āĻļāĻŋāĻ•ā§āĻˇāĻžāĻ° āĻšāĻžāĻ° (āĻ•ā§‹āĻ¸āĻžāĻ‡āĻ¨ āĻ…ā§āĻ¯āĻžāĻ¨āĻŋāĻ˛āĻŋāĻ‚ āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ…āĻ¨ā§āĻ°ā§‹āĻ§ā§‡ āĻ›āĻŋāĻ˛ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻŋāĻ¤, āĻ§āĻ¨ā§āĻ¯āĻŦāĻžāĻĻ āĻ¸ā§āĻ•āĻžāĻ‡āĻĄāĻžāĻ¨).

āĻāĻ‡ āĻĒā§āĻ°āĻ¤āĻŋāĻ¯ā§‹āĻ—āĻŋāĻ¤āĻž āĻĨā§‡āĻ•ā§‡ āĻ•ā§€ āĻ•ā§€ āĻĻāĻ°āĻ•āĻžāĻ°ā§€ āĻœāĻŋāĻ¨āĻŋāĻ¸ āĻļāĻŋāĻ–ā§‡āĻ›ā§‡:

  • āĻ…āĻĒā§‡āĻ•ā§āĻˇāĻžāĻ•ā§ƒāĻ¤ āĻ•āĻŽ-āĻĒāĻžāĻ“āĻ¯āĻŧāĻžāĻ° āĻšāĻžāĻ°ā§āĻĄāĻ“āĻ¯āĻŧā§āĻ¯āĻžāĻ°ā§‡, āĻ†āĻĒāĻ¨āĻŋ āĻŦā§āĻ¯āĻĨāĻž āĻ›āĻžāĻĄāĻŧāĻžāĻ‡ āĻļāĻžāĻ˛ā§€āĻ¨ (āĻ°ā§āĻ¯āĻžāĻŽā§‡āĻ° āĻ†āĻ•āĻžāĻ°ā§‡āĻ° āĻ…āĻ¨ā§‡āĻ• āĻ—ā§āĻŖ) āĻ­āĻ˛āĻŋāĻ‰āĻŽ āĻĄā§‡āĻŸāĻž āĻ¨āĻŋāĻ¯āĻŧā§‡ āĻ•āĻžāĻœ āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨āĨ¤ āĻĒā§āĻ˛āĻžāĻ¸ā§āĻŸāĻŋāĻ• āĻŦā§āĻ¯āĻžāĻ— āĻĄā§‡āĻŸāĻž.āĻŸā§āĻ¯āĻžāĻŦāĻ˛ āĻŸā§‡āĻŦāĻŋāĻ˛ā§‡āĻ° āĻ‡āĻ¨-āĻĒā§āĻ˛ā§‡āĻ¸ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ā§‡āĻ° āĻ•āĻžāĻ°āĻŖā§‡ āĻŽā§‡āĻŽāĻ°āĻŋ āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖ āĻ•āĻ°ā§‡, āĻ¯āĻž āĻ¤āĻžāĻĻā§‡āĻ° āĻ…āĻ¨ā§āĻ˛āĻŋāĻĒāĻŋ āĻ•āĻ°āĻž āĻāĻĄāĻŧāĻŋāĻ¯āĻŧā§‡ āĻ¯āĻžāĻ¯āĻŧ āĻāĻŦāĻ‚ āĻ¸āĻ āĻŋāĻ•āĻ­āĻžāĻŦā§‡ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž āĻšāĻ˛ā§‡, āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸāĻŋāĻ‚ āĻ­āĻžāĻˇāĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ•āĻžāĻ›ā§‡ āĻĒāĻ°āĻŋāĻšāĻŋāĻ¤ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻ¸āĻ°āĻžā§āĻœāĻžāĻŽāĻ—ā§āĻ˛āĻŋāĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻāĻ° āĻ•ā§āĻˇāĻŽāĻ¤āĻžāĻ—ā§āĻ˛āĻŋ āĻĒā§āĻ°āĻžāĻ¯āĻŧ āĻ¸āĻŦāĻ¸āĻŽāĻ¯āĻŧāĻ‡ āĻ¸āĻ°ā§āĻŦā§‹āĻšā§āĻš āĻ—āĻ¤āĻŋ āĻĒā§āĻ°āĻĻāĻ°ā§āĻļāĻ¨ āĻ•āĻ°ā§‡āĨ¤ āĻāĻ•āĻŸāĻŋ āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸ā§‡ āĻĄā§‡āĻŸāĻž āĻ¸āĻ‚āĻ°āĻ•ā§āĻˇāĻŖ āĻ•āĻ°āĻž āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻ…āĻ¨ā§‡āĻ• āĻ•ā§āĻˇā§‡āĻ¤ā§āĻ°ā§‡ āĻ¸āĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻĄā§‡āĻŸāĻžāĻ¸ā§‡āĻŸāĻ•ā§‡ RAM-āĻ¤ā§‡ āĻšā§‡āĻĒā§‡ āĻĻā§‡āĻ“āĻ¯āĻŧāĻžāĻ° āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻ•ā§‡ āĻšāĻŋāĻ¨ā§āĻ¤āĻž āĻ•āĻ°āĻ¤ā§‡ āĻĻā§‡āĻ¯āĻŧ āĻ¨āĻžāĨ¤
  • āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°ā§‡ R-āĻ āĻ§ā§€āĻ° āĻĢāĻžāĻ‚āĻļāĻ¨ C++-āĻ āĻĻā§āĻ°ā§āĻ¤ āĻĢāĻžāĻ‚āĻļāĻ¨ āĻĻāĻŋāĻ¯āĻŧā§‡ āĻĒā§āĻ°āĻ¤āĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻ•āĻ°āĻž āĻ¯ā§‡āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡ Rcpp. āĻāĻ›āĻžāĻĄāĻŧāĻž āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻ˛ā§‡ RcppThread āĻŦāĻž Rcpp āĻ¸āĻŽāĻžāĻ¨ā§āĻ¤āĻ°āĻžāĻ˛, āĻ†āĻŽāĻ°āĻž āĻ•ā§āĻ°āĻ¸-āĻĒā§āĻ˛ā§āĻ¯āĻžāĻŸāĻĢāĻ°ā§āĻŽ āĻŽāĻžāĻ˛ā§āĻŸāĻŋ-āĻĨā§āĻ°ā§‡āĻĄā§‡āĻĄ āĻ‡āĻŽāĻĒā§āĻ˛āĻŋāĻŽā§‡āĻ¨ā§āĻŸā§‡āĻļāĻ¨ āĻĒāĻžāĻ‡, āĻ¤āĻžāĻ‡ R āĻ˛ā§‡āĻ­ā§‡āĻ˛ā§‡ āĻ•ā§‹āĻĄāĻŸāĻŋāĻ•ā§‡ āĻ¸āĻŽāĻžāĻ¨ā§āĻ¤āĻ°āĻžāĻ˛ āĻ•āĻ°āĻžāĻ° āĻĻāĻ°āĻ•āĻžāĻ° āĻ¨ā§‡āĻ‡āĨ¤
  • āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœ Rcpp C++ āĻāĻ° āĻ—ā§āĻ°ā§āĻ¤āĻ° āĻœā§āĻžāĻžāĻ¨ āĻ›āĻžāĻĄāĻŧāĻžāĻ‡ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻž āĻ¯ā§‡āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡, āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ā§€āĻ¯āĻŧ āĻ¨ā§āĻ¯ā§‚āĻ¨āĻ¤āĻŽ āĻ°ā§‚āĻĒāĻ°ā§‡āĻ–āĻž āĻĻā§‡āĻ“āĻ¯āĻŧāĻž āĻ†āĻ›ā§‡ āĻāĻ–āĻžāĻ¨ā§‡. āĻŦā§‡āĻļ āĻ•āĻ¯āĻŧā§‡āĻ•āĻŸāĻŋ āĻļā§€āĻ¤āĻ˛ āĻ¸āĻŋ-āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋāĻ° āĻœāĻ¨ā§āĻ¯ āĻšā§‡āĻĄāĻžāĻ° āĻĢāĻžāĻ‡āĻ˛ āĻāĻ•ā§āĻ¸āĻŸā§‡āĻ¨āĻ¸āĻ° CRAN-āĻ āĻ‰āĻĒāĻ˛āĻŦā§āĻ§, āĻ…āĻ°ā§āĻĨāĻžā§Ž, āĻĒā§āĻ°āĻ•āĻ˛ā§āĻĒāĻ—ā§āĻ˛āĻŋ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻĒāĻ°āĻŋāĻ•āĻžāĻ āĻžāĻŽā§‹ āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻž āĻšāĻšā§āĻ›ā§‡ āĻ¯āĻž āĻ°ā§‡āĻĄāĻŋāĻŽā§‡āĻĄ āĻšāĻžāĻ‡-āĻĒāĻžāĻ°āĻĢāĻ°āĻŽā§āĻ¯āĻžāĻ¨ā§āĻ¸ C++ āĻ•ā§‹āĻĄāĻ•ā§‡ R-āĻ¤ā§‡ āĻ¸āĻ‚āĻšāĻ¤ āĻ•āĻ°ā§‡āĨ¤ āĻ…āĻ¤āĻŋāĻ°āĻŋāĻ•ā§āĻ¤ āĻ¸ā§āĻŦāĻŋāĻ§āĻž āĻšāĻ˛ āĻ¸āĻŋāĻ¨āĻŸā§āĻ¯āĻžāĻ•ā§āĻ¸ āĻšāĻžāĻ‡āĻ˛āĻžāĻ‡āĻŸāĻŋāĻ‚ āĻāĻŦāĻ‚ RStudio-āĻ¤ā§‡ āĻāĻ•āĻŸāĻŋ āĻ¸ā§āĻŸā§āĻ¯āĻžāĻŸāĻŋāĻ• C++ āĻ•ā§‹āĻĄ āĻŦāĻŋāĻļā§āĻ˛ā§‡āĻˇāĻ•āĨ¤
  • āĻĄāĻ•āĻĒā§āĻŸ āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻĒāĻ°āĻžāĻŽāĻŋāĻ¤āĻŋ āĻ¸āĻš āĻ¸ā§āĻŦāĻ¯āĻŧāĻ‚āĻ¸āĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸ āĻšāĻžāĻ˛āĻžāĻ¨ā§‹āĻ° āĻ…āĻ¨ā§āĻŽāĻ¤āĻŋ āĻĻā§‡āĻ¯āĻŧāĨ¤ āĻāĻŸāĻŋ āĻāĻ•āĻŸāĻŋ āĻĻā§‚āĻ°āĻŦāĻ°ā§āĻ¤ā§€ āĻ¸āĻžāĻ°ā§āĻ­āĻžāĻ°ā§‡ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻ¸ā§āĻŦāĻŋāĻ§āĻžāĻœāĻ¨āĻ•, āĻ¸āĻšāĨ¤ āĻĄāĻ•āĻžāĻ° āĻ…āĻ§ā§€āĻ¨ā§‡ RStudio-āĻ¤ā§‡, āĻ¨āĻŋāĻ‰āĻ°āĻžāĻ˛ āĻ¨ā§‡āĻŸāĻ“āĻ¯āĻŧāĻžāĻ°ā§āĻ•ā§‡āĻ° āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖ āĻ¨āĻŋāĻ¯āĻŧā§‡ āĻ…āĻ¨ā§‡āĻ• āĻ˜āĻ¨ā§āĻŸāĻž āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž-āĻ¨āĻŋāĻ°ā§€āĻ•ā§āĻˇāĻž āĻ•āĻ°āĻž āĻ…āĻ¸ā§āĻŦāĻŋāĻ§āĻžāĻœāĻ¨āĻ•, āĻāĻŦāĻ‚ āĻ¸āĻžāĻ°ā§āĻ­āĻžāĻ°ā§‡ IDE āĻ‡āĻ¨āĻ¸ā§āĻŸāĻ˛ āĻ•āĻ°āĻž āĻ¸āĻ°ā§āĻŦāĻĻāĻž āĻ¨ā§āĻ¯āĻžāĻ¯āĻŧāĻ¸āĻ™ā§āĻ—āĻ¤ āĻ¨āĻ¯āĻŧāĨ¤
  • āĻĄāĻ•āĻžāĻ° OS āĻāĻŦāĻ‚ āĻ˛āĻžāĻ‡āĻŦā§āĻ°ā§‡āĻ°āĻŋāĻ° āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āĻ¨ āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖ āĻ¸āĻš āĻĄā§‡āĻ­ā§‡āĻ˛āĻĒāĻžāĻ°āĻĻā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻĢāĻ˛āĻžāĻĢāĻ˛ā§‡āĻ° āĻ•ā§‹āĻĄ āĻŦāĻšāĻ¨āĻ¯ā§‹āĻ—ā§āĻ¯āĻ¤āĻž āĻāĻŦāĻ‚ āĻĒā§āĻ¨āĻ°ā§āĻ¤ā§āĻĒāĻžāĻĻāĻ¨āĻ¯ā§‹āĻ—ā§āĻ¯āĻ¤āĻž āĻ¨āĻŋāĻļā§āĻšāĻŋāĻ¤ āĻ•āĻ°ā§‡, āĻ¸ā§‡āĻ‡āĻ¸āĻžāĻĨā§‡ āĻ¸āĻžāĻ°ā§āĻ­āĻžāĻ°āĻ—ā§āĻ˛āĻŋāĻ¤ā§‡ āĻ¸āĻŽā§āĻĒāĻžāĻĻāĻ¨ā§‡āĻ° āĻ¸āĻšāĻœāĻ¤āĻžāĨ¤ āĻ†āĻĒāĻ¨āĻŋ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻāĻ•āĻŸāĻŋ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻĻāĻŋāĻ¯āĻŧā§‡ āĻ¸āĻŽāĻ—ā§āĻ° āĻĒā§āĻ°āĻļāĻŋāĻ•ā§āĻˇāĻŖ āĻĒāĻžāĻ‡āĻĒāĻ˛āĻžāĻ‡āĻ¨ āĻšāĻžāĻ˛ā§ āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨āĨ¤
  • Google āĻ•ā§āĻ˛āĻžāĻ‰āĻĄ āĻŦā§āĻ¯āĻ¯āĻŧāĻŦāĻšā§āĻ˛ āĻšāĻžāĻ°ā§āĻĄāĻ“āĻ¯āĻŧā§āĻ¯āĻžāĻ° āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻŦāĻžāĻœā§‡āĻŸ-āĻŦāĻžāĻ¨ā§āĻ§āĻŦ āĻ‰āĻĒāĻžāĻ¯āĻŧ, āĻ•āĻŋāĻ¨ā§āĻ¤ā§ āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻ¸āĻžāĻŦāĻ§āĻžāĻ¨ā§‡ āĻ•āĻ¨āĻĢāĻŋāĻ—āĻžāĻ°ā§‡āĻļāĻ¨ āĻ¨āĻŋāĻ°ā§āĻŦāĻžāĻšāĻ¨ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻŦā§‡āĨ¤
  • āĻĒā§ƒāĻĨāĻ• āĻ•ā§‹āĻĄā§‡āĻ° āĻŸā§āĻ•āĻ°ā§‹āĻ—ā§āĻ˛āĻŋāĻ° āĻ—āĻ¤āĻŋ āĻĒāĻ°āĻŋāĻŽāĻžāĻĒ āĻ•āĻ°āĻž āĻ–ā§āĻŦ āĻĻāĻ°āĻ•āĻžāĻ°ā§€, āĻŦāĻŋāĻļā§‡āĻˇāĻ¤ āĻ¯āĻ–āĻ¨ R āĻāĻŦāĻ‚ C++ āĻāĻŦāĻ‚ āĻĒā§āĻ¯āĻžāĻ•ā§‡āĻœā§‡āĻ° āĻ¸āĻžāĻĨā§‡ āĻāĻ•āĻ¤ā§āĻ°āĻŋāĻ¤ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧ āĻ¨ā§āĻ¯āĻžāĻ¯āĻŧāĻžāĻ¸āĻ¨ - āĻāĻ›āĻžāĻĄāĻŧāĻžāĻ“ āĻ–ā§āĻŦ āĻ¸āĻšāĻœāĨ¤

āĻ¸āĻžāĻŽāĻ—ā§āĻ°āĻŋāĻ•āĻ­āĻžāĻŦā§‡ āĻāĻ‡ āĻ…āĻ­āĻŋāĻœā§āĻžāĻ¤āĻž āĻ–ā§āĻŦāĻ‡ āĻĢāĻ˛āĻĒā§āĻ°āĻ¸ā§‚ āĻ›āĻŋāĻ˛ āĻāĻŦāĻ‚ āĻ†āĻŽāĻ°āĻž āĻ‰āĻ¤ā§āĻĨāĻžāĻĒāĻŋāĻ¤ āĻ•āĻŋāĻ›ā§ āĻ¸āĻŽāĻ¸ā§āĻ¯āĻž āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻ•āĻžāĻœ āĻšāĻžāĻ˛āĻŋāĻ¯āĻŧā§‡ āĻ¯āĻžāĻšā§āĻ›āĻŋāĨ¤

āĻ‰āĻ¤ā§āĻ¸: www.habr.com

āĻāĻ•āĻŸāĻŋ āĻŽāĻ¨ā§āĻ¤āĻŦā§āĻ¯ āĻœā§āĻĄāĻŧā§āĻ¨