๐Ÿ˜ŠAI๋ฅผ ์ด์šฉํ•ด์„œ ์† ์ œ์Šค์ณ๋ฅผ ์ธ์‹ํ•ด๋ณด์ž.

,

๋ฌด์—‡์„ ๋งŒ๋“ค๊นŒ ๊ณ ๋ฏผ.

์–ด๋‘์šด ์ด๋ฏธ์ง€๋ฅผ ๋ฐ๊ฒŒ ๋งŒ๋“œ๋Š” ๋ชจ๋ธ์„ ๋งŒ๋“ค๊ณ  ๋ˆ„๊ฒŸ์œผ๋กœ ์‹ธ์„œ ์˜ฌ๋ ค๋„ ๋ดค์Šต๋‹ˆ๋‹ค.
๋งŽ์€ ๋ถ„๋“ค์ด ๊ด€์‹ฌ์„ ๊ฐ€์ ธ์ฃผ์‹œ๊ณ  ๋Œ“๊ธ€์„ ๋‹ฌ์•„ ์ฃผ์‹œ๋‹ˆ ์žฌ๋ฏธ๊ฐ€ ์žˆ๊ตฐ์š”..
์ด๋ฒˆ์—๋Š” ์† ์ œ์Šค์ณ๋ฅผ ์ธ์‹ํ•˜๋Š” (์—ฐ์† ๋™์˜์ƒ) ๋ชจ๋ธ์„ ๋งŒ๋“ค๊ณ  ๊ทธ ๊ณผ์ •์„ ๋ˆ„๊ฒŸ์œผ๋กœ ์˜ฌ๋ ค๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
์–ผ๊ตด์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๋ˆ„๊ฒŸ๋„ ์ƒ๊ฐํ•ด ๋ณด์•˜๋Š”๋ฐ. ๋„ˆ๋ฌด ์ข‹์€ ๊ฒƒ๋“ค์ด ๋งŽ๋”๊ตฐ์š”.
๋’ค์ ธ๋ณด๋‹ˆ ์ œ์Šค์ณ๋Š” ๋งŽ์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์‹ค ํšŒ์‚ฌ์—์„œ ๋น„์Šทํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•œ ์ ์ด ์žˆ๋Š”๋ฐ
์•„์‹œ๋‹ค์‹œํ”ผ ํšŒ์‚ฌ์™€ ๊ด€๋ จ๋œ ํ”„๋กœ์ ํŠธ๋Š” ์–ด๋– ํ•œ ์ข‹์€ ๊ธฐ์ˆ ์„ ๊ฐ€์ ธ๋‹ค ๋ถ™์—ฌ๋„ ์žฌ๋ฏธ๊ฐ€ ์—†๊ณ  ์ŠคํŠธ๋ ˆ์Šค๋งŒ ์Œ“์ด๋”๊ตฐ์š”..
์ด๋ฒˆ์—๋Š” ์ž์‹์ฒ˜๋Ÿผ ์• ์ •์„ ๊ฐ€์ง€๊ณ  ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์“ธ๋งŒํ•œ ๋ฐ์ดํ„ฐ์…‹ ์กฐ์‚ฌ


์ด๊ฒŒ ์“ธ๋งŒํ•ด ๋ณด์ด๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋ฐ๋ชจ๋กœ ์ปดํ“จํ„ฐ ์•ž์— ์•‰์•„์„œ ์ œ์Šค์ณ ๋™์ž‘์„ ๋Œ€๋ถ€๋ถ„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—
(๋ฐ์ดํ„ฐ์…‹์˜ ๊ตฌ์„ฑ์ด ๋‹ค ๋ชจ๋‹ˆํ„ฐ์•ž์— ์•‰์•„ ์žˆ๋Š” ์‚ฌ๋žŒ์˜ ์ œ์Šค์ณ๋ฅผ ๊ธฐ๋กํ•จ)
๋ชฉ์ ์— ๋ถ€ํ•ฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ผ์ด์„ผ์Šค


๋‹ค ์ฝ์–ด๋ณด๋‹ˆ ์ƒ์—…์ ์ธ ์‚ฌ์šฉ์€ ๋ชปํ•˜๊ณ  ๋น„์˜๋ฆฌ๋ชฉ์ ์œผ๋กœ๋Š” ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

๋‚ด์ผ๊นŒ์ง€ ์‰ฌ์šด ๋…ผ๋ฌธ ์ฐพ๊ธฐ.

์Œโ€ฆ ๋”ฅ๋Ÿฌ๋‹ ๋…ผ๋ฌธ์ค‘์—์„œ ์‰ฌ์šฐ๋ฉด์„œ ๊ทธ๋Ÿด์‹ธํ•˜๊ณ  ์ง€์  ์š•๊ตฌ๋ฅผ ์ถฉ์กฑํ•  ๋…ผ๋ฌธ์„ ์ฐพ์•„์„œ ๋‚ด์ผ๊นŒ์ง€ ๋’ค์ ธ๋ณผ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค. ๋˜๋„๋ก์ด๋ฉด ํšŒ์‚ฌ์—์„œ ์‚ฌ์šฉํ•œ ๋…ผ๋ฌธ์„ ํ”ผํ•ด์„œ ์ƒˆ๋กœ์šด ๋„์ „์  ๋ชจ๋ธ์ด ๋ˆˆ์— ๋ณด์ด๋ฉด ์ข‹๊ฒ ๊ตฐ์š”..

๊ทธ ์™ธ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ ๊ด€๋ จ ๋ฌธ์˜

ํ˜น์‹œ powershell ์ž˜ํ•˜์‹œ๋Š” ๋ถ„ ๊ณ„์‹ ๊ฐ€์š”?.. ๋ญ”๊ฐ€ ์žฌ๋ฏธ๋‚œ ์•„์ด๋””์–ด๊ฐ€ ์žˆ๋Š”๋ฐ ๊ฐ™์ด ํ•ด๋ณด์‹ค ๋ถ„ ์ฐพ์Šต๋‹ˆ๋‹ค.
๊ด€์‹ฌ ์žˆ์œผ์‹œ๋ฉด ๋Œ“๊ธ€ ๋‚จ๊ฒจ์ฃผ์„ธ์š” ใ… 

8 Likes

๋น„๊ตํ•ด๋ณด์ž

์•„์นด์ด๋ธŒ์—์„œ ๋น„๊ต์  3d convolution์„ ์ด์šฉํ•œ ์„ค๊ณ„๋ฅผ ์ฑ„์šฉํ•œ ๋ชจ๋ธ๋งŒ ๋Œ€์ถฉ ๊ณจ๋ผ๋‹ค๊ฐ€ (์ฃผ๊ด€์ ์ธ ๊ด€์ ์œผ๋กœ ์‰ฌ์šด๊ฒƒ๋งŒ)
๋น„๊ตํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์ฉโ€ฆ ์ถ”๋ ค์ง€๊ณ  ์ถ”๋ ค์ง„ ๋…€์„์ด .. ํšŒ์‚ฌ์—์„œ ์“ด ๋…€์„์ด๋ผ๋‹ˆโ€ฆ


https://arxiv.org/pdf/1904.02422
์ด ๋…ผ๋ฌธ์˜ ์žฌ๋ฏธ์žˆ๋Š” ์ ์€ ๊ธฐ์กด์— ์œ ๋ช…ํ•œ 2D ์ปจ๋ณผ๋ฃจ์…˜ ๋ชจ๋ธ์„ 3D ์ปจ๋ณผ๋ฃจ์…˜์œผ๋กœ ๋‚ด๋ถ€ ๋ธ”๋ก์„ ๋ฐ”๊พธ์–ด
Video Classification๋ถ„์•ผ์— ์„ฑ๋Šฅ ๋น„๊ต๋ฅผ ์‹œ๋„ํ–ˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.
์ด ๋…ผ๋ฌธ 1์žฅ ๋‚ด์— ์—ฌ๋Ÿฌ ๋ชจ๋ธ์„ ๊ตฌํ˜„ํ•˜์—ฌ ์„ฑ๋Šฅ ๋น„๊ต๋ฅผ ์‹œ๋„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด 1์žฅ์˜ ๋…ผ๋ฌธ ๋‚ด์—์„œ๋„ ๋ชจ๋ธ์„ ์„ ํƒํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค
์ด ๋…ผ๋ฌธ์—์„œ ์‚ฌ๋‚ด์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๋•Œ ์‚ฌ์šฉํ–ˆ๋˜ ๋ชจ๋ธ์€ ์•„๋ž˜์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์‚ฌ๋‚ด์—์„œ๋Š” ์ ๋‹นํ•œ ์„ฑ๋Šฅ์˜ ์ ๋‹นํ•œ speed๋ฅผ ๊ฐ€์ง„ MobileNetV2 3D๋ฒ„์ „์„ ๊ฐ€์ ธ๋‹ค๊ฐ€ ์ผ์—ˆ๋Š”๋ฐ์š”.
์Œโ€ฆ ๊ทธ๋Ÿผ ๋˜‘๊ฐ™์€ ๊ฑธ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์žฌ๋ฏธ๋„ ์—†๊ณ โ€ฆ ์ด ํ† ์ด ํ”„๋กœ์ ํŠธ์˜ ์ทจ์ง€์™€ ๋งž์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— -_-โ€ฆ
์ด ๋…ผ๋ฌธ์—์„œ ์ปจ๋ฒ„์ „ ํ•˜์ง€ ์•Š์€ 2d๋ชจ๋ธ์„ 3d ์ปจ๋ณผ๋ฃจ์…˜์œผ๋กœ ๋ฆฌ์–ด๋ ˆ์ธ์ง€ํ•˜๋Š” ์‹œ๋„๋ฅผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์–ด๋–ค 2D ์ปจ๋ณผ๋ฃจ์…˜ ๋ชจ๋ธ์„ ๋ฆฌ์–ด๋ ˆ์ธ์ง€ํ•  ๊ฒƒ์ธ๊ฐ€?


์•„๊นŒ ์œ„์—์„œ ๋ณธ Video Classification ๋…ผ๋ฌธ์ด ๋งˆ์ง€๋ง‰ ์ˆ˜์ •๋œ ์ผ์ž๊ฐ€ 2021๋…„์ธ๋ฐ.. ๊ทธ ์ดํ›„๋กœ Convolution๋ถ„์•ผ์—์„œ ์„ฑ๋Šฅ์„ ์žก์œผ๋ฉด์„œ ์•„์ฃผ ๋น ๋ฅธ ์†๋„์˜ ์ตœ์ ํ™” ๋ชจ๋ธ๋“ค์ด ๋ช‡ ๊ฐœ๊ฐ€ ๋‚˜์™”์Šต๋‹ˆ๋‹ค.
์ œ๊ฐ€ ๊ธ€์„ ์ ์œผ๋ฉด์„œ ๋”ฑ ์ƒ๊ฐ์ด ๋‚˜๋Š” ์•„์ฃผ ๊ฐ€๋ฒผ์˜จ ๋ชจ๋ธ์ด GhostNet์ด๋ผ๊ณ  ์žˆ๋Š”๋ฐ ์˜ˆ์ „์— ๊ตฌํ˜„ํ•ด๋ณธ ๊ธฐ์–ต์ด ์žˆ์–ด์„œ ์ œ repository๋ฅผ ๋’ค์ ธ๋ณด๋‹ˆ Layer ๋ชจ๋“ˆ์ด ์žˆ๋”๊ตฐ์š”

์ œ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ๊ณต๋ถ€ํ•œ ๋ชจ๋ธ ์„ค๊ณ„์— ๋“ค์–ด๊ฐ€๋Š” ๋ชจ๋“  ๋ ˆ์ด์–ด ๋ชจ๋“ˆ (์‹์žฌ๋ฃŒ๊ฐ™์€ ๋…€์„)๋“ค์ด ์œ„ ๋งํฌ์— ๋‹ค ๋“ค์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณ ์ŠคํŠธ ๋ชจ๋“ˆ V1์ด ์žˆ๊ตฐ์š”.. ๊ธฐ์–ต์„ ๋”๋“ฌ์–ด ๊ฐ€๋ฉด์„œ ์ด Ghost๋ชจ๋“ˆV1 2D์šฉ์„ 3D ์ปจ๋ณผ๋ฃจ์…˜์œผ๋กœ ๋ฐ”๊พธ์–ด์„œ Video Classification์„ ์‹œ๋„ํ•˜๋ฉด ์†๋„์™€ ์„ฑ๋Šฅ์„ ์žก์„ ์ˆ˜ ์žˆ์ง€ ์•Š์„๊ฐ€ ์ƒ๊ฐ๋ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ ์ œ๊ฐ€ ์ผ์— ๋งค๋ชฐ๋˜์–ด ์žˆ๋Š” ๋™์•ˆ GhostNetV1 (GhostModule์„ ์‚ฌ์šฉํ•˜๋Š” ๋…ผ๋ฌธ)์€ ๋ฒŒ์จ V3๊นŒ์ง€ ๋‚ด๋†“์•˜๊ตฐ์š”..

2020๋…„ V1 ๋ฒ„์ „๊ณผ


https://arxiv.org/pdf/1911.11907

2024๋…„ V3 ๋ฒ„์ „๊นŒ์ง€


https://arxiv.org/pdf/2404.11202

๋…ผ๋ฌธ ์ €์ž ๋ถ„๋“ค์ด ์—ด์‹ฌํžˆ ์—ฐ๊ตฌ๋ฅผ ํ•˜๊ณ  ๊ณ„์…จ๊ตฐ์š”.
Transformer๊ฐ€ ํŒ์น˜๋Š” ์ด ์„ธ์ƒ์—์„œ ์—ฌ์ „ํžˆ ๊ฐ„๋‹จํ•œ ์•„์ด๋””์–ด์™€ Convolution๋งŒ์œผ๋กœ ์„ฑ๋Šฅ๊ณผ ๊ฒฝ๋Ÿ‰์„ฑ์„ ์—ฐ๊ตฌํ•˜์‹œ๋Š” ๊ฒƒ์„ ๋ณด๋‹ˆ ๋†€๋ผ์šธ ๋”ฐ๋ฆ„์ž…๋‹ˆ๋‹ค.

2 Likes

๊ธฐ์กด ๊ณ ์ŠคํŠธ ๋ชจ๋“ˆ 2D โ†’ 3D ์ปจ๋ณผ๋ฃจ์…˜ ์Šค์™‘

๊ณ ์ŠคํŠธ๋„ท ๋…ผ๋ฌธ ๋งํฌ : https://arxiv.org/pdf/1911.11907
๊ธฐ์กด์— ๋งŒ๋“ค์–ด ๋†“์€ ๊ณ ์ŠคํŠธ๋„ท ๋ชจ๋“ˆ์—์„œ 2D Convolution๋ถ€๋ถ„์„ 3D ์ปจ๋ณผ๋ฃจ์…˜์œผ๋กœ ๋ณ€๊ฒฝ ๋ฐ ๊ฐ„๋‹จํ•œ ๋ชจ๋ธ์„ ๋งŒ๋“ค์–ด์„œ ํ•™์Šตํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์™œ ๊ณ ์ŠคํŠธ๋„ท์ด๋ƒ

์•„๋ž˜ ๊ทธ๋ฆผ์€ ๋…ผ๋ฌธ์—์„œ ๋ฐœ์ตœํ•œ ๊ทธ๋ฆผ์ธ๋ฐ์š”.
์ผ๋ฐ˜ ๊ฐœ๋ฐœ์ž๋“ค๋„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ์„ค๋ช…์œผ๋กœ๋Š” ์Œ..
๊ณ ์ŠคํŠธ๋„ท ์ €์ž๋“ค์ด ์„ฑ๋Šฅ์ด ์ข‹์€ ๋ชจ๋ธ๋“ค์˜ ํ”ผ์ณ๋ฅผ ๊นŒ์„œ ์กฐ์‚ฌ๋ฅผ ๋‹ค ํ•ด๋ณด๋‹ˆ
๋น„์Šทํ•˜๊ฒŒ ์ƒ๊ธด ํ”ผ์ณ๋“ค์ด ๋งŽ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธ ํ–ˆ์Šต๋‹ˆ๋‹ค.
(ํ•ญ์ƒ ๋น„์Šทํ•˜๊ฒŒ ์ƒ๊ธด ํ”ผ์ณ๊ฐ€ ๋งŽ๋‹ค๊ณ  ์„ฑ๋Šฅ์ด ์ข‹๋‹ค๋Š” ๊ฑด ์•„๋‹™๋‹ˆ๋‹ค. ๋•Œ์— ๋”ฐ๋ผ์„œ ๋‹ค๋ฆ…๋‹ˆ๋‹ค)


๊ทธ๋Ÿผ ์• ์‹œ๋‹น์ดˆ ํž˜๊ฒน๊ฒŒ ์ปจ๋ณผ๋ฃจ์…˜ ํ•„ํ„ฐ ๊ฐฏ์ˆ˜๋ฅผ ๋Š˜๋ ค์„œ ๋น„์Šทํ•œ ๋…€์„ ๋งŒ๋“ค์ง€ ๋ง๊ณ 
์˜†์— ์žˆ๋Š” ํ”ผ์ณ๋ž‘ ์œ ์‚ฌํ•˜๊ฒŒ ๋น„์Šทํ•˜๊ฒŒ ๋‹ฎ๋„๋ก ์˜†์— ์žˆ๋Š” ๋…€์„์„ ๋น„๋ฒผ์„œ (์ปจ๋ณผ๋ฃจ์…˜) ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค์ž๋Š” ๊ฒƒ์ด ์•„์ด๋””์–ด์ž…๋‹ˆ๋‹ค.
(์ด๋•Œ Depth wise conolution์„ ํ•˜๋Š”๋ฐ ์ด๊ฑด ๋„ˆ๋ฌด ๊ธธ์–ด์ง€๋‹ˆโ€ฆ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.)

๊ทธ๋ž˜์„œ.. ์ด ๊ณ ์ŠคํŠธ ๋ชจ๋“ˆ์ด ์ ์€ ์—ฐ์‚ฐ์œผ๋กœ ๋น„์Šทํ•œ ํ”ผ์ณ๋ฅผ ๋งŽ์ด ๋งŒ๋“ค์–ด๋‚ด๋Š”๋ฐ ์žฅ์ ์ด ์žˆ์œผ๋‹ˆ ์ด ์—ฐ์‚ฐ๋Ÿ‰ ์ž‘์€ ๊ณ ์ŠคํŠธ ๋ชจ๋“ˆ์„ Gesture ์ธ์‹์— ๋งž๊ฒŒ ์ˆ˜์ •ํ•˜์—ฌ ์จ๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ณผ๊ฑฐ์— ์ž‘์„ฑํ•ด ๋†“์€ ์ฝ”๋“œ

class GhostModule(torch.nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=1, ratio=2, dw_size=3, stride=1, use_activation=True, activation=torch.nn.ReLU):
        super(GhostModule, self).__init__()
        self.oup = out_channels
        init_channels = math.ceil(out_channels / ratio)
        new_channels = init_channels*(ratio-1)

        self.primary_conv = torch.nn.Sequential(
            torch.nn.Conv2d(in_channels, init_channels, kernel_size, stride, kernel_size//2, bias=False),
            torch.nn.BatchNorm2d(init_channels),
            activation(inplace=True) if use_activation else torch.nn.Sequential(),
        )

        self.cheap_operation = torch.nn.Sequential(
            torch.nn.Conv2d(init_channels, new_channels, dw_size, 1, dw_size//2, groups=init_channels, bias=False),
            torch.nn.BatchNorm2d(new_channels),
            activation(inplace=True) if use_activation else torch.nn.Sequential(),
        )

    def forward(self, x):
        x1 = self.primary_conv(x)
        x2 = self.cheap_operation(x1)
        out = torch.cat([x1,x2], dim=1)
        return out[:,:self.oup,:,:]

ํ…Œ์ŠคํŠธ ์ค‘์ธ ๋ณ€๊ฒฝ๋œ ์ฝ”๋“œ

import torch
import math


class GhostLayer3D(torch.nn.Module):
    def __init__(self,
                 in_channels: int,
                 out_channels: int,
                 ratio: int = 2,
                 stride=1, #T, H ,W 
                 use_activation: bool = True,
                 activation=torch.nn.ReLU):
        super().__init__()

        if ratio < 1:
            raise Exception("ratio must be >= 1")
        self.oup = out_channels


        if isinstance(stride, int):
            stride_3d = (stride, stride, stride)
        else:
            if len(stride) != 3:
                raise Exception("stride must be int or tuple of length 3")
            stride_3d = tuple(int(s) for s in stride)

        init_channels = int(math.ceil(out_channels / ratio))
        new_channels = init_channels * (ratio - 1)

        # ์‹œ๊ฐ„๊ณผ ๊ณต๊ฐ„๋งŒ ๋น„๋น„๊ธฐ
        self.primary_conv = torch.nn.Sequential(
            torch.nn.Conv3d(
                in_channels=in_channels,
                out_channels=init_channels,
                kernel_size=(3, 3, 3),
                stride=stride_3d,
                padding=(1, 1, 1),
                bias=False
            ),
            torch.nn.BatchNorm3d(init_channels),
            activation(inplace=True) if use_activation else torch.nn.Identity(),
        )

        # ๊ณต๊ฐ„๋งŒ ๋น„๋น„๊ธฐ
        if new_channels > 0:
            self.cheap_operation = torch.nn.Sequential(
                torch.nn.Conv3d(
                    in_channels=init_channels,
                    out_channels=new_channels,
                    kernel_size=(1, 3, 3),
                    stride=(1, 1, 1),
                    padding=(0, 1, 1),
                    groups=init_channels,     # ๋ށ์Šค์™€์ด์ฆˆ ์ปจ๋ณผ๋ฃจ์…˜ 
                    bias=False
                ),
                torch.nn.BatchNorm3d(new_channels),
                activation(inplace=True) if use_activation else torch.nn.Identity(),
            )
        else:
            self.cheap_operation = None

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x1 = self.primary_conv(x) 
        if self.cheap_operation is None:
            out = x1
        else:
            x2 = self.cheap_operation(x1) 
            out = torch.cat([x1, x2], dim=1) 

        return out[:, :self.oup, :, :, :]

์˜์ƒ Gesture ์ธ์‹์—์„œ ํ•ต์‹ฌ ๊ณผ์ œ

์ œ์Šค์ณ๋Š” ์ผ๋ฐ˜ ์ •์ง€ ์˜์ƒ๊ณผ ๋‹ค๋ฅด๊ฒŒ T0~Tn ๊นŒ์ง€ ํ๋ฅด๋Š” ์ •์ง€ ์˜์ƒ๋“ค์˜ ๋ฌถ์Œ์„ ๋‹ค ๋ณด์•„์•ผ๋งŒ
๋ชจ๋ธ์ด ์–ป๊ณ ์žํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์˜ˆ์ธก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
(์˜ˆ: ์†์„ ํ”๋“ค๊ฑฐ๋‚˜, ์†์„ ๋จธ๋ฆฌ ์œ„๋กœ ์˜ฌ๋ฆฐ๋‹ค๊ฑฐ๋‚˜, ๋™์ ์ธ ์›€์ง์ž„ ํ•œ ์„ธํŠธ์˜ ๋ถ„์„)

๊ทธ๋ž˜์„œ ์ผ๋ฐ˜์ ์ธ 2D ์ปจ๋ณผ๋ฃจ์…˜์€ R,G,B ์ƒ‰์ƒ์ด ์žˆ๋Š” ์ด๋ฏธ์ง€๋‚ด์—์„œ Width์™€ Height ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ์›€์ง์ด์ง€๋งŒ. 3D ์ปจ๋ณผ๋ฃจ์…˜ ์‹œ๊ฐ„ ์ถ• T๋ฅผ ์ดํ•ดํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— T์ถ•์œผ๋กœ ์ปจ๋ณผ๋ฃจ์…˜ ์ปค๋„์ด ์›€์ง์ด๊ฒŒ ๋””์ž์ธ ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

2D ์ปจ๋ณผ๋ฃจ์…˜ ์˜ˆ์‹œ :

2dconv

3D ์ปจ๋ณผ๋ฃจ์…˜ ์˜ˆ์‹œ :

1*l1m0Ttk35To6TsBzil1f6Q

์ธํ„ฐ๋„ท์— ๋Œ์•„๋‹ค๋‹ˆ๋Š” gif๋ฅผ ๊ธ์–ด๋‹ค๊ฐ€ ๊ฐ€์ ธ์™”๋Š”๋ฐ์š”.
๋ณด์‹œ๋‹ค์‹œํ”ผ 3D ์ปจ๋ณผ๋ฃจ์…˜์€ ๋‚ด๊ฐ€ ์ •์˜ํ•œ (gif์—์„œ๋Š” z์ถ•) ๋ฐฉํ–ฅ์œผ๋กœ ์ปค๋„์ด ์ž์œ ๋กญ๊ฒŒ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

Ghost๋ชจ๋“ˆ์„ ์ ์šฉํ•œ ์ œ์Šค์ณ ์ธ์‹์šฉ ๋ชจ๋ธ ์ฝ”๋“œ

import torch

from layers.ghost_layer3d import GhostLayer3D

class GhostNet3D(torch.nn.Module):
    def __init__(self, 
                 in_channels, 
                 class_num,
                 ):
        super(GhostNet3D, self).__init__()


        # ์‹œ๊ฐ„์ถ• frame 16์œผ๋กœ ์‹œ์ž‘
        # ๊ณต๊ฐ„ ํฌ๊ธฐ 128x64
        self.stem = torch.nn.Sequential(
            GhostLayer3D(in_channels=in_channels, out_channels=16)
        )

        # ์‹œ๊ฐ„์ถ• frame 8๋กœ ์••์ถ•
        # ๊ณต๊ฐ„ ํฌ๊ธฐ 64x32๋กœ ์••์ถ•
        self.layer1 = torch.nn.Sequential(
            GhostLayer3D(in_channels=16, out_channels=24, stride=2),
            GhostLayer3D(in_channels=24, out_channels=24)
        )


        # ์‹œ๊ฐ„์ถ• frame 8๋กœ ์œ ์ง€
        # ๊ณต๊ฐ„ ํฌ๊ธฐ 32x16
        self.layer2 = torch.nn.Sequential(
            GhostLayer3D(in_channels=24, out_channels=40, stride=(1,2,2)),
            GhostLayer3D(in_channels=40, out_channels=40),
        )


        # ์‹œ๊ฐ„์ถ• frame 8๋กœ ์œ ์ง€
        # ๊ณต๊ฐ„ ํฌ๊ธฐ 16x8
        self.layer3 = torch.nn.Sequential(
            GhostLayer3D(in_channels=40, out_channels=80, stride=(1,2,2)),
            GhostLayer3D(in_channels=80, out_channels=80),
            GhostLayer3D(in_channels=80, out_channels=80),
            GhostLayer3D(in_channels=80, out_channels=80),
        )

        # ์‹œ๊ฐ„์ถ• frame 8๋กœ ์œ ์ง€
        # ๊ณต๊ฐ„ ํฌ๊ธฐ 8x4
        self.layer4 = torch.nn.Sequential(
            GhostLayer3D(in_channels=80, out_channels=80, stride=(1,2,2)),
            GhostLayer3D(in_channels=80, out_channels=80),
            GhostLayer3D(in_channels=80, out_channels=80),
            GhostLayer3D(in_channels=80, out_channels=80),
        )

        self.gap = torch.nn.AdaptiveAvgPool3d((1,1,1))
        self.fc = torch.nn.Linear(80, class_num)
        

    def forward(self, x):

        ## ๋””๋ฒ„๊น…์šฉ ์‹œ๊ฐ„์ถ• 16์—์„œ ์‹œ์ž‘ ํ™•์ธ์šฉ
        B, C, T, H, W = x.shape

        x = self.stem(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)

        x = self.gap(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)

        return x
    

ํ•™์Šต ์ฝ”๋“œ ๋ฐ ๋ฐ์ดํ„ฐ์…‹ ๋งํฌ

๋ฐ์ดํ„ฐ์…‹ : 20bn-jester | Kaggle
ํ•™์Šต ์Šคํฌ๋ฆฝํŠธ : HGR/python/train.py at main ยท gellston/HGR ยท GitHub

Gesture ์—ฐ์†๋™์ž‘ ๋ฐ์ดํ„ฐ์…‹์ด์—ฌ์„œ ๊ทธ๋Ÿฐ์ง€ ์—„์ฒญ ํ•™์Šต์ด ๋А๋ฆฌ๊ตฐ์š”.. ๋‚ด์ผ ์•„์นจ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

2 Likes

์ปดํ“จํ„ฐ ๋’ค์ง€๋‹ค ๋ณด๋‹ˆ ์‚ฌ๋‚ด์—์„œ ๋งŒ๋“ค์—ˆ๋˜ ์ œ์Šค์ณ ์ธ์‹ ํ”„๋กœ๊ทธ๋žจ ์‹œ์—ฐ ๋™์˜์ƒ์ด ์žˆ๋„ค์š” ๊ฐ™์ด ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค.

4 Likes


ํ•™์Šต ์‹œํ‚ค๋‹ค๊ฐ€ ๊ณ ์–‘์ด๊ฐ€ ๊บผ๋ฒ„๋ ธ๊ตฐ์š” ใ… 
2 epoch์„ ๋ณด๋Š”๋ฐ 2์‹œ๊ฐ„์ด ๋„˜๊ฒŒ ๊ฑธ๋ฆฌ๋Š”๊ตฐ์š”โ€ฆ ๋‚ด์ผ ๋งˆ๋ฌด๋ฆฌ๊ฐ€ ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

3 Likes

์ด ์ •๋„๋ฉด ๊ทธ๋ƒฅ ์ทจ๋ฏธ๋กœ ๋งŒ์ง„ ์ˆ˜์ค€์ด ์•„๋‹ˆ๋ผ AI ๊ฐœ๋ฐœ์ž ํ•ด๋„ ๋˜๊ฒ ๋‹ค๋Š” ๋А๋‚Œ์ด์—์š” ์ด์ฐธ์— ์ „ํ–ฅ์„โ€ฆ ใ…‹ใ…‹

2 Likes

๊ทธ ๋ถ„๋“ค์€ ๋˜ ๊ทธ ๋ถ„๋“ค์˜ ์„ธ๊ณ„๊ฐ€ ์žˆ๋”๊ตฐ์˜ค.. ๋ง์”€๋งŒ์œผ๋กœ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

1 Like


ํ•™์Šต์„ ํ•ด๋ณด๋‹ˆ. ํ•™์Šต ์ •ํ™•๋„๋Š” ์˜ฌ๋ผ๊ฐ€์ง€๋งŒ ๊ฒ€์ฆ ์ •ํ™•๋„๊ฐ€ ์ ์  ๋–จ์–ด์ง€๋Š” ๊ฒƒ์„ ๋ณด๋‹ˆ ์˜ค๋ฒ„ํ”ผํŒ…์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋ชจ๋ธ์€ ๋งŒ๋“ค์—ˆ์ง€๋งŒ ๊ฐ€๋งŒ๋ณด๋‹ˆ.. ์˜ค๋ฒ„ํ”ผํŒ…์— ๋Œ€์‘ํ•˜๋Š” ๊ธฐ๋ฒ•์€ ๋„ฃ์ง€ ์•Š์•˜๊ตฐ์š”.
๋ณดํ†ต ํšŒ์‚ฌ์—์„œ ๊ฒ€์‚ฌ์šฉ์œผ๋กœ ๊ฐœ๋ฐœํ•˜๋Š” ๋ชจ๋ธ๋“ค์€ ํฌ๊ธฐ๊ฐ€ ์ž‘๊ณ  ๋‹จ์ˆœํ•ด์„œ ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๋˜๊ฒƒ ๊ฐ™์€๋ฐ
๋Œ€ํ˜• ๋ฐ์ดํ„ฐ์…‹์„ ์œ„ํ•œ ๋น„๊ต์  ํฐ ๋ชจ๋ธ์„ ๋งŒ๋“ค์–ด์„œ ํ•™์Šตํ•˜๋‹ˆ ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํ›„โ€ฆ ๋‹ค์‹œ ํ•™์Šต์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•ด์•ผ๊ฒ ๊ตฐ์š”. ์ƒ๊ฐ์ข€ ํ•ด๋ด์•ผ๊ฒ ์Šต๋‹ˆ๋‹ค.

6 Likes


ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜์ •ํ•˜๊ณ  4๋ฒˆ์งธ ํ•™์Šต์ธ๋ฐ validation ์ •ํ™•๋„๊ณ  90์„ ๋„˜์–ด์„ฐ๊ตฐ์š”.. ์˜ค๋Š˜ ํ•˜๋ฃจ๋ฐค ๋” ์ง€์ผœ๋ณด๊ณ  ์ •์ฒด๋˜๋Š”๊ฒƒ ๊ฐ™์ด ๋ณด์ด๋ฉด ๋ฉˆ์ถ”๊ณ  ๋žฉํ•‘์„ ์ง„ํ–‰ํ•ด์•ผ ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

5 Likes

๊ธธ๊ณ  ๊ธด ๊ณ ํ†ต์˜ ํ•™์Šต ์‹œ๊ฐ„์„ ๊ฑฐ์ณ์„œโ€ฆ

python์œผ๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑํ•ด์„œ ๋Œ๋ ค๋ดค๋Š”๋ฐ ๋Œ€์ถฉ ๋Œ์•„๊ฐ€๋Š”๊ตฐ์š”..
์„ฑ๋Šฅ์ด ์•„์‰ฝ์ง€๋งŒ.. ๋„ˆ๋ฌด ํž˜๋“ค๊ตฐ์š” ๋…ธํŠธ๋ถ์œผ๋กœ (๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค ใ… )

โ€ป ํ™•๋ฅ ์ด ์ŠคํŒŒ์ดํฌ์ฒ˜๋Ÿผ ํŠ€๋Š” ๊ตฌ๊ฐ„์ด ๋งŽ์•„์„œ EMA (Exponential Moving Average) ๋กœ ๋‘”๊ฐํ•˜๊ฒŒ ๋ญ‰๊ฐœ๋ฒ„๋ ธ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” ์ƒˆ๋ฒฝ์— ๋„ˆ๋ฌด ๊ท€์ฐฎ์•„์„œ chatGPTํ˜•์˜ ๋„์›€์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. (1ํŒจ)

ํ…Œ์ŠคํŠธ ๋™์˜์ƒ

์ฝ”๋“œ

import torch
import os
import cv2
import numpy as np
from collections import deque

from model.ghostnet3d import GhostNet3D
from model.softmax_model import SoftmaxModel

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"ํ˜„์žฌ ์‚ฌ์šฉ ์ค‘์ธ ๋””๋ฐ”์ด์Šค: {device}")

image_width = 128
image_height = 64
image_channel = 3
class_num = 27
frames = 16

weight_path = "C://github//HGR//python//results//weights.pth"

model = GhostNet3D(in_channels=image_channel, class_num=class_num).to(device)
if os.path.exists(weight_path):
    state_dict = torch.load(weight_path, map_location=device)
    model.load_state_dict(state_dict)

net = SoftmaxModel(backbone=model).to(device)
net.eval()

# ===== ์„ค์ • =====
ACCUM_FRAMES = 25       # 30fps ํ™˜๊ฒฝ์—์„œ TARGET_FPS=17, frames=16์ด๋ฉด 32 ์ด์ƒ ๊ถŒ์žฅ
TARGET_FPS = 17
STRIDE = 1              # ๋ช‡ ํ”„๋ ˆ์ž„๋งˆ๋‹ค ์ถ”๋ก ํ• ์ง€
EMA_ALPHA = 0.7        # 0.7~0.95 (ํด์ˆ˜๋ก ๋” ์•ˆ์ •์ , ๋ฐ˜์‘์€ ๋А๋ ค์ง)

GESTURES = [
    "Doing other things","No gesture","Drumming Fingers","Pulling Hand In","Pulling Two Fingers In",
    "Pushing Hand Away","Pushing Two Fingers Away","Rolling Hand Backward","Rolling Hand Forward",
    "Shaking Hand","Sliding Two Fingers Down","Sliding Two Fingers Left","Sliding Two Fingers Right",
    "Sliding Two Fingers Up","Stop Sign","Swiping Down","Swiping Left","Swiping Right","Swiping Up",
    "Thumb Down","Thumb Up","Turning Hand Clockwise","Turning Hand Counterclockwise",
    "Zooming In With Full Hand","Zooming In With Two Fingers","Zooming Out With Full Hand",
    "Zooming Out With Two Fingers",
]

def preprocess(frame_bgr):
    x = cv2.resize(frame_bgr, (image_width, image_height))
    x = cv2.cvtColor(x, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0
    return x  # (H,W,C)

def sample_by_target_fps(buf_frames_rgb, cam_fps, target_fps, out_len):
    L = len(buf_frames_rgb)
    if L < out_len:
        return None

    if cam_fps is None or cam_fps <= 1:
        idx = np.linspace(0, L - 1, out_len).round().astype(int)
        return [buf_frames_rgb[i] for i in idx]

    step = max(1, int(round(cam_fps / target_fps)))
    need = 1 + (out_len - 1) * step
    if L < need:
        return None

    start = L - need
    idx = start + np.arange(out_len) * step
    return [buf_frames_rgb[i] for i in idx]

@torch.no_grad()
def infer_probs(net, sampled_frames_rgb):
    clip = np.stack(sampled_frames_rgb, axis=0)        # (T,H,W,C)
    clip = np.transpose(clip, (3, 0, 1, 2))            # (C,T,H,W)
    x = torch.from_numpy(clip).unsqueeze(0).to(device) # (1,C,T,H,W)

    probs = net(x)
    probs = probs[0] if isinstance(probs, (list, tuple)) else probs
    return probs.squeeze(0)  # (C,)

# ===== ์‹คํ–‰๋ถ€ =====
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
if not cap.isOpened():
    raise RuntimeError("์นด๋ฉ”๋ผ๋ฅผ ์—ด ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. cam_index(0/1/2...)๋ฅผ ๋ฐ”๊ฟ”๋ณด์„ธ์š”.")

cam_fps = cap.get(cv2.CAP_PROP_FPS)
print(f"Camera FPS: {cam_fps if cam_fps else 'Unknown'}")

buf = deque(maxlen=ACCUM_FRAMES)  # โœ… ํ•œ ์นธ์”ฉ ๋ฐ€๋ฆฌ๋Š” ์Šฌ๋ผ์ด๋”ฉ ๋ฒ„ํผ
ema = None                        # โœ… EMA ์ƒํƒœ(ํ™•๋ฅ  ๋ฒกํ„ฐ)
frame_count = 0

print("์›น์บ  ์ œ์Šค์ฒ˜ ํ…Œ์ŠคํŠธ ์‹œ์ž‘ (q ์ข…๋ฃŒ)")

while True:
    ok, frame = cap.read()
    if not ok:
        print("ํ”„๋ ˆ์ž„์„ ์ฝ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.")
        break

    cv2.imshow("Webcam", frame)
    buf.append(preprocess(frame))
    frame_count += 1

    if len(buf) < ACCUM_FRAMES:
        if (cv2.waitKey(1) & 0xFF) == ord('q'):
            break
        continue

    if frame_count % STRIDE == 0:
        sampled = sample_by_target_fps(list(buf), cam_fps, TARGET_FPS, frames)
        if sampled is not None:
            probs = infer_probs(net, sampled)  # (C,)

            # ===== EMA ์ ์šฉ =====
            if ema is None:
                ema = probs.detach().clone()
            else:
                ema = EMA_ALPHA * ema + (1.0 - EMA_ALPHA) * probs

            pred = int(torch.argmax(ema).item())
            conf = float(torch.max(ema).item())
            name = GESTURES[pred] if pred < len(GESTURES) else str(pred)
            print(f"{name}  conf(EMA)={conf:.3f}")

    if (cv2.waitKey(1) & 0xFF) == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
2 Likes

์•„.. ํ•™์Šตํ•œ ๋ชจ๋ธ์€ git์— ์˜ฌ๋ ค๋’€์Šต๋‹ˆ๋‹ค.

2 Likes

README ์—…๋ฐ์ดํŠธ


.NET ๋ˆ„๊ฒŸ์€ ๊ณง ์—…๋ฐ์ดํŠธ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

C++ Nuget ํ…Œ์ŠคํŠธ

#include <iostream>
#include <opencv2/opencv.hpp>


#include <hgr/hgr.h>
#include <hgr/clipSampler.h>

int main()
{

    try {

        auto memoryPool = hgrapi::v1::memoryPool::create();

        auto hgr = hgrapi::v1::hgr::create();
        hgr->setup("C://github//HGR//python//results//model.onnx", hgrapi::v1::device::cuda);
        hgr->setEmaAlpha(0.2f);

        auto sampler = hgrapi::v1::clipSampler::create();
        sampler->setMaxFrames(40);
        sampler->setSampleFrames(16);

        cv::VideoCapture cap;
        cap.open(0);

        if (!cap.isOpened()) {
            std::cerr << "Failed to open VideoCapture.\n";
            return 1;
        }

        cv::Mat frame;

        while (true) {

            if (!cap.read(frame) || frame.empty()) {
                std::cerr << "End of stream or failed to read frame.\n";
                break;
            }

            auto dlImage = hgrapi::v1::image::create(frame.cols, frame.rows, 3, memoryPool);
            std::memcpy(dlImage->data(), frame.data, dlImage->size());
            auto resizeImage = hgrapi::v1::image::resize(dlImage, 128, 64);
            sampler->append(resizeImage);


            auto samples = sampler->requestSampling();
            auto result = hgr->predict(samples);


            std::cout << "name : " << result.name << " prob : " << result.prob << std::endl;

            cv::imshow("capture", frame);
            cv::waitKey(1);
        }

    }
    catch (std::exception ex) {
        std::cout << ex.what() << std::endl;
    }

    return 0;

}

ํ…Œ์ŠคํŠธ ๋™์˜์ƒ

ํŒŒ์ด์ฌ๋ณด๋‹ค ์™œ ๋น ๋ฅธ๊ฐ€

์–ธ์–ด ์ฐจ์ด๋„ ์žˆ๊ฒ ์ง€๋งŒ.. ํฐ ๋ณ€์ˆ˜๋Š” ์•„๋‹Œ ๊ฒƒ ๊ฐ™๊ณ .. python์—์„œ๋Š” pytorch๋กœ ํ…Œ์ŠคํŠธํ–ˆ๋Š”๋ฐ์š”..
C++์€ ONNX๋ชจ๋ธ๋กœ ๋ณ€ํ™˜๋˜๋ฉด์„œ node fusion์œผ๋กœ ์ธํ•ด์„œ ์„ ํ˜• ์—ฐ์‚ฐ ๊ตฌ๊ฐ„์ด ์••์ถ•๋˜์–ด์„œ ๊ทธ๋Ÿฐ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. (์ƒ๋žต์ด ๋งž๋Š” ํ‘œํ˜„ ๊ฐ™๊ตฐ์š”)

1 Like

๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐโ€ฆ

์ €์กฐ๋„ ๊ฐœ์„  Nuget ์ž‘์—…๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ .NET ๋ˆ„๊ฒŸ์„ ๋งŒ๋“ค์–ด์„œ ์˜ฌ๋ ธ์Šต๋‹ˆ๋‹ค.
๋ฐ๋ชจ์•ฑ์€ Release์—์„œ ๋ฐ›์œผ์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์†Œ๊ฐ

Nuget์€ ์ •๋ง ์–ด๋ ต๊ตฐ์š”.
ํŠนํžˆ๋‚˜ C++๊ณผ C# dll์ด ์„ž์—ฌ ์žˆ๋Š” ๋ˆ„๊ฒŸ์€ ์ •๋ง ๋งŒ๋“ค๊ธฐ ๊นŒ๋‹ค๋กœ์šด ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์„ ํ•˜๋ฉด์„œ ์ง€์ธ ๋ถ„๋“ค ๋ณด๋ฉด ๋‹ค๋“ค LLM์œผ๋กœ ๋ญ”๊ฐ€ ๋š๋”ฑ ๋งŒ๋“œ์‹œ๋Š”๋ฐ
ํ˜„ํƒ€๊ฐ€ ์˜ค๋Š”๊ตฐ์š”โ€ฆ ์ด๋Ÿฐ ์ž‘์—…์ด ์˜๋ฏธ๊ฐ€ ์žˆ๋‚˜ ์‹ถ๊ธฐ๋„ ํ•˜๊ณ  ํ›„!
LLM์„ ์ •๋ง ๊ณต๋ถ€ํ•ด์•ผ ๋  ๊ฒƒ ๊ฐ™๊ตฐ์š”.. Agent๋ž‘..

7 Likes