์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿค– ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ์™€ NLTKยทspaCy๋ฅผ ํ™œ์šฉํ•œ ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ์™„์ „์ •๋ณต

๐Ÿค– ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ์™€ NLTKยทspaCy๋ฅผ ํ™œ์šฉํ•œ ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ์™„์ „์ •๋ณต

ํŒŒ์ด์ฌ์œผ๋กœ ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ ๋ถ„์„ํ•˜๋Š” ๋ฒ•, ์ง„์งœ ์‹ค์ „ ๋…ธํ•˜์šฐ๊นŒ์ง€ ๋‹ค ์•Œ๋ ค๋“œ๋ฆผ ใ…Žใ…Ž

๐Ÿ“š ํ…์ŠคํŠธ ๋งˆ์ด๋‹์ด ๋ญ”๋ฐ? ์™œ ์ด๋ ‡๊ฒŒ ํ•ซํ•œ๊ฑฐ์•ผ?

์š”์ฆ˜ ๋ฐ์ดํ„ฐ ๋ถ„์„ ์ชฝ์—์„œ ์ผํ•˜๊ฑฐ๋‚˜ ๊ด€์‹ฌ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์ด๋ผ๋ฉด 'ํ…์ŠคํŠธ ๋งˆ์ด๋‹'์ด๋ผ๋Š” ๋‹จ์–ด ํ•œ ๋ฒˆ์ฏค์€ ๋“ค์–ด๋ดค์„ ๊ฑฐ์ž„ ใ…‹ใ…‹
๊ทผ๋ฐ ๋ง‰์ƒ ๋ญ”์ง€ ๋ฌผ์–ด๋ณด๋ฉด "์Œ... ํ…์ŠคํŠธ ๋ถ„์„ํ•˜๋Š” ๊ฑฐ?" ์ด ์ •๋„๋กœ๋งŒ ์•Œ๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋”๋ผ๊ณ .

ํ…์ŠคํŠธ ๋งˆ์ด๋‹(Text Mining)์€ ๋น„์ •ํ˜• ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์—์„œ ์˜๋ฏธ ์žˆ๋Š” ์ •๋ณด์™€ ํŒจํ„ด์„ ์ถ”์ถœํ•˜๋Š” ๊ธฐ์ˆ ์ด์•ผ.
์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด ์—„์ฒญ๋‚œ ์–‘์˜ ๋ฌธ์„œ, ๋ฆฌ๋ทฐ, SNS ๊ธ€, ๋‰ด์Šค ๊ธฐ์‚ฌ ๊ฐ™์€ ํ…์ŠคํŠธ ๋”๋ฏธ์—์„œ ์ธ์‚ฌ์ดํŠธ๋ฅผ ๋ฝ‘์•„๋‚ด๋Š” ๊ฑฐ์ง€ ๐Ÿ’ก

์˜ˆ๋ฅผ ๋“ค์–ด๋ณผ๊ฒŒ:
โ€ข ์‡ผํ•‘๋ชฐ ๋ฆฌ๋ทฐ 10๋งŒ ๊ฐœ๋ฅผ ๋ถ„์„ํ•ด์„œ ๊ณ ๊ฐ๋“ค์ด ๊ฐ€์žฅ ๋ถˆ๋งŒ์กฑํ•˜๋Š” ํฌ์ธํŠธ ์ฐพ๊ธฐ
โ€ข ํŠธ์œ„ํ„ฐ ๋ฐ์ดํ„ฐ๋กœ ํŠน์ • ๋ธŒ๋žœ๋“œ์— ๋Œ€ํ•œ ๊ฐ์„ฑ ๋ถ„์„ํ•˜๊ธฐ
โ€ข ๋‰ด์Šค ๊ธฐ์‚ฌ์—์„œ ์ฃผ์š” ํ‚ค์›Œ๋“œ์™€ ํ† ํ”ฝ ์ž๋™ ์ถ”์ถœํ•˜๊ธฐ
โ€ข ๊ณ ๊ฐ ๋ฌธ์˜ ๋‚ด์šฉ์„ ์ž๋™ ๋ถ„๋ฅ˜ํ•ด์„œ ๋‹ด๋‹น ๋ถ€์„œ๋กœ ๋ผ์šฐํŒ…ํ•˜๊ธฐ

์ด๋Ÿฐ ๊ฒƒ๋“ค์ด ๋‹ค ํ…์ŠคํŠธ ๋งˆ์ด๋‹์˜ ์˜์—ญ์ด์•ผ. ์ง„์งœ ์‹ค๋ฌด์—์„œ ๊ฐœ์ฉŒ๋Š” ํ™œ์šฉ๋„๋ฅผ ์ž๋ž‘ํ•˜๋Š” ๊ธฐ์ˆ ์ด๋ผ๊ณ  ใ…‡ใ…‡

๐ŸŽฏ ์™œ ์ง€๊ธˆ ํ…์ŠคํŠธ ๋งˆ์ด๋‹์ด ์ค‘์š”ํ•œ๊ฐ€? 1. ๋ฐ์ดํ„ฐ์˜ 80%๊ฐ€ ๋น„์ •ํ˜• ๋ฐ์ดํ„ฐ: ์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฃจ๋Š” ๋ฐ์ดํ„ฐ ์ค‘ ๋Œ€๋ถ€๋ถ„์ด ํ…์ŠคํŠธ, ์ด๋ฏธ์ง€, ์˜์ƒ ๊ฐ™์€ ๋น„์ •ํ˜• ๋ฐ์ดํ„ฐ์ž„. ํŠนํžˆ ํ…์ŠคํŠธ๋Š” ๊ทธ ์ค‘์—์„œ๋„ ์••๋„์ ์ธ ๋น„์ค‘์„ ์ฐจ์ง€ํ•จ
2. SNSยท๋ฆฌ๋ทฐ ๋ฌธํ™”์˜ ํญ๋ฐœ์  ์„ฑ์žฅ: ์‚ฌ๋žŒ๋“ค์ด ์˜จ๋ผ์ธ์—์„œ ์˜๊ฒฌ์„ ํ‘œํ˜„ํ•˜๋Š” ๊ฒŒ ์ผ์ƒํ™”๋˜๋ฉด์„œ ๋ถ„์„ํ•  ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ์ฆ๊ฐ€
3. AI ๊ธฐ์ˆ ์˜ ๋ฐœ์ „: ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ(NLP) ๊ธฐ์ˆ ์ด ๋ฐœ์ „ํ•˜๋ฉด์„œ ์˜ˆ์ „์—” ๋ถˆ๊ฐ€๋Šฅํ–ˆ๋˜ ์ˆ˜์ค€์˜ ํ…์ŠคํŠธ ์ดํ•ด๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง
4. ๋น„์ฆˆ๋‹ˆ์Šค ์˜์‚ฌ๊ฒฐ์ •์˜ ํ•ต์‹ฌ: ๊ณ ๊ฐ์˜ ๋ชฉ์†Œ๋ฆฌ(VOC)๋ฅผ ์ •๋Ÿ‰์ ์œผ๋กœ ๋ถ„์„ํ•ด์„œ ์ „๋žต ์ˆ˜๋ฆฝ์— ํ™œ์šฉํ•˜๋Š” ๊ฒŒ ํ•„์ˆ˜๊ฐ€ ๋จ
ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ํ”„๋กœ์„ธ์Šค ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ์ „์ฒ˜๋ฆฌ ์ •์ œ ๋ถ„์„ ๋ชจ๋ธ๋ง ์‹œ๊ฐํ™” ์ธ์‚ฌ์ดํŠธ ํ™œ์šฉ ์˜์‚ฌ๊ฒฐ์ • ํ•ต์‹ฌ ๋„๊ตฌ NLTK spaCy scikit-learn Gensim ๊ธฐ๋ณธ NLP ๊ณ ๊ธ‰ ์ฒ˜๋ฆฌ ๋จธ์‹ ๋Ÿฌ๋‹ ํ† ํ”ฝ๋ชจ๋ธ๋ง

๐Ÿ ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ(NLP)์˜ ๊ธฐ์ดˆ ๊ฐœ๋…๋ถ€ํ„ฐ ์ฐจ๊ทผ์ฐจ๊ทผ

ํ…์ŠคํŠธ ๋งˆ์ด๋‹์„ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๋ ค๋ฉด ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ(Natural Language Processing, NLP)์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ๊ฐœ๋…์ด ํ•„์š”ํ•ด.
์ž์—ฐ์–ด ์ฒ˜๋ฆฌ๋Š” ์ปดํ“จํ„ฐ๊ฐ€ ์ธ๊ฐ„์˜ ์–ธ์–ด๋ฅผ ์ดํ•ดํ•˜๊ณ  ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ธ๊ณต์ง€๋Šฅ์˜ ํ•œ ๋ถ„์•ผ์•ผ ๐Ÿค–

๊ทผ๋ฐ ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๊ฐ€ ๋ญ๋ƒ๋ฉด, ์ปดํ“จํ„ฐ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ˆซ์ž๋งŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑฐ์ž„ ใ…‹ใ…‹ใ…‹
์šฐ๋ฆฌ๊ฐ€ ์“ฐ๋Š” ํ•œ๊ธ€, ์˜์–ด ๊ฐ™์€ ์ž์—ฐ์–ด๋Š” ์ปดํ“จํ„ฐ ์ž…์žฅ์—์„œ๋Š” ๊ทธ๋ƒฅ ์˜๋ฏธ ์—†๋Š” ๋ฌธ์ž์—ด์ผ ๋ฟ์ด์ง€.

๊ทธ๋ž˜์„œ NLP์˜ ํ•ต์‹ฌ ๊ณผ์ œ๋Š”:
1. ํ…์ŠคํŠธ๋ฅผ ์ปดํ“จํ„ฐ๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ
2. ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๋กœ ์˜๋ฏธ ์žˆ๋Š” ๋ถ„์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ
3. ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ์‚ฌ๋žŒ์ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ํ‘œํ˜„ํ•˜๊ธฐ

์ด ์„ธ ๊ฐ€์ง€๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒŒ ๋ฐ”๋กœ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฐ์šธ NLTK์™€ spaCy ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์—ญํ• ์ด์•ผ ๐Ÿ’ช

๐Ÿ“Œ NLP์˜ ์ฃผ์š” ์ฒ˜๋ฆฌ ๋‹จ๊ณ„
๋‹จ๊ณ„ ์„ค๋ช… ์˜ˆ์‹œ
ํ† ํฐํ™”
(Tokenization)
ํ…์ŠคํŠธ๋ฅผ ์˜๋ฏธ ์žˆ๋Š” ๋‹จ์œ„๋กœ ์ชผ๊ฐœ๋Š” ์ž‘์—… "์•ˆ๋…•ํ•˜์„ธ์š”" โ†’ ["์•ˆ๋…•", "ํ•˜", "์„ธ์š”"]
์ •๊ทœํ™”
(Normalization)
ํ…์ŠคํŠธ๋ฅผ ์ผ๊ด€๋œ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ "iPhone" โ†’ "iphone"
๋ถˆ์šฉ์–ด ์ œ๊ฑฐ
(Stopword Removal)
๋ถ„์„์— ๋ถˆํ•„์š”ํ•œ ๋‹จ์–ด ์ œ๊ฑฐ "the", "a", "์€", "๋Š”" ๋“ฑ ์ œ๊ฑฐ
์–ด๊ฐ„ ์ถ”์ถœ
(Stemming)
๋‹จ์–ด๋ฅผ ๊ธฐ๋ณธ ํ˜•ํƒœ๋กœ ์ถ•์•ฝ "running" โ†’ "run"
ํ‘œ์ œ์–ด ์ถ”์ถœ
(Lemmatization)
๋‹จ์–ด๋ฅผ ์‚ฌ์ „์  ๊ธฐ๋ณธํ˜•์œผ๋กœ ๋ณ€ํ™˜ "better" โ†’ "good"
ํ’ˆ์‚ฌ ํƒœ๊น…
(POS Tagging)
๊ฐ ๋‹จ์–ด์˜ ํ’ˆ์‚ฌ ์ •๋ณด ๋ถ€์—ฌ "์‚ฌ๊ณผ" โ†’ ๋ช…์‚ฌ or ๋™์‚ฌ
๊ฐœ์ฒด๋ช… ์ธ์‹
(NER)
๊ณ ์œ ๋ช…์‚ฌ, ๋‚ ์งœ, ์žฅ์†Œ ๋“ฑ ์ธ์‹ "์„œ์šธ" โ†’ ์ง€๋ช…
๐Ÿ’ก ์ดˆ๋ณด์ž ํŒ ์ฒ˜์Œ์—” ์ด ๋ชจ๋“  ๋‹จ๊ณ„๊ฐ€ ๋ณต์žกํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์‹ค์ œ๋กœ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋Œ€๋ถ€๋ถ„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์คŒ ใ…Žใ…Ž
์šฐ๋ฆฌ๋Š” ๊ฐ ๋‹จ๊ณ„๊ฐ€ ์™œ ํ•„์š”ํ•œ์ง€๋งŒ ์ดํ•ดํ•˜๊ณ , ํ•„์š”ํ•  ๋•Œ ์ ์ ˆํžˆ ํ™œ์šฉํ•˜๋ฉด ๋ผ!

ํŠนํžˆ ํ•œ๊ตญ์–ด ์ฒ˜๋ฆฌ๋Š” ์˜์–ด๋ณด๋‹ค ํ›จ์”ฌ ๊นŒ๋‹ค๋กœ์šด๋ฐ, ๊ทธ ์ด์œ ๋Š”:

1. ๊ต์ฐฉ์–ด ํŠน์„ฑ: "๋จน์—ˆ์Šต๋‹ˆ๋‹ค"์ฒ˜๋Ÿผ ์–ด๊ฐ„์— ์—ฌ๋Ÿฌ ์–ด๋ฏธ๊ฐ€ ๋ถ™์–ด์„œ ์˜๋ฏธ๊ฐ€ ๋ณ€ํ•จ
2. ๋„์–ด์“ฐ๊ธฐ ๋ชจํ˜ธ์„ฑ: "์•„๋ฒ„์ง€๊ฐ€๋ฐฉ์—๋“ค์–ด๊ฐ€์‹ ๋‹ค" ๊ฐ™์€ ๊ฒฝ์šฐ ๋„์–ด์“ฐ๊ธฐ์— ๋”ฐ๋ผ ์˜๋ฏธ๊ฐ€ ์™„์ „ํžˆ ๋‹ฌ๋ผ์ง
3. ๋™์Œ์ด์˜์–ด: "๋ฐฐ"๊ฐ€ ๊ณผ์ผ์ธ์ง€, ํƒˆ๊ฒƒ์ธ์ง€, ์‹ ์ฒด๋ถ€์œ„์ธ์ง€ ๋ฌธ๋งฅ์œผ๋กœ ํŒ๋‹จํ•ด์•ผ ํ•จ

๊ทธ๋ž˜์„œ ํ•œ๊ตญ์–ด NLP์—๋Š” KoNLPy, Mecab ๊ฐ™์€ ์ „์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ๋งŽ์ด ์“ฐ์ด๋Š”๋ฐ, ์ด๊ฑด ๋‚˜์ค‘์— ๋” ์ž์„ธํžˆ ๋‹ค๋ค„๋ณผ๊ฒŒ ๐Ÿ˜Š

๐Ÿ”ง NLTK: ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ์˜ ์Šค์œ„์Šค ์•„๋ฏธ ๋‚˜์ดํ”„

NLTK(Natural Language Toolkit)๋Š” ํŒŒ์ด์ฌ์—์„œ ๊ฐ€์žฅ ์œ ๋ช…ํ•œ NLP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜์•ผ.
2001๋…„์— ์ฒ˜์Œ ๋‚˜์™”์œผ๋‹ˆ๊นŒ ๋ฒŒ์จ 20๋…„์ด ๋„˜์€ ๋ฒ ํ…Œ๋ž‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ง€ ใ…‹ใ…‹ใ…‹

NLTK์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์€ ๊ต์œก์šฉ์œผ๋กœ ์„ค๊ณ„๋˜์–ด์„œ ๋ฐฐ์šฐ๊ธฐ ์‰ฝ๋‹ค๋Š” ๊ฑฐ์•ผ.
NLP์˜ ๊ฑฐ์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉด์„œ๋„, ๊ฐ ๊ธฐ๋Šฅ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์–ด.

์‹ค๋ฌด์—์„œ๋Š” ์†๋„ ๋•Œ๋ฌธ์— spaCy๋ฅผ ๋” ๋งŽ์ด ์“ฐ๊ธด ํ•˜์ง€๋งŒ, NLTK๋Š” ์—ฌ์ „ํžˆ:
โ€ข NLP ํ•™์Šต์šฉ์œผ๋กœ ์ตœ๊ณ 
โ€ข ํ”„๋กœํ† ํƒ€์ดํ•‘ํ•  ๋•Œ ๋น ๋ฅด๊ฒŒ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์ข‹์Œ
โ€ข ํŠน์ • ์–ธ์–ดํ•™์  ๋ถ„์„์ด ํ•„์š”ํ•  ๋•Œ ์œ ์šฉํ•จ

์ด๋Ÿฐ ์ด์œ ๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์–ด ๐Ÿ‘

๐Ÿ“ฆ NLTK ์„ค์น˜ ๋ฐ ๊ธฐ๋ณธ ์„ค์ •

NLTK ์„ค์น˜๋Š” ์ง„์งœ ๊ฐ„๋‹จํ•จ. pip๋กœ ํ•œ ๋ฐฉ์ด์•ผ:

pip install nltk

์„ค์น˜ ํ›„์—๋Š” ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด๊ฒƒ๋„ ์ฝ”๋“œ ๋ช‡ ์ค„์ด๋ฉด ๋:

import nltk

# ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ๋‹ค์šด๋กœ๋“œ
nltk.download('punkt')  # ํ† ํฐํ™” ๋„๊ตฌ
nltk.download('stopwords')  # ๋ถˆ์šฉ์–ด ์‚ฌ์ „
nltk.download('averaged_perceptron_tagger')  # ํ’ˆ์‚ฌ ํƒœ๊ฑฐ
nltk.download('wordnet')  # WordNet ์‚ฌ์ „
nltk.download('omw-1.4')  # ๋‹ค๊ตญ์–ด WordNet

# ๋˜๋Š” ์ „์ฒด ๋‹ค์šด๋กœ๋“œ (์šฉ๋Ÿ‰ ํผ, ์‹œ๊ฐ„ ๊ฑธ๋ฆผ)
# nltk.download('all')
โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ nltk.download('all')์€ ์•ฝ 3.5GB ์ •๋„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•จ.
์ฒ˜์Œ์—” ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ๊ฐœ๋ณ„์ ์œผ๋กœ ๋‹ค์šด๋กœ๋“œํ•˜๋Š” ๊ฒŒ ์ข‹์•„. ๋‚˜์ค‘์— ์—๋Ÿฌ ๋‚˜๋ฉด ๊ทธ๋•Œ๊ทธ๋•Œ ์ถ”๊ฐ€๋กœ ๋ฐ›์œผ๋ฉด ๋จ ใ…‡ใ…‡
๐Ÿ”จ NLTK ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์‹ค์ „ ํ™œ์šฉ

์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ NLTK๋กœ ๋ญ˜ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์•Œ์•„๋ณด์ž!

1๏ธโƒฃ ํ† ํฐํ™”(Tokenization)

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

from nltk.tokenize import word_tokenize, sent_tokenize, TreebankWordTokenizer

text = "์•ˆ๋…•ํ•˜์„ธ์š”! NLTK๋ฅผ ๋ฐฐ์šฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ •๋ง ์žฌ๋ฏธ์žˆ๋„ค์š” ใ…Žใ…Ž"

# ๋ฌธ์žฅ ํ† ํฐํ™”
sentences = sent_tokenize(text)
print("๋ฌธ์žฅ ํ† ํฐํ™”:", sentences)
# ์ถœ๋ ฅ: ['์•ˆ๋…•ํ•˜์„ธ์š”!', 'NLTK๋ฅผ ๋ฐฐ์šฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.', '์ •๋ง ์žฌ๋ฏธ์žˆ๋„ค์š” ใ…Žใ…Ž']

# ๋‹จ์–ด ํ† ํฐํ™”
words = word_tokenize(text)
print("๋‹จ์–ด ํ† ํฐํ™”:", words)
# ์ถœ๋ ฅ: ['์•ˆ๋…•ํ•˜์„ธ์š”', '!', 'NLTK๋ฅผ', '๋ฐฐ์šฐ๊ณ ', '์žˆ์Šต๋‹ˆ๋‹ค', '.', '์ •๋ง', '์žฌ๋ฏธ์žˆ๋„ค์š”', 'ใ…Žใ…Ž']

# ์˜์–ด ํ…์ŠคํŠธ ์˜ˆ์‹œ
eng_text = "I can't believe it's already 2024! Time flies."
eng_words = word_tokenize(eng_text)
print("์˜์–ด ํ† ํฐํ™”:", eng_words)
# ์ถœ๋ ฅ: ['I', 'ca', "n't", 'believe', 'it', "'s", 'already', '2024', '!', 'Time', 'flies', '.']

๋ณด๋ฉด ์•Œ๊ฒ ์ง€๋งŒ NLTK์˜ ๊ธฐ๋ณธ ํ† ํฌ๋‚˜์ด์ €๋Š” ์˜์–ด์— ์ตœ์ ํ™”๋˜์–ด ์žˆ์–ด.
ํ•œ๊ตญ์–ด๋Š” ์ข€ ์–ด์ƒ‰ํ•˜๊ฒŒ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๊ฑด ๋‚˜์ค‘์— KoNLPy ๊ฐ™์€ ํ•œ๊ตญ์–ด ์ „์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ณด์™„ํ•  ์ˆ˜ ์žˆ์Œ ๐Ÿ‘Œ

2๏ธโƒฃ ๋ถˆ์šฉ์–ด(Stopwords) ์ œ๊ฑฐ

๋ถˆ์šฉ์–ด๋Š” "the", "a", "is" ๊ฐ™์ด ์ž์ฃผ ๋‚˜์˜ค์ง€๋งŒ ๋ถ„์„์—๋Š” ํฐ ์˜๋ฏธ๊ฐ€ ์—†๋Š” ๋‹จ์–ด๋“ค์ด์•ผ.
์ด๋Ÿฐ ๊ฑธ ์ œ๊ฑฐํ•˜๋ฉด ๋ถ„์„ ์ •ํ™•๋„๊ฐ€ ์˜ฌ๋ผ๊ฐ€๊ณ  ์ฒ˜๋ฆฌ ์†๋„๋„ ๋นจ๋ผ์ง:

from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

# ์˜์–ด ๋ถˆ์šฉ์–ด ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ
stop_words = set(stopwords.words('english'))
print(f"์˜์–ด ๋ถˆ์šฉ์–ด ๊ฐœ์ˆ˜: {len(stop_words)}๊ฐœ")
print("๋ถˆ์šฉ์–ด ์˜ˆ์‹œ:", list(stop_words)[:10])

# ๋ถˆ์šฉ์–ด ์ œ๊ฑฐ ์‹ค์Šต
text = "This is a sample sentence demonstrating the removal of stop words."
words = word_tokenize(text.lower())

filtered_words = [word for word in words if word not in stop_words and word.isalpha()]
print("์›๋ณธ:", words)
print("๋ถˆ์šฉ์–ด ์ œ๊ฑฐ ํ›„:", filtered_words)
# ์ถœ๋ ฅ: ['sample', 'sentence', 'demonstrating', 'removal', 'stop', 'words']
๐Ÿ’ก ์‹ค๋ฌด ํŒ ๋ถˆ์šฉ์–ด ๋ชฉ๋ก์€ ๋„๋ฉ”์ธ์— ๋”ฐ๋ผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•˜๋Š” ๊ฒŒ ์ข‹์•„.
์˜ˆ๋ฅผ ๋“ค์–ด ์˜ํ™” ๋ฆฌ๋ทฐ ๋ถ„์„์ด๋ผ๋ฉด "movie", "film" ๊ฐ™์€ ๋‹จ์–ด๋Š” ๋„ˆ๋ฌด ํ”ํ•ด์„œ ๋ถˆ์šฉ์–ด๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ๊ณ ,
๋ฐ˜๋Œ€๋กœ ๊ฐ์„ฑ ๋ถ„์„์—์„œ๋Š” "not", "no" ๊ฐ™์€ ๋ถ€์ •์–ด๋Š” ๋ถˆ์šฉ์–ด์—์„œ ์ œ์™ธํ•ด์•ผ ํ•จ!

3๏ธโƒฃ ์–ด๊ฐ„ ์ถ”์ถœ(Stemming)๊ณผ ํ‘œ์ œ์–ด ์ถ”์ถœ(Lemmatization)

์ด ๋‘˜์€ ๋น„์Šทํ•ด ๋ณด์ด์ง€๋งŒ ์ ‘๊ทผ ๋ฐฉ์‹์ด ๋‹ค๋ฅธ ๊ธฐ์ˆ ์ด์•ผ:

from nltk.stem import PorterStemmer, LancasterStemmer, WordNetLemmatizer
from nltk.corpus import wordnet

# Stemming (์–ด๊ฐ„ ์ถ”์ถœ)
porter = PorterStemmer()
lancaster = LancasterStemmer()

words = ["running", "runs", "ran", "runner", "easily", "fairly"]

print("Porter Stemmer:")
for word in words:
    print(f"{word} โ†’ {porter.stem(word)}")

print("\nLancaster Stemmer:")
for word in words:
    print(f"{word} โ†’ {lancaster.stem(word)}")

# Lemmatization (ํ‘œ์ œ์–ด ์ถ”์ถœ)
lemmatizer = WordNetLemmatizer()

print("\nLemmatization:")
print(f"running (๋™์‚ฌ) โ†’ {lemmatizer.lemmatize('running', pos='v')}")
print(f"running (๋ช…์‚ฌ) โ†’ {lemmatizer.lemmatize('running', pos='n')}")
print(f"better (ํ˜•์šฉ์‚ฌ) โ†’ {lemmatizer.lemmatize('better', pos='a')}")
print(f"cacti (๋ช…์‚ฌ) โ†’ {lemmatizer.lemmatize('cacti', pos='n')}")

Stemming vs Lemmatization ์ฐจ์ด์ :

Stemming: ๊ทœ์น™ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹จ์–ด ๋์„ ์ž˜๋ผ๋ƒ„. ๋น ๋ฅด์ง€๋งŒ ๋ถ€์ •ํ™•ํ•  ์ˆ˜ ์žˆ์Œ
โ€ข "running" โ†’ "run" โœ…
โ€ข "better" โ†’ "better" โŒ (good์œผ๋กœ ๋ชป ๋ฐ”๊ฟˆ)

Lemmatization: ์‚ฌ์ „ ๊ธฐ๋ฐ˜์œผ๋กœ ์ •ํ™•ํ•œ ๊ธฐ๋ณธํ˜• ์ฐพ์Œ. ๋А๋ฆฌ์ง€๋งŒ ์ •ํ™•ํ•จ
โ€ข "running" โ†’ "run" โœ…
โ€ข "better" โ†’ "good" โœ…

์‹ค๋ฌด์—์„œ๋Š” ์ •ํ™•๋„๊ฐ€ ์ค‘์š”ํ•˜๋ฉด Lemmatization, ์†๋„๊ฐ€ ์ค‘์š”ํ•˜๋ฉด Stemming์„ ์“ฐ๋Š” ํŽธ์ด์•ผ ใ…‡ใ…‡

4๏ธโƒฃ ํ’ˆ์‚ฌ ํƒœ๊น…(POS Tagging)

ํ’ˆ์‚ฌ ํƒœ๊น…์€ ๊ฐ ๋‹จ์–ด๊ฐ€ ๋ช…์‚ฌ์ธ์ง€, ๋™์‚ฌ์ธ์ง€, ํ˜•์šฉ์‚ฌ์ธ์ง€ ๋“ฑ์„ ํŒ๋ณ„ํ•˜๋Š” ์ž‘์—…์ด์•ผ.
์ด๊ฒŒ ์™œ ์ค‘์š”ํ•˜๋ƒ๋ฉด, ๊ฐ™์€ ๋‹จ์–ด๋„ ํ’ˆ์‚ฌ์— ๋”ฐ๋ผ ์˜๋ฏธ๊ฐ€ ์™„์ „ํžˆ ๋‹ฌ๋ผ์ง€๊ฑฐ๋“ :

from nltk import pos_tag
from nltk.tokenize import word_tokenize

# ํ’ˆ์‚ฌ ํƒœ๊น… ์˜ˆ์‹œ
text1 = "They refuse to permit us to obtain the refuse permit."
words1 = word_tokenize(text1)
pos_tags1 = pos_tag(words1)

print("ํ’ˆ์‚ฌ ํƒœ๊น… ๊ฒฐ๊ณผ:")
for word, tag in pos_tags1:
    print(f"{word}: {tag}")

# ์ฃผ์š” ํ’ˆ์‚ฌ ํƒœ๊ทธ ์„ค๋ช…
# NN: ๋ช…์‚ฌ(๋‹จ์ˆ˜), NNS: ๋ช…์‚ฌ(๋ณต์ˆ˜), NNP: ๊ณ ์œ ๋ช…์‚ฌ
# VB: ๋™์‚ฌ(๊ธฐ๋ณธํ˜•), VBD: ๋™์‚ฌ(๊ณผ๊ฑฐํ˜•), VBG: ๋™์‚ฌ(ํ˜„์žฌ๋ถ„์‚ฌ)
# JJ: ํ˜•์šฉ์‚ฌ, RB: ๋ถ€์‚ฌ
# DT: ๊ด€์‚ฌ, IN: ์ „์น˜์‚ฌ
๐ŸŽฏ ํ’ˆ์‚ฌ ํƒœ๊น… ํ™œ์šฉ ์‚ฌ๋ก€ 1. ๊ฐ์„ฑ ๋ถ„์„: ํ˜•์šฉ์‚ฌ์™€ ๋ถ€์‚ฌ๋ฅผ ์ค‘์ ์ ์œผ๋กœ ๋ถ„์„ํ•ด์„œ ๊ธ์ •/๋ถ€์ • ํŒ๋‹จ
2. ์ •๋ณด ์ถ”์ถœ: ๊ณ ์œ ๋ช…์‚ฌ(NNP)๋ฅผ ์ฐพ์•„์„œ ์ธ๋ฌผ, ์žฅ์†Œ, ์กฐ์ง๋ช… ์ถ”์ถœ
3. ํ‚ค์›Œ๋“œ ์ถ”์ถœ: ๋ช…์‚ฌ์™€ ํ˜•์šฉ์‚ฌ ์กฐํ•ฉ์œผ๋กœ ์˜๋ฏธ ์žˆ๋Š” ํ‚ค์›Œ๋“œ ๋ฐœ๊ตด
4. ๋ฌธ๋ฒ• ๊ฒ€์‚ฌ: ํ’ˆ์‚ฌ ํŒจํ„ด์„ ๋ถ„์„ํ•ด์„œ ๋ฌธ๋ฒ• ์˜ค๋ฅ˜ ํƒ์ง€

5๏ธโƒฃ ๊ฐœ์ฒด๋ช… ์ธ์‹(Named Entity Recognition)

๊ฐœ์ฒด๋ช… ์ธ์‹์€ ํ…์ŠคํŠธ์—์„œ ์‚ฌ๋žŒ ์ด๋ฆ„, ์ง€๋ช…, ์กฐ์ง๋ช…, ๋‚ ์งœ ๋“ฑ์„ ์ž๋™์œผ๋กœ ์ฐพ์•„๋‚ด๋Š” ๊ธฐ์ˆ ์ด์•ผ:

from nltk import ne_chunk, pos_tag, word_tokenize
from nltk.tree import Tree

text = "Apple Inc. was founded by Steve Jobs in Cupertino, California on April 1, 1976."
words = word_tokenize(text)
pos_tags = pos_tag(words)
named_entities = ne_chunk(pos_tags)

print("๊ฐœ์ฒด๋ช… ์ธ์‹ ๊ฒฐ๊ณผ:")
for chunk in named_entities:
    if isinstance(chunk, Tree):
        entity = " ".join([token for token, pos in chunk.leaves()])
        entity_type = chunk.label()
        print(f"{entity}: {entity_type}")

# ์ถœ๋ ฅ ์˜ˆ์‹œ:
# Apple Inc.: ORGANIZATION
# Steve Jobs: PERSON
# Cupertino: GPE (์ง€์ •ํ•™์  ๊ฐœ์ฒด)
# California: GPE

๊ฐœ์ฒด๋ช… ์ธ์‹์€ ๋‰ด์Šค ๊ธฐ์‚ฌ ๋ถ„์„, ๋ฌธ์„œ ์ž๋™ ๋ถ„๋ฅ˜, ์ฑ—๋ด‡ ๊ฐœ๋ฐœ ๋“ฑ์—์„œ ์—„์ฒญ ์œ ์šฉํ•˜๊ฒŒ ์“ฐ์—ฌ.
ํŠนํžˆ ๋Œ€๋Ÿ‰์˜ ๋ฌธ์„œ์—์„œ ํŠน์ • ์ธ๋ฌผ์ด๋‚˜ ์กฐ์ง์— ๋Œ€ํ•œ ์–ธ๊ธ‰์„ ์ถ”์ ํ•  ๋•Œ ๊ฐœ๊ฟ€์ž„ ใ…‹ใ…‹ใ…‹

โšก spaCy: ์‚ฐ์—…์šฉ NLP์˜ ๊ฐ•์ž

NLTK๊ฐ€ ๊ต์œก์šฉ ์Šค์œ„์Šค ์•„๋ฏธ ๋‚˜์ดํ”„๋ผ๋ฉด, spaCy๋Š” ์‹ค์ „์šฉ ํŒŒ์›Œํˆด์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์–ด.
2015๋…„์— ๋‚˜์˜จ ๋น„๊ต์  ์ตœ์‹  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ๋ฐ, ์†๋„์™€ ์ •ํ™•๋„ ๋ฉด์—์„œ NLTK๋ฅผ ์••๋„ํ•˜๋Š” ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์คŒ ๐Ÿš€

spaCy์˜ ํ•ต์‹ฌ ํŠน์ง•:

1. ์••๋„์ ์ธ ์†๋„: Cython์œผ๋กœ ์ž‘์„ฑ๋˜์–ด NLTK๋ณด๋‹ค ์ˆ˜์‹ญ ๋ฐฐ ๋น ๋ฆ„
2. ๋”ฅ๋Ÿฌ๋‹ ๊ธฐ๋ฐ˜: ์ตœ์‹  ์‹ ๊ฒฝ๋ง ๋ชจ๋ธ์„ ํ™œ์šฉํ•œ ๋†’์€ ์ •ํ™•๋„
3. ํ”„๋กœ๋•์…˜ ๋ ˆ๋””: ์‹ค์ œ ์„œ๋น„์Šค์— ๋ฐ”๋กœ ์ ์šฉ ๊ฐ€๋Šฅํ•œ ์•ˆ์ •์„ฑ
4. ๋‹ค๊ตญ์–ด ์ง€์›: 60๊ฐœ ์ด์ƒ์˜ ์–ธ์–ด ๋ชจ๋ธ ์ œ๊ณต
5. ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์กฐ: ์—ฌ๋Ÿฌ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์—ฐ๊ฒฐ

์‹ค๋ฌด์—์„œ ๋Œ€์šฉ๋Ÿ‰ ํ…์ŠคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋ฉด spaCy๊ฐ€ ๊ฑฐ์˜ ํ•„์ˆ˜๋ผ๊ณ  ๋ด๋„ ๋จ ๐Ÿ’ช

๐Ÿ“ฆ spaCy ์„ค์น˜ ๋ฐ ๋ชจ๋ธ ๋‹ค์šด๋กœ๋“œ
# spaCy ์„ค์น˜
pip install spacy

# ์˜์–ด ๋ชจ๋ธ ๋‹ค์šด๋กœ๋“œ (ํฌ๊ธฐ๋ณ„๋กœ 3๊ฐ€์ง€)
python -m spacy download en_core_web_sm  # ์†Œํ˜• (12MB)
python -m spacy download en_core_web_md  # ์ค‘ํ˜• (40MB)
python -m spacy download en_core_web_lg  # ๋Œ€ํ˜• (560MB)

# ํ•œ๊ตญ์–ด ๋ชจ๋ธ (๋น„๊ณต์‹, ์„ฑ๋Šฅ ์ œํ•œ์ )
pip install spacy-korean
๐Ÿ’ก ๋ชจ๋ธ ์„ ํƒ ๊ฐ€์ด๋“œ โ€ข sm (small): ๋น ๋ฅธ ์†๋„, ๊ธฐ๋ณธ ๊ธฐ๋Šฅ๋งŒ ํ•„์š”ํ•  ๋•Œ
โ€ข md (medium): ๊ท ํ˜•์žกํžŒ ์„ฑ๋Šฅ, ์ผ๋ฐ˜์ ์ธ ์šฉ๋„์— ์ถ”์ฒœ
โ€ข lg (large): ์ตœ๊ณ  ์ •ํ™•๋„, ๋‹จ์–ด ๋ฒกํ„ฐ ํฌํ•จ, ๋ฉ”๋ชจ๋ฆฌ ์—ฌ์œ  ์žˆ์„ ๋•Œ

์ฒ˜์Œ์—” sm์œผ๋กœ ์‹œ์ž‘ํ•ด์„œ ํ•„์š”ํ•˜๋ฉด ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋Š” ๊ฒŒ ์ข‹์•„!
๐Ÿ”จ spaCy ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์‹ค์ „ ํ™œ์šฉ

1๏ธโƒฃ ๊ธฐ๋ณธ ํŒŒ์ดํ”„๋ผ์ธ ์‚ฌ์šฉ๋ฒ•

spaCy์˜ ๊ฐ€์žฅ ํฐ ํŠน์ง•์€ ํ•œ ๋ฒˆ์˜ ์ฒ˜๋ฆฌ๋กœ ํ† ํฐํ™”, ํ’ˆ์‚ฌ ํƒœ๊น…, ๊ฐœ์ฒด๋ช… ์ธ์‹ ๋“ฑ์„ ๋ชจ๋‘ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ๊ฑฐ์•ผ:

import spacy

# ๋ชจ๋ธ ๋กœ๋“œ
nlp = spacy.load("en_core_web_sm")

# ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ
text = "Apple is looking at buying U.K. startup for $1 billion"
doc = nlp(text)

# ํ† ํฐ ์ •๋ณด ์ถœ๋ ฅ
print("ํ† ํฐ ๋ถ„์„:")
for token in doc:
    print(f"{token.text:12} {token.pos_:8} {token.dep_:10} {token.lemma_}")

# ๊ฐœ์ฒด๋ช… ์ธ์‹
print("\n๊ฐœ์ฒด๋ช…:")
for ent in doc.ents:
    print(f"{ent.text:20} {ent.label_:15} {spacy.explain(ent.label_)}")

์ด ์ฝ”๋“œ ํ•œ ๋ฒˆ ์‹คํ–‰ํ•˜๋ฉด:
โ€ข ํ† ํฐํ™” โœ…
โ€ข ํ’ˆ์‚ฌ ํƒœ๊น… โœ…
โ€ข ์˜์กด ๊ตฌ๋ฌธ ๋ถ„์„ โœ…
โ€ข ํ‘œ์ œ์–ด ์ถ”์ถœ โœ…
โ€ข ๊ฐœ์ฒด๋ช… ์ธ์‹ โœ…

์ด ๋ชจ๋“  ๊ฒŒ ๋™์‹œ์— ์ฒ˜๋ฆฌ๋จ. NLTK๋กœ ํ•˜๋ ค๋ฉด ๊ฐ๊ฐ ๋”ฐ๋กœ ํ•จ์ˆ˜ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š”๋ฐ spaCy๋Š” ์›์ƒท์ด์•ผ ใ…‹ใ…‹ใ…‹

2๏ธโƒฃ ๋ฌธ์žฅ ๋ถ„๋ฆฌ์™€ ํ† ํฐ ์†์„ฑ

import spacy

nlp = spacy.load("en_core_web_sm")
text = """
spaCy is amazing! It can process text super fast.
Let's see how it handles multiple sentences.
"""

doc = nlp(text)

# ๋ฌธ์žฅ ๋ถ„๋ฆฌ
print("๋ฌธ์žฅ ๋ถ„๋ฆฌ:")
for i, sent in enumerate(doc.sents, 1):
    print(f"{i}. {sent.text.strip()}")

# ํ† ํฐ ์ƒ์„ธ ์†์„ฑ
print("\nํ† ํฐ ์ƒ์„ธ ๋ถ„์„:")
for token in doc[:10]:  # ์ฒ˜์Œ 10๊ฐœ๋งŒ
    print(f"""
    ํ…์ŠคํŠธ: {token.text}
    ํ‘œ์ œ์–ด: {token.lemma_}
    ํ’ˆ์‚ฌ: {token.pos_} ({spacy.explain(token.pos_)})
    ํƒœ๊ทธ: {token.tag_}
    ์˜์กด๊ด€๊ณ„: {token.dep_}
    ๋ถˆ์šฉ์–ด ์—ฌ๋ถ€: {token.is_stop}
    ๊ตฌ๋‘์  ์—ฌ๋ถ€: {token.is_punct}
    ์ˆซ์ž ์—ฌ๋ถ€: {token.like_num}
    """)

spaCy์˜ ํ† ํฐ ๊ฐ์ฒด๋Š” ์ง„์งœ ์ •๋ณด๊ฐ€ ํ’๋ถ€ํ•จ.
๊ฐ ํ† ํฐ๋งˆ๋‹ค 20๊ฐœ ์ด์ƒ์˜ ์†์„ฑ์„ ์ œ๊ณตํ•ด์„œ ์›ฌ๋งŒํ•œ ๋ถ„์„์€ ๋‹ค ๊ฐ€๋Šฅํ•ด ๐Ÿ‘

3๏ธโƒฃ ๋‹จ์–ด ๋ฒกํ„ฐ์™€ ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ

md๋‚˜ lg ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹จ์–ด๋ฅผ ๋ฒกํ„ฐ๋กœ ํ‘œํ˜„ํ•ด์„œ ์˜๋ฏธ์  ์œ ์‚ฌ๋„๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์–ด:

import spacy

# ๋ฒกํ„ฐ๊ฐ€ ํฌํ•จ๋œ ๋ชจ๋ธ ํ•„์š” (md ๋˜๋Š” lg)
nlp = spacy.load("en_core_web_md")

# ๋‹จ์–ด ์œ ์‚ฌ๋„
doc1 = nlp("dog")
doc2 = nlp("cat")
doc3 = nlp("banana")

print(f"dog vs cat: {doc1.similarity(doc2):.4f}")
print(f"dog vs banana: {doc1.similarity(doc3):.4f}")
print(f"cat vs banana: {doc2.similarity(doc3):.4f}")

# ๋ฌธ์žฅ ์œ ์‚ฌ๋„
sent1 = nlp("I love programming in Python")
sent2 = nlp("Python is my favorite programming language")
sent3 = nlp("I enjoy eating pizza")

print(f"\n๋ฌธ์žฅ ์œ ์‚ฌ๋„:")
print(f"sent1 vs sent2: {sent1.similarity(sent2):.4f}")
print(f"sent1 vs sent3: {sent1.similarity(sent3):.4f}")

์ด ๊ธฐ๋Šฅ์€ ์ถ”์ฒœ ์‹œ์Šคํ…œ, ๋ฌธ์„œ ๋ถ„๋ฅ˜, ์ค‘๋ณต ํƒ์ง€ ๋“ฑ์—์„œ ์—„์ฒญ ์œ ์šฉํ•˜๊ฒŒ ์“ฐ์—ฌ.
์˜ˆ๋ฅผ ๋“ค์–ด ๊ณ ๊ฐ ๋ฌธ์˜๋ฅผ ์ž๋™์œผ๋กœ ๋ถ„๋ฅ˜ํ•  ๋•Œ, ์ƒˆ๋กœ์šด ๋ฌธ์˜์™€ ๊ธฐ์กด ์นดํ…Œ๊ณ ๋ฆฌ์˜ ์œ ์‚ฌ๋„๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ์ž๋™ ๋ฐฐ์ •ํ•  ์ˆ˜ ์žˆ์Œ!

4๏ธโƒฃ ์ปค์Šคํ…€ ํŒŒ์ดํ”„๋ผ์ธ ์ปดํฌ๋„ŒํŠธ

spaCy์˜ ์ง„์งœ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ํŒŒ์ดํ”„๋ผ์ธ์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑฐ์•ผ:

import spacy
from spacy.language import Language

nlp = spacy.load("en_core_web_sm")

# ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ ์ •์˜
@Language.component("custom_sentiment")
def custom_sentiment_component(doc):
    # ๊ฐ„๋‹จํ•œ ๊ฐ์„ฑ ๋ถ„์„ ๋กœ์ง
    positive_words = {"good", "great", "excellent", "amazing", "wonderful"}
    negative_words = {"bad", "terrible", "awful", "horrible", "poor"}
    
    pos_count = sum(1 for token in doc if token.text.lower() in positive_words)
    neg_count = sum(1 for token in doc if token.text.lower() in negative_words)
    
    # ๋ฌธ์„œ์— ์ปค์Šคํ…€ ์†์„ฑ ์ถ”๊ฐ€
    doc._.sentiment_score = pos_count - neg_count
    doc._.sentiment = "positive" if pos_count > neg_count else "negative" if neg_count > pos_count else "neutral"
    
    return doc

# ์ปค์Šคํ…€ ์†์„ฑ ๋“ฑ๋ก
from spacy.tokens import Doc
Doc.set_extension("sentiment_score", default=0, force=True)
Doc.set_extension("sentiment", default="neutral", force=True)

# ํŒŒ์ดํ”„๋ผ์ธ์— ์ถ”๊ฐ€
nlp.add_pipe("custom_sentiment", last=True)

# ํ…Œ์ŠคํŠธ
texts = [
    "This product is amazing and wonderful!",
    "Terrible experience, very bad service.",
    "It's okay, nothing special."
]

for text in texts:
    doc = nlp(text)
    print(f"ํ…์ŠคํŠธ: {text}")
    print(f"๊ฐ์„ฑ: {doc._.sentiment} (์ ์ˆ˜: {doc._.sentiment_score})\n")

์ด๋Ÿฐ ์‹์œผ๋กœ ์ž๊ธฐ๋งŒ์˜ ๋ถ„์„ ๋กœ์ง์„ ํŒŒ์ดํ”„๋ผ์ธ์— ๋ผ์›Œ๋„ฃ์„ ์ˆ˜ ์žˆ์–ด.
์‹ค๋ฌด์—์„œ๋Š” ๋„๋ฉ”์ธ ํŠนํ™” ๊ทœ์น™์ด๋‚˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ด๋ ‡๊ฒŒ ์ถ”๊ฐ€ํ•ด์„œ ์“ฐ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ ใ…‡ใ…‡

๐ŸŽฏ spaCy vs NLTK ๋น„๊ต ์ •๋ฆฌ

ํ•ญ๋ชฉ NLTK spaCy
์†๋„ ๋А๋ฆผ (์ˆœ์ˆ˜ Python) ๋งค์šฐ ๋น ๋ฆ„ (Cython)
์ •ํ™•๋„ ๋ณดํ†ต ๋†’์Œ (๋”ฅ๋Ÿฌ๋‹ ๊ธฐ๋ฐ˜)
ํ•™์Šต ๊ณก์„  ์™„๋งŒํ•จ ์•ฝ๊ฐ„ ๊ฐ€ํŒŒ๋ฆ„
์šฉ๋„ ๊ต์œก, ์—ฐ๊ตฌ, ํ”„๋กœํ† ํƒ€์ž… ํ”„๋กœ๋•์…˜, ๋Œ€์šฉ๋Ÿ‰ ์ฒ˜๋ฆฌ
์œ ์—ฐ์„ฑ ๋งค์šฐ ๋†’์Œ ์ค‘๊ฐ„ (ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์กฐ)
๋ฌธ์„œํ™” ํ’๋ถ€ํ•จ ๋งค์šฐ ํ’๋ถ€ํ•จ
์ปค๋ฎค๋‹ˆํ‹ฐ ํฌ๊ณ  ์˜ค๋ž˜๋จ ๋น ๋ฅด๊ฒŒ ์„ฑ์žฅ ์ค‘

๊ฒฐ๋ก : ๋ฐฐ์šฐ๋Š” ๋‹จ๊ณ„์—์„œ๋Š” NLTK๋กœ ๊ฐœ๋… ์žก๊ณ , ์‹ค์ „์—์„œ๋Š” spaCy ์“ฐ๋Š” ๊ฒŒ ๋ฒ ์ŠคํŠธ ์กฐํ•ฉ!

๐Ÿ“Š ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ์‹ค์ „ ํ”„๋กœ์ ํŠธ: ์˜ํ™” ๋ฆฌ๋ทฐ ๊ฐ์„ฑ ๋ถ„์„

์ด๋ก ๋งŒ ๋ฐฐ์šฐ๋ฉด ์žฌ๋ฏธ์—†์œผ๋‹ˆ๊นŒ, ์ด์ œ ์‹ค์ œ๋กœ ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ํ”„๋กœ์ ํŠธ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ํ•ด๋ณด์ž!
์˜ํ™” ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ๊ธ์ •/๋ถ€์ •์„ ์ž๋™์œผ๋กœ ๋ถ„๋ฅ˜ํ•˜๋Š” ๊ฐ์„ฑ ๋ถ„์„ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ณผ ๊ฑฐ์•ผ ๐ŸŽฌ

์ด ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด ๋ฐฐ์šธ ๋‚ด์šฉ:
โ€ข ์‹ค์ œ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ฐ ์ „์ฒ˜๋ฆฌ
โ€ข NLTK์™€ spaCy๋ฅผ ํ™œ์šฉํ•œ ํ…์ŠคํŠธ ์ •์ œ
โ€ข ํŠน์ง• ์ถ”์ถœ (Feature Extraction)
โ€ข ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€
โ€ข ๊ฒฐ๊ณผ ์‹œ๊ฐํ™”

๐ŸŽฌ 1๋‹จ๊ณ„: ๋ฐ์ดํ„ฐ ์ค€๋น„

์‹ค์Šต์šฉ์œผ๋กœ IMDB ์˜ํ™” ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ์…‹์„ ์‚ฌ์šฉํ•  ๊ฑฐ์•ผ. ์ด๊ฑด 50,000๊ฐœ์˜ ๋ฆฌ๋ทฐ๊ฐ€ ์žˆ๋Š” ์œ ๋ช…ํ•œ ๋ฐ์ดํ„ฐ์…‹์ž„:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

# ๋ฐ์ดํ„ฐ ๋กœ๋“œ (์‹ค์ œ๋กœ๋Š” ํŒŒ์ผ์—์„œ ์ฝ์–ด์˜ด)
# ์—ฌ๊ธฐ์„œ๋Š” ์˜ˆ์‹œ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ
sample_reviews = [
    ("This movie was absolutely amazing! Best film I've seen this year.", "positive"),
    ("Terrible waste of time. I want my money back.", "negative"),
    ("Great acting and wonderful storyline. Highly recommended!", "positive"),
    ("Boring and predictable. Fell asleep halfway through.", "negative"),
    ("Masterpiece! The director outdid himself.", "positive"),
    ("Awful movie. Poor acting and terrible script.", "negative"),
]

# DataFrame ์ƒ์„ฑ
df = pd.DataFrame(sample_reviews, columns=['review', 'sentiment'])

# ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ด๋ ‡๊ฒŒ ๋กœ๋“œ
# df = pd.read_csv('IMDB_Dataset.csv')

print(f"์ „์ฒด ๋ฆฌ๋ทฐ ์ˆ˜: {len(df)}")
print(f"๊ธ์ • ๋ฆฌ๋ทฐ: {len(df[df['sentiment']=='positive'])}")
print(f"๋ถ€์ • ๋ฆฌ๋ทฐ: {len(df[df['sentiment']=='negative'])}")
print("\n์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ:")
print(df.head())
๐Ÿงน 2๋‹จ๊ณ„: ํ…์ŠคํŠธ ์ „์ฒ˜๋ฆฌ

์›์‹œ ํ…์ŠคํŠธ๋ฅผ ๋ถ„์„ ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ๋กœ ์ •์ œํ•˜๋Š” ๋‹จ๊ณ„์•ผ. ์—ฌ๊ธฐ์„œ NLTK์™€ spaCy๊ฐ€ ํ™œ์•ฝํ•จ:

import re
import spacy
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

# spaCy ๋ชจ๋ธ ๋กœ๋“œ
nlp = spacy.load("en_core_web_sm")

# ๋ถˆ์šฉ์–ด ์„ธํŠธ
stop_words = set(stopwords.words('english'))

def preprocess_text(text):
    """ํ…์ŠคํŠธ ์ „์ฒ˜๋ฆฌ ํ•จ์ˆ˜"""
    
    # 1. ์†Œ๋ฌธ์ž ๋ณ€ํ™˜
    text = text.lower()
    
    # 2. HTML ํƒœ๊ทธ ์ œ๊ฑฐ
    text = re.sub(r'<.*?>', '', text)
    
    # 3. URL ์ œ๊ฑฐ
    text = re.sub(r'http\S+|www\S+', '', text)
    
    # 4. ํŠน์ˆ˜๋ฌธ์ž ์ œ๊ฑฐ (์•ŒํŒŒ๋ฒณ๊ณผ ๊ณต๋ฐฑ๋งŒ ๋‚จ๊น€)
    text = re.sub(r'[^a-zA-Z\s]', '', text)
    
    # 5. spaCy๋กœ ์ฒ˜๋ฆฌ
    doc = nlp(text)
    
    # 6. ํ‘œ์ œ์–ด ์ถ”์ถœ + ๋ถˆ์šฉ์–ด ์ œ๊ฑฐ
    tokens = [
        token.lemma_ for token in doc 
        if not token.is_stop 
        and not token.is_punct 
        and len(token.text) > 2
    ]
    
    return ' '.join(tokens)

# ์ „์ฒ˜๋ฆฌ ์ ์šฉ
df['cleaned_review'] = df['review'].apply(preprocess_text)

print("์ „์ฒ˜๋ฆฌ ์ „ํ›„ ๋น„๊ต:")
for i in range(3):
    print(f"\n์›๋ณธ: {df['review'].iloc[i]}")
    print(f"์ „์ฒ˜๋ฆฌ ํ›„: {df['cleaned_review'].iloc[i]}")
๐Ÿ’ก ์ „์ฒ˜๋ฆฌ ํŒ ์ „์ฒ˜๋ฆฌ๋Š” ๋ฐ์ดํ„ฐ์™€ ๋ชฉ์ ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ ธ์•ผ ํ•ด:
โ€ข ๊ฐ์„ฑ ๋ถ„์„: ์ด๋ชจํ‹ฐ์ฝ˜, ๋А๋‚Œํ‘œ ๋“ฑ์€ ์œ ์ง€ํ•˜๋Š” ๊ฒŒ ์ข‹์„ ์ˆ˜ ์žˆ์Œ
โ€ข ํ† ํ”ฝ ๋ชจ๋ธ๋ง: ๋ช…์‚ฌ ์œ„์ฃผ๋กœ ์ถ”์ถœ
โ€ข ๋ฌธ์„œ ๋ถ„๋ฅ˜: ๊ณ ์œ ๋ช…์‚ฌ๋Š” ์ค‘์š”ํ•˜๋‹ˆ ๋ณด์กด

๋ฌด์กฐ๊ฑด ๋งŽ์ด ์ œ๊ฑฐํ•œ๋‹ค๊ณ  ์ข‹์€ ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋ถ„์„ ๋ชฉ์ ์— ๋งž๊ฒŒ ์กฐ์ ˆํ•˜๋Š” ๊ฒŒ ํ•ต์‹ฌ!
๐Ÿ”ข 3๋‹จ๊ณ„: ํŠน์ง• ์ถ”์ถœ (Feature Extraction)

๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์€ ์ˆซ์ž๋งŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ, ํ…์ŠคํŠธ๋ฅผ ์ˆซ์ž ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ด.
๋Œ€ํ‘œ์ ์ธ ๋ฐฉ๋ฒ•์ด TF-IDF์•ผ:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split

# TF-IDF ๋ฒกํ„ฐ๋ผ์ด์ € ์ƒ์„ฑ
tfidf = TfidfVectorizer(
    max_features=5000,  # ์ƒ์œ„ 5000๊ฐœ ๋‹จ์–ด๋งŒ ์‚ฌ์šฉ
    ngram_range=(1, 2),  # 1-gram๊ณผ 2-gram ๋ชจ๋‘ ์‚ฌ์šฉ
    min_df=2,  # ์ตœ์†Œ 2๋ฒˆ ์ด์ƒ ๋“ฑ์žฅํ•œ ๋‹จ์–ด๋งŒ
    max_df=0.8  # 80% ์ด์ƒ ๋ฌธ์„œ์— ๋“ฑ์žฅํ•˜๋Š” ๋‹จ์–ด ์ œ์™ธ
)

# ํŠน์ง• ๋ฒกํ„ฐ ์ƒ์„ฑ
X = tfidf.fit_transform(df['cleaned_review'])
y = df['sentiment'].map({'positive': 1, 'negative': 0})

# ํ•™์Šต/ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌ
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

print(f"ํ•™์Šต ๋ฐ์ดํ„ฐ: {X_train.shape}")
print(f"ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ: {X_test.shape}")
print(f"ํŠน์ง• ๋ฒกํ„ฐ ์ฐจ์›: {X.shape[1]}")

# ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋‹จ์–ด๋“ค ํ™•์ธ
feature_names = tfidf.get_feature_names_out()
print(f"\n์ถ”์ถœ๋œ ํŠน์ง• ์˜ˆ์‹œ: {feature_names[:20]}")
๐Ÿ“– TF-IDF๋ž€? TF-IDF (Term Frequency-Inverse Document Frequency)๋Š” ๋‹จ์–ด์˜ ์ค‘์š”๋„๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์•ผ.

โ€ข TF (Term Frequency): ํŠน์ • ๋ฌธ์„œ์—์„œ ๋‹จ์–ด๊ฐ€ ์–ผ๋งˆ๋‚˜ ์ž์ฃผ ๋‚˜์˜ค๋Š”๊ฐ€
โ€ข IDF (Inverse Document Frequency): ์ „์ฒด ๋ฌธ์„œ์—์„œ ๋‹จ์–ด๊ฐ€ ์–ผ๋งˆ๋‚˜ ํฌ๊ท€ํ•œ๊ฐ€

ํ•ต์‹ฌ ์•„์ด๋””์–ด: ํŠน์ • ๋ฌธ์„œ์—์„œ ์ž์ฃผ ๋‚˜์˜ค์ง€๋งŒ ๋‹ค๋ฅธ ๋ฌธ์„œ์—์„œ๋Š” ์ž˜ ์•ˆ ๋‚˜์˜ค๋Š” ๋‹จ์–ด๊ฐ€ ๊ทธ ๋ฌธ์„œ๋ฅผ ๋Œ€ํ‘œํ•˜๋Š” ์ค‘์š”ํ•œ ๋‹จ์–ด!

์˜ˆ๋ฅผ ๋“ค์–ด "์˜ํ™”"๋ผ๋Š” ๋‹จ์–ด๋Š” ๋ชจ๋“  ์˜ํ™” ๋ฆฌ๋ทฐ์— ๋‚˜์˜ค๋‹ˆ๊นŒ ์ค‘์š”๋„๊ฐ€ ๋‚ฎ๊ณ ,
"์Šค๋ฆด๋Ÿฌ"๋Š” ํŠน์ • ์žฅ๋ฅด ๋ฆฌ๋ทฐ์—๋งŒ ๋‚˜์˜ค๋‹ˆ๊นŒ ์ค‘์š”๋„๊ฐ€ ๋†’์•„์ง€๋Š” ์‹์ด์•ผ ใ…‡ใ…‡
๐Ÿค– 4๋‹จ๊ณ„: ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ ํ•™์Šต

์ด์ œ ์—ฌ๋Ÿฌ ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ํ•™์Šต์‹œ์ผœ์„œ ์„ฑ๋Šฅ์„ ๋น„๊ตํ•ด๋ณด์ž:

from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

# ์—ฌ๋Ÿฌ ๋ชจ๋ธ ์ •์˜
models = {
    'Naive Bayes': MultinomialNB(),
    'Logistic Regression': LogisticRegression(max_iter=1000),
    'Linear SVM': LinearSVC(max_iter=1000),
    'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42)
}

# ๊ฐ ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€
results = {}

for name, model in models.items():
    print(f"\n{'='*50}")
    print(f"๋ชจ๋ธ: {name}")
    print('='*50)
    
    # ํ•™์Šต
    model.fit(X_train, y_train)
    
    # ์˜ˆ์ธก
    y_pred = model.predict(X_test)
    
    # ํ‰๊ฐ€
    accuracy = accuracy_score(y_test, y_pred)
    results[name] = accuracy
    
    print(f"์ •ํ™•๋„: {accuracy:.4f}")
    print("\n๋ถ„๋ฅ˜ ๋ฆฌํฌํŠธ:")
    print(classification_report(y_test, y_pred, 
                                target_names=['Negative', 'Positive']))
    
    print("\nํ˜ผ๋™ ํ–‰๋ ฌ:")
    print(confusion_matrix(y_test, y_pred))

# ์ตœ๊ณ  ์„ฑ๋Šฅ ๋ชจ๋ธ
best_model = max(results, key=results.get)
print(f"\n๐Ÿ† ์ตœ๊ณ  ์„ฑ๋Šฅ ๋ชจ๋ธ: {best_model} (์ •ํ™•๋„: {results[best_model]:.4f})")
๐Ÿ” 5๋‹จ๊ณ„: ๋ชจ๋ธ ํ•ด์„ ๋ฐ ์ค‘์š” ํŠน์ง• ๋ถ„์„

๋ชจ๋ธ์ด ์–ด๋–ค ๋‹จ์–ด๋ฅผ ์ค‘์š”ํ•˜๊ฒŒ ์ƒ๊ฐํ•˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด์ž:

import numpy as np
import matplotlib.pyplot as plt

# Logistic Regression ๋ชจ๋ธ์˜ ๊ณ„์ˆ˜ ๋ถ„์„
lr_model = models['Logistic Regression']
feature_names = tfidf.get_feature_names_out()
coefficients = lr_model.coef_[0]

# ๊ธ์ •์  ์˜ํ–ฅ์„ ์ฃผ๋Š” ๋‹จ์–ด Top 20
top_positive_idx = np.argsort(coefficients)[-20:]
top_positive_words = [(feature_names[i], coefficients[i]) for i in top_positive_idx]

print("๊ธ์ • ๊ฐ์„ฑ์— ๊ฐ€์žฅ ์˜ํ–ฅ์„ ์ฃผ๋Š” ๋‹จ์–ด:")
for word, coef in reversed(top_positive_words):
    print(f"{word:20} {coef:.4f}")

# ๋ถ€์ •์  ์˜ํ–ฅ์„ ์ฃผ๋Š” ๋‹จ์–ด Top 20
top_negative_idx = np.argsort(coefficients)[:20]
top_negative_words = [(feature_names[i], coefficients[i]) for i in top_negative_idx]

print("\n๋ถ€์ • ๊ฐ์„ฑ์— ๊ฐ€์žฅ ์˜ํ–ฅ์„ ์ฃผ๋Š” ๋‹จ์–ด:")
for word, coef in top_negative_words:
    print(f"{word:20} {coef:.4f}")

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋ธ์ด "amazing", "excellent" ๊ฐ™์€ ๋‹จ์–ด๋ฅผ ๊ธ์ •์œผ๋กœ,
"terrible", "awful" ๊ฐ™์€ ๋‹จ์–ด๋ฅผ ๋ถ€์ •์œผ๋กœ ํ•™์Šตํ–ˆ๋‹ค๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด ใ…Žใ…Ž

๐ŸŽฏ 6๋‹จ๊ณ„: ์‹ค์‹œ๊ฐ„ ์˜ˆ์ธก ํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐ

์ด์ œ ์ƒˆ๋กœ์šด ๋ฆฌ๋ทฐ๊ฐ€ ๋“ค์–ด์™”์„ ๋•Œ ๋ฐ”๋กœ ๊ฐ์„ฑ์„ ์˜ˆ์ธกํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž:

def predict_sentiment(review_text, model, vectorizer, preprocessor):
    """
    ์ƒˆ๋กœ์šด ๋ฆฌ๋ทฐ์˜ ๊ฐ์„ฑ์„ ์˜ˆ์ธกํ•˜๋Š” ํ•จ์ˆ˜
    
    Args:
        review_text: ์˜ˆ์ธกํ•  ๋ฆฌ๋ทฐ ํ…์ŠคํŠธ
        model: ํ•™์Šต๋œ ๋ชจ๋ธ
        vectorizer: ํ•™์Šต๋œ TF-IDF ๋ฒกํ„ฐ๋ผ์ด์ €
        preprocessor: ์ „์ฒ˜๋ฆฌ ํ•จ์ˆ˜
    
    Returns:
        sentiment: 'Positive' ๋˜๋Š” 'Negative'
        probability: ์˜ˆ์ธก ํ™•๋ฅ 
    """
    # ์ „์ฒ˜๋ฆฌ
    cleaned_text = preprocessor(review_text)
    
    # ๋ฒกํ„ฐํ™”
    text_vector = vectorizer.transform([cleaned_text])
    
    # ์˜ˆ์ธก
    prediction = model.predict(text_vector)[0]
    probability = model.predict_proba(text_vector)[0]
    
    sentiment = "Positive" if prediction == 1 else "Negative"
    confidence = probability[prediction]
    
    return sentiment, confidence

# ํ…Œ์ŠคํŠธ
test_reviews = [
    "This movie is absolutely fantastic! I loved every minute of it.",
    "Worst movie ever. Complete waste of time and money.",
    "It was okay, nothing special but not terrible either.",
]

best_model_obj = models['Logistic Regression']

print("์‹ค์‹œ๊ฐ„ ์˜ˆ์ธก ํ…Œ์ŠคํŠธ:\n")
for review in test_reviews:
    sentiment, confidence = predict_sentiment(
        review, best_model_obj, tfidf, preprocess_text
    )
    print(f"๋ฆฌ๋ทฐ: {review}")
    print(f"์˜ˆ์ธก: {sentiment} (ํ™•์‹ ๋„: {confidence:.2%})\n")

์ด์ œ ์™„์ „ํžˆ ์ž‘๋™ํ•˜๋Š” ๊ฐ์„ฑ ๋ถ„์„ ์‹œ์Šคํ…œ์ด ์™„์„ฑ๋์–ด!
์‹ค์ œ ์„œ๋น„์Šค์— ์ ์šฉํ•˜๋ ค๋ฉด Flask๋‚˜ FastAPI๋กœ API๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ฐฐํฌํ•˜๋ฉด ๋จ ๐Ÿš€

๐ŸŽจ ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•๋“ค

๊ธฐ๋ณธ์ ์ธ ๊ฐ์„ฑ ๋ถ„์„์„ ๋„˜์–ด์„œ, ๋” ๊ณ ๊ธ‰ ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ๊ธฐ๋ฒ•๋“ค์„ ์•Œ์•„๋ณด์ž.
์ด๋Ÿฐ ๊ธฐ๋ฒ•๋“ค์€ ์‹ค๋ฌด์—์„œ ์ง„์งœ ๋งŽ์ด ์“ฐ์ด๋Š” ๊ฒƒ๋“ค์ด์•ผ ๐Ÿ’ก

๐Ÿ“š ํ† ํ”ฝ ๋ชจ๋ธ๋ง (Topic Modeling)

ํ† ํ”ฝ ๋ชจ๋ธ๋ง์€ ๋Œ€๋Ÿ‰์˜ ๋ฌธ์„œ์—์„œ ์ˆจ๊ฒจ์ง„ ์ฃผ์ œ๋ฅผ ์ž๋™์œผ๋กœ ์ฐพ์•„๋‚ด๋Š” ๊ธฐ์ˆ ์ด์•ผ.
๋Œ€ํ‘œ์ ์œผ๋กœ LDA (Latent Dirichlet Allocation)๊ฐ€ ๋งŽ์ด ์“ฐ์ž„:

from sklearn.decomposition import LatentDirichletAllocation
from sklearn.feature_extraction.text import CountVectorizer

# ์ƒ˜ํ”Œ ๋ฌธ์„œ (์‹ค์ œ๋กœ๋Š” ์ˆ˜๋ฐฑ~์ˆ˜์ฒœ ๊ฐœ)
documents = [
    "Python is a great programming language for data science",
    "Machine learning and deep learning are hot topics",
    "Natural language processing helps understand text data",
    "Data visualization is important for data analysis",
    "Neural networks are used in deep learning models",
]

# CountVectorizer๋กœ ๋ฌธ์„œ-๋‹จ์–ด ํ–‰๋ ฌ ์ƒ์„ฑ
vectorizer = CountVectorizer(max_features=100, stop_words='english')
doc_term_matrix = vectorizer.fit_transform(documents)

# LDA ๋ชจ๋ธ ํ•™์Šต
n_topics = 2
lda = LatentDirichletAllocation(
    n_components=n_topics,
    random_state=42,
    max_iter=10
)
lda.fit(doc_term_matrix)

# ํ† ํ”ฝ๋ณ„ ์ฃผ์š” ๋‹จ์–ด ์ถœ๋ ฅ
feature_names = vectorizer.get_feature_names_out()

print("๋ฐœ๊ฒฌ๋œ ํ† ํ”ฝ๋“ค:\n")
for topic_idx, topic in enumerate(lda.components_):
    top_words_idx = topic.argsort()[-10:][::-1]
    top_words = [feature_names[i] for i in top_words_idx]
    print(f"ํ† ํ”ฝ {topic_idx + 1}: {', '.join(top_words)}")

ํ† ํ”ฝ ๋ชจ๋ธ๋ง์€ ์ด๋Ÿฐ ๊ณณ์— ํ™œ์šฉ๋ผ:
โ€ข ๋‰ด์Šค ๊ธฐ์‚ฌ ์ž๋™ ๋ถ„๋ฅ˜
โ€ข ๊ณ ๊ฐ ๋ฆฌ๋ทฐ์—์„œ ์ฃผ์š” ๋ถˆ๋งŒ์‚ฌํ•ญ ํŒŒ์•…
โ€ข ์—ฐ๊ตฌ ๋…ผ๋ฌธ ํŠธ๋ Œ๋“œ ๋ถ„์„
โ€ข SNS ๋Œ€ํ™” ์ฃผ์ œ ์ถ”์ถœ

๐Ÿ”— Word2Vec๊ณผ ๋‹จ์–ด ์ž„๋ฒ ๋”ฉ

Word2Vec์€ ๋‹จ์–ด๋ฅผ ๋ฒกํ„ฐ ๊ณต๊ฐ„์— ๋ฐฐ์น˜ํ•ด์„œ ๋‹จ์–ด ๊ฐ„ ์˜๋ฏธ์  ๊ด€๊ณ„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ธฐ์ˆ ์ด์•ผ.
"์™• - ๋‚จ์ž + ์—ฌ์ž = ์—ฌ์™•" ๊ฐ™์€ ์‹ ๊ธฐํ•œ ์—ฐ์‚ฐ์ด ๊ฐ€๋Šฅํ•จ ใ…‹ใ…‹ใ…‹

from gensim.models import Word2Vec
from nltk.tokenize import word_tokenize

# ์ƒ˜ํ”Œ ๋ฌธ์žฅ๋“ค
sentences = [
    "the king sits on the throne",
    "the queen sits beside the king",
    "the prince is the son of the king",
    "the princess is the daughter of the queen",
]

# ํ† ํฐํ™”
tokenized_sentences = [word_tokenize(sent.lower()) for sent in sentences]

# Word2Vec ๋ชจ๋ธ ํ•™์Šต
model = Word2Vec(
    sentences=tokenized_sentences,
    vector_size=100,  # ๋ฒกํ„ฐ ์ฐจ์›
    window=5,  # ๋ฌธ๋งฅ ์œˆ๋„์šฐ ํฌ๊ธฐ
    min_count=1,  # ์ตœ์†Œ ๋“ฑ์žฅ ํšŸ์ˆ˜
    workers=4
)

# ์œ ์‚ฌํ•œ ๋‹จ์–ด ์ฐพ๊ธฐ
print("'king'๊ณผ ์œ ์‚ฌํ•œ ๋‹จ์–ด:")
similar_words = model.wv.most_similar('king', topn=5)
for word, similarity in similar_words:
    print(f"{word}: {similarity:.4f}")

# ๋‹จ์–ด ๊ฐ„ ์œ ์‚ฌ๋„
similarity = model.wv.similarity('king', 'queen')
print(f"\n'king'๊ณผ 'queen'์˜ ์œ ์‚ฌ๋„: {similarity:.4f}")

# ๋‹จ์–ด ์—ฐ์‚ฐ
result = model.wv.most_similar(
    positive=['king', 'woman'],
    negative=['man'],
    topn=1
)
print(f"\nking - man + woman = {result[0][0]}")
๐Ÿ’ก ์‹ค๋ฌด ํŒ Word2Vec์€ ์ถฉ๋ถ„ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ ํšจ๊ณผ์ ์ด์•ผ. ์ตœ์†Œ ์ˆ˜์ฒœ ๊ฐœ ์ด์ƒ์˜ ๋ฌธ์žฅ์ด ํ•„์š”ํ•จ.
๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€์กฑํ•˜๋ฉด ์‚ฌ์ „ ํ•™์Šต๋œ ๋ชจ๋ธ(GloVe, FastText ๋“ฑ)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์•„!
๐ŸŽฏ ๊ฐœ์ฒด๋ช… ์ธ์‹ (NER) ๊ณ ๊ธ‰ ํ™œ์šฉ

spaCy์˜ NER์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•ด์„œ ๋„๋ฉ”์ธ ํŠนํ™” ๊ฐœ์ฒด๋ฅผ ์ธ์‹ํ•˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด:

import spacy
from spacy.training import Example
from spacy.util import minibatch
import random

# ๊ธฐ๋ณธ ๋ชจ๋ธ ๋กœ๋“œ
nlp = spacy.blank("en")

# NER ํŒŒ์ดํ”„๋ผ์ธ ์ถ”๊ฐ€
if "ner" not in nlp.pipe_names:
    ner = nlp.add_pipe("ner")
else:
    ner = nlp.get_pipe("ner")

# ์ปค์Šคํ…€ ๋ ˆ์ด๋ธ” ์ถ”๊ฐ€ (์˜ˆ: ์ œํ’ˆ๋ช…)
ner.add_label("PRODUCT")

# ํ•™์Šต ๋ฐ์ดํ„ฐ (ํ…์ŠคํŠธ, {๊ฐœ์ฒด ์œ„์น˜์™€ ๋ ˆ์ด๋ธ”})
TRAIN_DATA = [
    ("I bought an iPhone 13 yesterday", {"entities": [(14, 23, "PRODUCT")]}),
    ("The new MacBook Pro is amazing", {"entities": [(8, 19, "PRODUCT")]}),
    ("Samsung Galaxy S21 has great camera", {"entities": [(0, 18, "PRODUCT")]}),
]

# ๋ชจ๋ธ ํ•™์Šต
optimizer = nlp.begin_training()
for epoch in range(10):
    random.shuffle(TRAIN_DATA)
    losses = {}
    
    for text, annotations in TRAIN_DATA:
        doc = nlp.make_doc(text)
        example = Example.from_dict(doc, annotations)
        nlp.update([example], drop=0.5, losses=losses)
    
    print(f"Epoch {epoch + 1}, Loss: {losses['ner']:.4f}")

# ํ…Œ์ŠคํŠธ
test_text = "I'm thinking about buying the new AirPods Pro"
doc = nlp(test_text)

print("\n์ธ์‹๋œ ๊ฐœ์ฒด:")
for ent in doc.ents:
    print(f"{ent.text}: {ent.label_}")

์ด๋Ÿฐ ์ปค์Šคํ…€ NER์€ ํŠนํžˆ ์ด๋Ÿฐ ๋ถ„์•ผ์—์„œ ์œ ์šฉํ•ด:
โ€ข ์˜๋ฃŒ: ์งˆ๋ณ‘๋ช…, ์•ฝ๋ฌผ๋ช… ์ถ”์ถœ
โ€ข ๋ฒ•๋ฅ : ๋ฒ•๋ฅ  ์šฉ์–ด, ํŒ๋ก€ ์ธ์‹
โ€ข ๊ธˆ์œต: ํšŒ์‚ฌ๋ช…, ๊ธˆ์œต์ƒํ’ˆ ์‹๋ณ„
โ€ข ์ „์ž์ƒ๊ฑฐ๋ž˜: ์ œํ’ˆ๋ช…, ๋ธŒ๋žœ๋“œ ์ถ”์ถœ

๐Ÿ“ˆ ํ…์ŠคํŠธ ๋ถ„๋ฅ˜ (Text Classification)

ํ…์ŠคํŠธ ๋ถ„๋ฅ˜๋Š” ๋ฌธ์„œ๋ฅผ ๋ฏธ๋ฆฌ ์ •์˜๋œ ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ์ž๋™ ๋ถ„๋ฅ˜ํ•˜๋Š” ๊ฑฐ์•ผ.
๋”ฅ๋Ÿฌ๋‹์„ ํ™œ์šฉํ•˜๋ฉด ๋” ๋†’์€ ์ •ํ™•๋„๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์–ด:

# ๊ฐ„๋‹จํ•œ CNN ๊ธฐ๋ฐ˜ ํ…์ŠคํŠธ ๋ถ„๋ฅ˜ (๊ฐœ๋… ์ฝ”๋“œ)
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, Conv1D, GlobalMaxPooling1D, Dense, Dropout
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

# ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ
vocab_size = 10000
embedding_dim = 100
max_length = 200
num_classes = 5

# ๋ชจ๋ธ ๊ตฌ์กฐ
model = Sequential([
    Embedding(vocab_size, embedding_dim, input_length=max_length),
    Conv1D(128, 5, activation='relu'),
    GlobalMaxPooling1D(),
    Dense(64, activation='relu'),
    Dropout(0.5),
    Dense(num_classes, activation='softmax')
])

model.compile(
    optimizer='adam',
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

print(model.summary())

์‹ค๋ฌด์—์„œ๋Š” BERT, GPT ๊ฐ™์€ ํŠธ๋žœ์Šคํฌ๋จธ ๋ชจ๋ธ์„ ํŒŒ์ธํŠœ๋‹ํ•ด์„œ ์“ฐ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„.
Hugging Face ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Œ ๐Ÿ‘

๐Ÿ› ๏ธ ์‹ค๋ฌด์—์„œ ์ž์ฃผ ๋งˆ์ฃผ์น˜๋Š” ๋ฌธ์ œ๋“ค๊ณผ ํ•ด๊ฒฐ๋ฒ•

์ด๋ก ์€ ์™„๋ฒฝํ•ด๋„ ์‹ค์ „์—์„œ๋Š” ์˜ˆ์ƒ ๋ชปํ•œ ๋ฌธ์ œ๋“ค์ด ํ„ฐ์ ธ ๋‚˜์™€ ใ…‹ใ…‹ใ…‹
๋‚ด๊ฐ€ ์‹ค๋ฌด์—์„œ ๊ฒช์—ˆ๋˜ ๋ฌธ์ œ๋“ค๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ๊ณต์œ ํ•ด๋ณผ๊ฒŒ ๐Ÿ’ช

๐Ÿ”ฅ ๋ฌธ์ œ 1: ํ•œ๊ตญ์–ด ์ฒ˜๋ฆฌ๊ฐ€ ์˜์–ด๋งŒํผ ์•ˆ ๋จ

์ฆ์ƒ: NLTK๋‚˜ spaCy๋กœ ํ•œ๊ตญ์–ด ์ฒ˜๋ฆฌํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ์—‰๋ง
์›์ธ: ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์˜์–ด ์ค‘์‹ฌ์œผ๋กœ ์„ค๊ณ„๋จ
ํ•ด๊ฒฐ:
โ€ข KoNLPy ์‚ฌ์šฉ (Okt, Komoran, Mecab ๋“ฑ)
โ€ข ํ•œ๊ตญ์–ด ํŠนํ™” ๋ชจ๋ธ ํ™œ์šฉ (KoBERT, KoGPT ๋“ฑ)
โ€ข ํ˜•ํƒœ์†Œ ๋ถ„์„๊ธฐ ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉ

# KoNLPy ์˜ˆ์‹œ
from konlpy.tag import Okt

okt = Okt()
text = "์ž์—ฐ์–ด ์ฒ˜๋ฆฌ๋Š” ์ •๋ง ์žฌ๋ฏธ์žˆ์–ด์š”!"

# ํ˜•ํƒœ์†Œ ๋ถ„์„
morphs = okt.morphs(text)
print("ํ˜•ํƒœ์†Œ:", morphs)

# ๋ช…์‚ฌ ์ถ”์ถœ
nouns = okt.nouns(text)
print("๋ช…์‚ฌ:", nouns)

# ํ’ˆ์‚ฌ ํƒœ๊น…
pos = okt.pos(text)
print("ํ’ˆ์‚ฌ:", pos)
๐Ÿ”ฅ ๋ฌธ์ œ 2: ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ์—๋Ÿฌ

์ฆ์ƒ: ๋Œ€์šฉ๋Ÿ‰ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ ์‹œ MemoryError ๋ฐœ์ƒ
์›์ธ: ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ํ•œ ๋ฒˆ์— ๋กœ๋“œ
ํ•ด๊ฒฐ:
โ€ข ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ (Batch Processing)
โ€ข ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ™œ์šฉ
โ€ข ์ฒญํฌ ๋‹จ์œ„๋กœ ํŒŒ์ผ ์ฝ๊ธฐ

# ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•œ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์  ์ฒ˜๋ฆฌ
def process_large_file(filename, batch_size=1000):
    """๋Œ€์šฉ๋Ÿ‰ ํŒŒ์ผ์„ ๋ฐฐ์น˜๋กœ ์ฒ˜๋ฆฌ"""
    batch = []
    
    with open(filename, 'r', encoding='utf-8') as f:
        for line in f:
            batch.append(line.strip())
            
            if len(batch) >= batch_size:
                # ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ
                yield process_batch(batch)
                batch = []
        
        # ๋‚จ์€ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
        if batch:
            yield process_batch(batch)

def process_batch(texts):
    """๋ฐฐ์น˜ ๋‹จ์œ„ ์ฒ˜๋ฆฌ ๋กœ์ง"""
    # ์—ฌ๊ธฐ์„œ ์‹ค์ œ NLP ์ฒ˜๋ฆฌ
    return [preprocess_text(text) for text in texts]

# ์‚ฌ์šฉ
for processed_batch in process_large_file('huge_file.txt'):
    # ์ฒ˜๋ฆฌ๋œ ๋ฐฐ์น˜๋กœ ์ž‘์—…
    save_to_database(processed_batch)
๐Ÿ”ฅ ๋ฌธ์ œ 3: ์ฒ˜๋ฆฌ ์†๋„๊ฐ€ ๋„ˆ๋ฌด ๋А๋ฆผ

์ฆ์ƒ: ์ˆ˜๋งŒ ๊ฐœ ๋ฌธ์„œ ์ฒ˜๋ฆฌ์— ๋ช‡ ์‹œ๊ฐ„์”ฉ ๊ฑธ๋ฆผ
์›์ธ: ์ˆœ์ฐจ ์ฒ˜๋ฆฌ, ๋น„ํšจ์œจ์ ์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜
ํ•ด๊ฒฐ:
โ€ข ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ ํ™œ์šฉ
โ€ข spaCy์˜ nlp.pipe() ์‚ฌ์šฉ
โ€ข GPU ๊ฐ€์† (๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ)

import spacy
from multiprocessing import Pool

nlp = spacy.load("en_core_web_sm")

# ๋น„ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ• โŒ
texts = ["text1", "text2", ...]
docs = [nlp(text) for text in texts]  # ๋А๋ฆผ!

# ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ• โœ…
docs = list(nlp.pipe(texts, batch_size=50))  # ํ›จ์”ฌ ๋น ๋ฆ„!

# ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ ํ™œ์šฉ
def process_text(text):
    doc = nlp(text)
    return [token.lemma_ for token in doc]

if __name__ == '__main__':
    with Pool(processes=4) as pool:
        results = pool.map(process_text, texts)
๐Ÿ”ฅ ๋ฌธ์ œ 4: ์‹ ์กฐ์–ด, ์€์–ด, ์˜คํƒ€ ์ฒ˜๋ฆฌ

์ฆ์ƒ: SNS ๋ฐ์ดํ„ฐ์—์„œ "ใ…‹ใ…‹ใ…‹", "ใ„นใ…‡", "๊ฟ€์žผ" ๊ฐ™์€ ํ‘œํ˜„ ์ฒ˜๋ฆฌ ์•ˆ ๋จ
์›์ธ: ์‚ฌ์ „์— ์—†๋Š” ๋‹จ์–ด๋“ค
ํ•ด๊ฒฐ:
โ€ข ์ปค์Šคํ…€ ์‚ฌ์ „ ๊ตฌ์ถ•
โ€ข ์ •๊ทœํ‘œํ˜„์‹์œผ๋กœ ํŒจํ„ด ์ฒ˜๋ฆฌ
โ€ข ์˜คํƒ€ ๊ต์ • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ

import re
from collections import defaultdict

# ์‹ ์กฐ์–ด ์‚ฌ์ „
slang_dict = {
    'ใ…‹ใ…‹ใ…‹': '์›ƒ์Œ',
    'ใ„นใ…‡': '๋ฆฌ์–ผ',
    '๊ฟ€์žผ': '์žฌ๋ฏธ์žˆ์Œ',
    'ใ…‡ใ…ˆ': '์ธ์ •',
    'ใ„ดใ„ด': '๋…ธ๋…ธ',
}

def normalize_slang(text):
    """์‹ ์กฐ์–ด๋ฅผ ํ‘œ์ค€์–ด๋กœ ๋ณ€ํ™˜"""
    for slang, standard in slang_dict.items():
        text = text.replace(slang, standard)
    return text

# ๋ฐ˜๋ณต ๋ฌธ์ž ์ •๊ทœํ™”
def normalize_repeats(text):
    """ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ โ†’ ใ…‹ใ…‹"""
    text = re.sub(r'(.)\1{2,}', r'\1\1', text)
    return text

# ์˜คํƒ€ ๊ต์ • (๊ฐ„๋‹จํ•œ ๋ฒ„์ „)
def simple_spell_check(word, dictionary):
    """ํŽธ์ง‘ ๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜ ์˜คํƒ€ ๊ต์ •"""
    if word in dictionary:
        return word
    
    # 1๊ธ€์ž ์ฐจ์ด๋‚˜๋Š” ๋‹จ์–ด ์ฐพ๊ธฐ
    candidates = []
    for dict_word in dictionary:
        if abs(len(word) - len(dict_word)) <= 1:
            distance = edit_distance(word, dict_word)
            if distance <= 1:
                candidates.append((dict_word, distance))
    
    if candidates:
        return min(candidates, key=lambda x: x[1])[0]
    return word
โš ๏ธ ์‹ค๋ฌด ์ฃผ์˜์‚ฌํ•ญ 1. ๋ฐ์ดํ„ฐ ํŽธํ–ฅ: ํ•™์Šต ๋ฐ์ดํ„ฐ๊ฐ€ ํŽธํ–ฅ๋˜๋ฉด ๋ชจ๋ธ๋„ ํŽธํ–ฅ๋จ. ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํ™•๋ณด ํ•„์ˆ˜
2. ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ: ์‹ค์ œ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ ๋‹ค๋ฃฐ ๋•Œ๋Š” ๊ฐœ์ธ์ •๋ณด ๋งˆ์Šคํ‚น ํ•„์ˆ˜
3. ๋ชจ๋ธ ์—…๋ฐ์ดํŠธ: ์–ธ์–ด๋Š” ๊ณ„์† ๋ณ€ํ™”ํ•จ. ์ •๊ธฐ์ ์ธ ๋ชจ๋ธ ์žฌํ•™์Šต ํ•„์š”
4. ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง: ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์ง€์†์ ์ธ ์„ฑ๋Šฅ ์ถ”์  ๋ฐ ๊ฐœ์„ 

๐ŸŽ“ ํ•™์Šต ๋กœ๋“œ๋งต๊ณผ ์ถ”์ฒœ ๋ฆฌ์†Œ์Šค

ํ…์ŠคํŠธ ๋งˆ์ด๋‹์„ ์ œ๋Œ€๋กœ ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‹ค๋ฉด ์ฒด๊ณ„์ ์ธ ํ•™์Šต์ด ์ค‘์š”ํ•ด.
๋‚ด๊ฐ€ ์ถ”์ฒœํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ๋กœ๋“œ๋งต์„ ๊ณต์œ ํ• ๊ฒŒ ๐Ÿ“š

ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ํ•™์Šต ๋กœ๋“œ๋งต 1๋‹จ๊ณ„: ๊ธฐ์ดˆ Python ๊ธฐ๋ณธ ์ •๊ทœํ‘œํ˜„์‹ 2๋‹จ๊ณ„: NLP ๊ธฐ์ดˆ NLTK ๋งˆ์Šคํ„ฐ ํ† ํฐํ™”, ํ’ˆ์‚ฌํƒœ๊น… 3๋‹จ๊ณ„: ๊ณ ๊ธ‰ NLP spaCy ํ™œ์šฉ Word2Vec, GloVe 4๋‹จ๊ณ„: ๋จธ์‹ ๋Ÿฌ๋‹ ํ…์ŠคํŠธ ๋ถ„๋ฅ˜ ๊ฐ์„ฑ ๋ถ„์„ 5๋‹จ๊ณ„: ๋”ฅ๋Ÿฌ๋‹ RNN, LSTM Transformer 6๋‹จ๊ณ„: ์‹ค์ „ ํ”„๋กœ์ ํŠธ ์ˆ˜ํ–‰ ํฌํŠธํด๋ฆฌ์˜ค ๊ตฌ์ถ• ์ถ”์ฒœ ํ•™์Šต ๋ฆฌ์†Œ์Šค ๐Ÿ“š ์ฑ… โ€ข Natural Language Processing with Python (NLTK ๊ณต์‹ ๊ฐ€์ด๋“œ) โ€ข Speech and Language Processing (NLP ๋ฐ”์ด๋ธ”) ๐ŸŽฅ ๊ฐ•์˜ โ€ข Stanford CS224N (NLP with Deep Learning) โ€ข Fast.ai NLP Course ๐ŸŒ ์‚ฌ์ดํŠธ โ€ข Kaggle (์‹ค์ „ ๋ฐ์ดํ„ฐ์…‹ ๋ฐ ์ปดํ”ผํ‹ฐ์…˜) โ€ข Papers with Code (์ตœ์‹  ์—ฐ๊ตฌ ๋™ํ–ฅ) ๐Ÿ’ป ์‹ค์Šต โ€ข GitHub ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ ์ฐธ์—ฌ โ€ข ์žฌ๋Šฅ๋„ท์—์„œ ์‹ค์ „ ํ”„๋กœ์ ํŠธ ์ˆ˜์ฃผ
๐Ÿ“– ๋‹จ๊ณ„๋ณ„ ์ƒ์„ธ ๊ฐ€์ด๋“œ

1๏ธโƒฃ ๊ธฐ์ดˆ ๋‹จ๊ณ„ (1-2๊ฐœ์›”)

โ€ข Python ๊ธฐ๋ณธ ๋ฌธ๋ฒ• ์™„๋ฒฝํžˆ ์ตํžˆ๊ธฐ
โ€ข ๋ฆฌ์ŠคํŠธ, ๋”•์…”๋„ˆ๋ฆฌ, ํ•จ์ˆ˜, ํด๋ž˜์Šค ๋“ฑ
โ€ข ์ •๊ทœํ‘œํ˜„์‹ ๋งˆ์Šคํ„ฐ (re ๋ชจ๋“ˆ)
โ€ข ํŒŒ์ผ ์ž…์ถœ๋ ฅ, ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ

์ถ”์ฒœ ์‹ค์Šต: ๊ฐ„๋‹จํ•œ ํ…์ŠคํŠธ ํŒŒ์ผ ์ฝ์–ด์„œ ๋‹จ์–ด ๋นˆ๋„์ˆ˜ ์„ธ๊ธฐ, ํŠน์ • ํŒจํ„ด ์ฐพ๊ธฐ ๋“ฑ

2๏ธโƒฃ NLP ๊ธฐ์ดˆ ๋‹จ๊ณ„ (2-3๊ฐœ์›”)

โ€ข NLTK ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ „์ฒด ๊ธฐ๋Šฅ ํ•™์Šต
โ€ข ํ† ํฐํ™”, ํ’ˆ์‚ฌ ํƒœ๊น…, ๊ฐœ์ฒด๋ช… ์ธ์‹
โ€ข ๋ถˆ์šฉ์–ด ์ฒ˜๋ฆฌ, ์–ด๊ฐ„ ์ถ”์ถœ
โ€ข ๊ธฐ๋ณธ์ ์ธ ํ…์ŠคํŠธ ์ „์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•

์ถ”์ฒœ ์‹ค์Šต: ๋‰ด์Šค ๊ธฐ์‚ฌ ํฌ๋กค๋งํ•ด์„œ ํ‚ค์›Œ๋“œ ์ถ”์ถœ, ๊ฐ„๋‹จํ•œ ์›Œ๋“œํด๋ผ์šฐ๋“œ ์ƒ์„ฑ

3๏ธโƒฃ ๊ณ ๊ธ‰ NLP ๋‹จ๊ณ„ (2-3๊ฐœ์›”)

โ€ข spaCy๋กœ ํšจ์œจ์ ์ธ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ
โ€ข Word2Vec, GloVe ๋“ฑ ๋‹จ์–ด ์ž„๋ฒ ๋”ฉ
โ€ข TF-IDF, BM25 ๋“ฑ ์ •๋ณด ๊ฒ€์ƒ‰ ๊ธฐ๋ฒ•
โ€ข ์˜์กด ๊ตฌ๋ฌธ ๋ถ„์„, ๊ณต์ง€์‹œ ํ•ด์†Œ

์ถ”์ฒœ ์‹ค์Šต: ์œ ์‚ฌ ๋ฌธ์„œ ์ฐพ๊ธฐ ์‹œ์Šคํ…œ, ๊ฐ„๋‹จํ•œ ๊ฒ€์ƒ‰ ์—”์ง„ ๊ตฌํ˜„

4๏ธโƒฃ ๋จธ์‹ ๋Ÿฌ๋‹ ๋‹จ๊ณ„ (3-4๊ฐœ์›”)

โ€ข scikit-learn์œผ๋กœ ํ…์ŠคํŠธ ๋ถ„๋ฅ˜
โ€ข Naive Bayes, SVM, Random Forest
โ€ข ๊ฐ์„ฑ ๋ถ„์„, ์ŠคํŒธ ํ•„ํ„ฐ๋ง
โ€ข ํ† ํ”ฝ ๋ชจ๋ธ๋ง (LDA, NMF)

์ถ”์ฒœ ์‹ค์Šต: ์˜ํ™” ๋ฆฌ๋ทฐ ๊ฐ์„ฑ ๋ถ„์„, ๋‰ด์Šค ๊ธฐ์‚ฌ ์ž๋™ ๋ถ„๋ฅ˜

5๏ธโƒฃ ๋”ฅ๋Ÿฌ๋‹ ๋‹จ๊ณ„ (4-6๊ฐœ์›”)

โ€ข RNN, LSTM์œผ๋กœ ์‹œํ€€์Šค ๋ชจ๋ธ๋ง
โ€ข Attention ๋ฉ”์ปค๋‹ˆ์ฆ˜ ์ดํ•ด
โ€ข Transformer, BERT ๋“ฑ ์ตœ์‹  ๋ชจ๋ธ
โ€ข Hugging Face Transformers ํ™œ์šฉ

์ถ”์ฒœ ์‹ค์Šต: ์ฑ—๋ด‡ ๊ตฌํ˜„, ๊ธฐ๊ณ„ ๋ฒˆ์—ญ, ๋ฌธ์„œ ์š”์•ฝ

6๏ธโƒฃ ์‹ค์ „ ๋‹จ๊ณ„ (์ง€์†์ )

โ€ข ์‹ค์ œ ๋น„์ฆˆ๋‹ˆ์Šค ๋ฌธ์ œ ํ•ด๊ฒฐ
โ€ข ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ฒฝํ—˜
โ€ข ๋ชจ๋ธ ๋ฐฐํฌ ๋ฐ ์„œ๋น™
โ€ข ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง

์ถ”์ฒœ ์‹ค์Šต: Kaggle ์ปดํ”ผํ‹ฐ์…˜ ์ฐธ๊ฐ€, ์˜คํ”ˆ์†Œ์Šค ๊ธฐ์—ฌ, ํฌํŠธํด๋ฆฌ์˜ค ํ”„๋กœ์ ํŠธ

๐Ÿ’ก ํ•™์Šต ํŒ 1. ๋งค์ผ ์กฐ๊ธˆ์”ฉ: ํ•˜๋ฃจ 1-2์‹œ๊ฐ„์”ฉ ๊พธ์ค€ํžˆ ํ•˜๋Š” ๊ฒŒ ์ฃผ๋ง์— ๋ชฐ์•„์„œ ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํšจ๊ณผ์ 
2. ์†์œผ๋กœ ์ง์ ‘ ์ฝ”๋”ฉ: ๋ณต๋ถ™ํ•˜์ง€ ๋ง๊ณ  ์ง์ ‘ ํƒ€์ดํ•‘ํ•˜๋ฉด์„œ ์ตํžˆ๊ธฐ
3. ์ž‘์€ ํ”„๋กœ์ ํŠธ๋ถ€ํ„ฐ: ๊ฑฐ์ฐฝํ•œ ๊ฒƒ๋ณด๋‹ค ์™„์„ฑ ๊ฐ€๋Šฅํ•œ ์ž‘์€ ํ”„๋กœ์ ํŠธ๋กœ ์‹œ์ž‘
4. ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™œ์šฉ: Stack Overflow, Reddit, ํ•œ๊ตญ NLP ์ปค๋ฎค๋‹ˆํ‹ฐ ๋“ฑ์—์„œ ์งˆ๋ฌธํ•˜๊ณ  ๋‹ต๋ณ€ํ•˜๊ธฐ
5. ์ตœ์‹  ํŠธ๋ Œ๋“œ ํŒ”๋กœ์šฐ: arXiv, Papers with Code์—์„œ ์ตœ์‹  ๋…ผ๋ฌธ ์ฝ๊ธฐ

ํŠนํžˆ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ์‹ค์ œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ˆ˜์ฃผํ•ด๋ณด๋Š” ๊ฒƒ๋„ ์—„์ฒญ ์ข‹์€ ํ•™์Šต ๋ฐฉ๋ฒ•์ด์•ผ.
์‹ค์ „ ๊ฒฝํ—˜๋งŒํผ ๋น ๋ฅด๊ฒŒ ์„ฑ์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—†๊ฑฐ๋“  ใ…Žใ…Ž

๐Ÿš€ ํ…์ŠคํŠธ ๋งˆ์ด๋‹์˜ ๋ฏธ๋ž˜์™€ ํŠธ๋ Œ๋“œ

ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ๋ถ„์•ผ๋Š” ์ •๋ง ๋น ๋ฅด๊ฒŒ ๋ฐœ์ „ํ•˜๊ณ  ์žˆ์–ด.
์•ž์œผ๋กœ ์–ด๋–ค ๋ฐฉํ–ฅ์œผ๋กœ ๋‚˜์•„๊ฐˆ์ง€, ์–ด๋–ค ๊ธฐ์ˆ ๋“ค์ด ์ฃผ๋ชฉ๋ฐ›์„์ง€ ์•Œ์•„๋ณด์ž ๐Ÿ”ฎ

๐Ÿค– ๋Œ€๊ทœ๋ชจ ์–ธ์–ด ๋ชจ๋ธ (LLM)์˜ ์‹œ๋Œ€

GPT-3, GPT-4, Claude, Gemini ๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ์–ธ์–ด ๋ชจ๋ธ์ด ๊ฒŒ์ž„ ์ฒด์ธ์ €๊ฐ€ ๋˜๊ณ  ์žˆ์–ด.
์ด์ œ๋Š” ๋ชจ๋ธ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•™์Šต์‹œํ‚ค๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ์‚ฌ์ „ ํ•™์Šต๋œ ๋ชจ๋ธ์„ ํŒŒ์ธํŠœ๋‹ํ•˜๋Š” ๊ฒŒ ๋Œ€์„ธ์•ผ:

# Hugging Face Transformers ์˜ˆ์‹œ
from transformers import pipeline

# ๊ฐ์„ฑ ๋ถ„์„ ํŒŒ์ดํ”„๋ผ์ธ (์‚ฌ์ „ ํ•™์Šต ๋ชจ๋ธ ํ™œ์šฉ)
classifier = pipeline("sentiment-analysis")

results = classifier([
    "I love this product!",
    "This is terrible.",
    "It's okay, nothing special."
])

for result in results:
    print(f"{result['label']}: {result['score']:.4f}")

# ํ…์ŠคํŠธ ์ƒ์„ฑ
generator = pipeline("text-generation", model="gpt2")
output = generator("Natural language processing is", max_length=50)
print(output[0]['generated_text'])

LLM์˜ ์žฅ์ :
โ€ข ๋ณ„๋„ ํ•™์Šต ์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ (Zero-shot Learning)
โ€ข ์†Œ๋Ÿ‰์˜ ์˜ˆ์‹œ๋งŒ์œผ๋กœ ํ•™์Šต (Few-shot Learning)
โ€ข ๋‹ค์–‘ํ•œ ํƒœ์Šคํฌ๋ฅผ ํ•˜๋‚˜์˜ ๋ชจ๋ธ๋กœ ์ฒ˜๋ฆฌ
โ€ข ์ธ๊ฐ„ ์ˆ˜์ค€์˜ ํ…์ŠคํŠธ ์ดํ•ด ๋ฐ ์ƒ์„ฑ

๐ŸŒ ๋‹ค๊ตญ์–ด NLP์˜ ๋ฐœ์ „

์˜์–ด ์ค‘์‹ฌ์—์„œ ๋ฒ—์–ด๋‚˜ ๋‹ค์–‘ํ•œ ์–ธ์–ด๋ฅผ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•˜๋Š” ๋ชจ๋ธ๋“ค์ด ๋‚˜์˜ค๊ณ  ์žˆ์–ด:

๋ชจ๋ธ ํŠน์ง• ์ง€์› ์–ธ์–ด
mBERT ๋‹ค๊ตญ์–ด BERT 104๊ฐœ ์–ธ์–ด
XLM-R ํฌ๋กœ์Šค๋ง๊ตฌ์–ผ ๋ชจ๋ธ 100๊ฐœ ์–ธ์–ด
mT5 ๋‹ค๊ตญ์–ด T5 101๊ฐœ ์–ธ์–ด
BLOOM ์˜คํ”ˆ์†Œ์Šค LLM 46๊ฐœ ์–ธ์–ด

ํ•œ๊ตญ์–ด NLP๋„ ๋น ๋ฅด๊ฒŒ ๋ฐœ์ „ ์ค‘:
โ€ข KoBERT, KoGPT, KoBART ๋“ฑ ํ•œ๊ตญ์–ด ํŠนํ™” ๋ชจ๋ธ
โ€ข ๋„ค์ด๋ฒ„, ์นด์นด์˜ค ๋“ฑ ๊ธฐ์—…๋“ค์˜ ๋Œ€๊ทœ๋ชจ ํˆฌ์ž
โ€ข ํ•œ๊ตญ์–ด ๋ฐ์ดํ„ฐ์…‹ ๊ณต๊ฐœ ๋ฐ ๋ฒค์น˜๋งˆํฌ ๊ตฌ์ถ•

๐ŸŽฏ ๋„๋ฉ”์ธ ํŠนํ™” NLP

๋ฒ”์šฉ ๋ชจ๋ธ์—์„œ ํŠน์ • ๋ถ„์•ผ์— ํŠนํ™”๋œ ๋ชจ๋ธ๋กœ ์ง„ํ™” ์ค‘:

์˜๋ฃŒ NLP
โ€ข BioBERT, PubMedBERT: ์˜ํ•™ ๋…ผ๋ฌธ ํ•™์Šต
โ€ข ์ „์ž์˜๋ฌด๊ธฐ๋ก(EMR) ์ž๋™ ๋ถ„์„
โ€ข ์•ฝ๋ฌผ ์ƒํ˜ธ์ž‘์šฉ ์˜ˆ์ธก

๋ฒ•๋ฅ  NLP
โ€ข LegalBERT: ๋ฒ•๋ฅ  ๋ฌธ์„œ ํŠนํ™”
โ€ข ๊ณ„์•ฝ์„œ ์ž๋™ ๊ฒ€ํ† 
โ€ข ํŒ๋ก€ ๊ฒ€์ƒ‰ ๋ฐ ๋ถ„์„

๊ธˆ์œต NLP
โ€ข FinBERT: ๊ธˆ์œต ๋‰ด์Šค ๊ฐ์„ฑ ๋ถ„์„
โ€ข ๋ฆฌ์Šคํฌ ํ‰๊ฐ€ ์ž๋™ํ™”
โ€ข ์‚ฌ๊ธฐ ํƒ์ง€ ์‹œ์Šคํ…œ

๐Ÿ”’ ์ฑ…์ž„ ์žˆ๋Š” AI์™€ ์œค๋ฆฌ

๊ธฐ์ˆ ์ด ๋ฐœ์ „ํ• ์ˆ˜๋ก ์œค๋ฆฌ์  ์ด์Šˆ๋„ ์ค‘์š”ํ•ด์ง€๊ณ  ์žˆ์–ด:

โš ๏ธ ์ฃผ์š” ์œค๋ฆฌ์  ๊ณ ๋ ค์‚ฌํ•ญ 1. ํŽธํ–ฅ(Bias): ํ•™์Šต ๋ฐ์ดํ„ฐ์˜ ํŽธํ–ฅ์ด ๋ชจ๋ธ์— ๋ฐ˜์˜๋จ
โ€ข ์„ฑ๋ณ„, ์ธ์ข…, ๋‚˜์ด ๋“ฑ์— ๋Œ€ํ•œ ์ฐจ๋ณ„์  ๊ฒฐ๊ณผ
โ€ข ํ•ด๊ฒฐ: ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํ™•๋ณด, ๊ณต์ •์„ฑ ๋ฉ”ํŠธ๋ฆญ ๋ชจ๋‹ˆํ„ฐ๋ง

2. ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ: ํ…์ŠคํŠธ์— ํฌํ•จ๋œ ๋ฏผ๊ฐ ์ •๋ณด
โ€ข ์ด๋ฆ„, ์ฃผ์†Œ, ์ „ํ™”๋ฒˆํ˜ธ ๋“ฑ ๊ฐœ์ธ ์‹๋ณ„ ์ •๋ณด
โ€ข ํ•ด๊ฒฐ: ๋ฐ์ดํ„ฐ ์ต๋ช…ํ™”, ์ฐจ๋“ฑ ํ”„๋ผ์ด๋ฒ„์‹œ ์ ์šฉ

3. ํ—ˆ์œ„์ •๋ณด ์ƒ์„ฑ: LLM์˜ ๊ทธ๋Ÿด๋“ฏํ•œ ๊ฑฐ์ง“๋ง
โ€ข ๋”ฅํŽ˜์ดํฌ ํ…์ŠคํŠธ, ๊ฐ€์งœ ๋‰ด์Šค ์ž๋™ ์ƒ์„ฑ
โ€ข ํ•ด๊ฒฐ: ํŒฉํŠธ ์ฒดํ‚น ์‹œ์Šคํ…œ, ์ถœ์ฒ˜ ํ‘œ์‹œ

4. ํˆฌ๋ช…์„ฑ: ๋ธ”๋ž™๋ฐ•์Šค ๋ชจ๋ธ์˜ ์„ค๋ช… ๊ฐ€๋Šฅ์„ฑ
โ€ข ์™œ ๊ทธ๋Ÿฐ ๊ฒฐ์ •์„ ๋‚ด๋ ธ๋Š”์ง€ ์„ค๋ช… ์–ด๋ ค์›€
โ€ข ํ•ด๊ฒฐ: LIME, SHAP ๋“ฑ ์„ค๋ช… ๊ฐ€๋Šฅ AI ๊ธฐ๋ฒ• ํ™œ์šฉ
๐Ÿ“ฑ ์—ฃ์ง€ AI์™€ ๊ฒฝ๋Ÿ‰ํ™”

ํด๋ผ์šฐ๋“œ๊ฐ€ ์•„๋‹Œ ๋””๋ฐ”์ด์Šค์—์„œ ์ง์ ‘ NLP ์ฒ˜๋ฆฌํ•˜๋Š” ์ถ”์„ธ:

โ€ข ๋ชจ๋ธ ๊ฒฝ๋Ÿ‰ํ™”: DistilBERT, TinyBERT ๋“ฑ
โ€ข ์–‘์žํ™”: ๋ชจ๋ธ ํฌ๊ธฐ ์ค„์ด๋ฉด์„œ ์„ฑ๋Šฅ ์œ ์ง€
โ€ข ํ”„๋ฃจ๋‹: ๋ถˆํ•„์š”ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ์ œ๊ฑฐ
โ€ข ์ง€์‹ ์ฆ๋ฅ˜: ํฐ ๋ชจ๋ธ์˜ ์ง€์‹์„ ์ž‘์€ ๋ชจ๋ธ๋กœ ์ „๋‹ฌ

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์Šค๋งˆํŠธํฐ, IoT ๊ธฐ๊ธฐ์—์„œ๋„ ๊ณ ๊ธ‰ NLP ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ ๐Ÿ“ฑ

๐Ÿ”ฎ ํ–ฅํ›„ 5๋…„ ์˜ˆ์ธก 1. ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ AI: ํ…์ŠคํŠธ+์ด๋ฏธ์ง€+์Œ์„ฑ์„ ํ†ตํ•ฉ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ชจ๋ธ ๋ณดํŽธํ™”
2. ์‹ค์‹œ๊ฐ„ ๋ฒˆ์—ญ: ๊ฑฐ์˜ ์™„๋ฒฝํ•œ ์ˆ˜์ค€์˜ ๋™์‹œํ†ต์—ญ ์‹คํ˜„
3. ๊ฐœ์ธํ™” AI ๋น„์„œ: ๊ฐœ์ธ ๋งž์ถคํ˜• ์–ธ์–ด ๋ชจ๋ธ์ด ์ผ์ƒํ™”
4. ์ฝ”๋“œ ์ƒ์„ฑ: ์ž์—ฐ์–ด๋กœ ํ”„๋กœ๊ทธ๋žจ ์ž๋™ ์ž‘์„ฑ (GitHub Copilot ์ˆ˜์ค€ ์ด์ƒ)
5. ์ฐฝ์ž‘ ์ง€์›: ์†Œ์„ค, ์‹œ๋‚˜๋ฆฌ์˜ค, ์Œ์•… ๊ฐ€์‚ฌ ๋“ฑ ์ฐฝ์ž‘ ํ™œ๋™ AI ํ˜‘์—…

ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ์ „๋ฌธ๊ฐ€์˜ ์ˆ˜์š”๋Š” ๊ณ„์† ์ฆ๊ฐ€ํ•  ๊ฑฐ์•ผ. ์ง€๊ธˆ ๋ฐฐ์›Œ๋‘๋ฉด ๋ฏธ๋ž˜๊ฐ€ ๋ฐ์Œ ใ…Žใ…Ž

๐Ÿ’ผ ์‹ค๋ฌด ํ™œ์šฉ ์‚ฌ๋ก€์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๊ฐ€์น˜

์ด๋ก ๊ณผ ๊ธฐ์ˆ ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ, ๊ฒฐ๊ตญ ์‹ค๋ฌด์—์„œ ์–ด๋–ป๊ฒŒ ์“ฐ์ด๋Š”์ง€๊ฐ€ ๊ฐ€์žฅ ์ค‘์š”ํ•˜์ง€ ใ…‡ใ…‡
๋‹ค์–‘ํ•œ ์‚ฐ์—…์—์„œ ํ…์ŠคํŠธ ๋งˆ์ด๋‹์ด ์–ด๋–ป๊ฒŒ ํ™œ์šฉ๋˜๋Š”์ง€ ์‚ดํŽด๋ณด์ž ๐Ÿ’ผ

๐Ÿ›’ ์ „์ž์ƒ๊ฑฐ๋ž˜: ๊ณ ๊ฐ ๋ฆฌ๋ทฐ ๋ถ„์„

๋ฌธ์ œ: ํ•˜๋ฃจ์— ์ˆ˜์ฒœ ๊ฐœ์”ฉ ์Œ“์ด๋Š” ์ƒํ’ˆ ๋ฆฌ๋ทฐ๋ฅผ ์ผ์ผ์ด ์ฝ์„ ์ˆ˜ ์—†์Œ
ํ•ด๊ฒฐ: ํ…์ŠคํŠธ ๋งˆ์ด๋‹์œผ๋กœ ์ž๋™ ๋ถ„์„

๊ตฌํ˜„ ๋‚ด์šฉ:
โ€ข ๊ฐ์„ฑ ๋ถ„์„์œผ๋กœ ๊ธ์ •/๋ถ€์ • ๋ฆฌ๋ทฐ ์ž๋™ ๋ถ„๋ฅ˜
โ€ข ํ† ํ”ฝ ๋ชจ๋ธ๋ง์œผ๋กœ ์ฃผ์š” ๋ถˆ๋งŒ์‚ฌํ•ญ ์ถ”์ถœ
โ€ข ํ‚ค์›Œ๋“œ ๋ถ„์„์œผ๋กœ ์ œํ’ˆ ๊ฐœ์„ ์  ๋„์ถœ
โ€ข ๊ฐ€์งœ ๋ฆฌ๋ทฐ ํƒ์ง€ ์‹œ์Šคํ…œ

๋น„์ฆˆ๋‹ˆ์Šค ํšจ๊ณผ:
โœ… ์ œํ’ˆ ๊ฐœ์„  ์‚ฌ์ดํด 50% ๋‹จ์ถ•
โœ… ๊ณ ๊ฐ ๋งŒ์กฑ๋„ 15% ํ–ฅ์ƒ
โœ… ๊ฐ€์งœ ๋ฆฌ๋ทฐ 90% ์ด์ƒ ์ฐจ๋‹จ

# ๋ฆฌ๋ทฐ ๋ถ„์„ ํŒŒ์ดํ”„๋ผ์ธ ์˜ˆ์‹œ
class ReviewAnalyzer:
    def __init__(self):
        self.sentiment_model = load_sentiment_model()
        self.topic_model = load_topic_model()
        self.fake_detector = load_fake_detector()
    
    def analyze_review(self, review_text):
        """๋ฆฌ๋ทฐ ์ข…ํ•ฉ ๋ถ„์„"""
        results = {
            'sentiment': self.sentiment_model.predict(review_text),
            'topics': self.topic_model.extract_topics(review_text),
            'is_fake': self.fake_detector.predict(review_text),
            'key_phrases': self.extract_key_phrases(review_text)
        }
        return results
    
    def generate_insights(self, reviews):
        """์ „์ฒด ๋ฆฌ๋ทฐ์—์„œ ์ธ์‚ฌ์ดํŠธ ์ถ”์ถœ"""
        # ๊ฐ์„ฑ ๋ถ„ํฌ
        sentiment_dist = self.get_sentiment_distribution(reviews)
        
        # ์ฃผ์š” ๋ถˆ๋งŒ์‚ฌํ•ญ
        complaints = self.extract_complaints(reviews)
        
        # ๊ฐœ์„  ์ œ์•ˆ
        suggestions = self.generate_suggestions(complaints)
        
        return {
            'sentiment_distribution': sentiment_dist,
            'top_complaints': complaints,
            'improvement_suggestions': suggestions
        }
๐Ÿ“ฐ ๋ฏธ๋””์–ด: ๋‰ด์Šค ์ž๋™ ๋ถ„๋ฅ˜ ๋ฐ ์š”์•ฝ

๋ฌธ์ œ: ์‹ค์‹œ๊ฐ„์œผ๋กœ ์Ÿ์•„์ง€๋Š” ๋‰ด์Šค๋ฅผ ๋น ๋ฅด๊ฒŒ ๋ถ„๋ฅ˜ํ•˜๊ณ  ์š”์•ฝ ํ•„์š”
ํ•ด๊ฒฐ: NLP ๊ธฐ๋ฐ˜ ์ž๋™ํ™” ์‹œ์Šคํ…œ

๊ตฌํ˜„ ๋‚ด์šฉ:
โ€ข ๋‰ด์Šค ๊ธฐ์‚ฌ ์ž๋™ ์นดํ…Œ๊ณ ๋ฆฌ ๋ถ„๋ฅ˜ (์ •์น˜, ๊ฒฝ์ œ, ์‚ฌํšŒ ๋“ฑ)
โ€ข ์ค‘์š” ๋ฌธ์žฅ ์ถ”์ถœ๋กœ 3์ค„ ์š”์•ฝ ์ƒ์„ฑ
โ€ข ๊ฐœ์ฒด๋ช… ์ธ์‹์œผ๋กœ ์ฃผ์š” ์ธ๋ฌผ/์žฅ์†Œ ํƒœ๊น…
โ€ข ์œ ์‚ฌ ๊ธฐ์‚ฌ ํด๋Ÿฌ์Šคํ„ฐ๋ง์œผ๋กœ ์ค‘๋ณต ์ œ๊ฑฐ

๋น„์ฆˆ๋‹ˆ์Šค ํšจ๊ณผ:
โœ… ํŽธ์ง‘ ์‹œ๊ฐ„ 70% ์ ˆ๊ฐ
โœ… ๋‰ด์Šค ๋ฐœํ–‰ ์†๋„ 3๋ฐฐ ํ–ฅ์ƒ
โœ… ๋…์ž ์ฒด๋ฅ˜ ์‹œ๊ฐ„ 25% ์ฆ๊ฐ€

๐Ÿฅ ์˜๋ฃŒ: ์ „์ž์˜๋ฌด๊ธฐ๋ก ๋ถ„์„

๋ฌธ์ œ: ์˜์‚ฌ์˜ ์ž์œ  ํ˜•์‹ ์ง„๋ฃŒ ๊ธฐ๋ก์—์„œ ์ •๋ณด ์ถ”์ถœ ์–ด๋ ค์›€
ํ•ด๊ฒฐ: ์˜๋ฃŒ ํŠนํ™” NLP ์‹œ์Šคํ…œ

๊ตฌํ˜„ ๋‚ด์šฉ:
โ€ข ์ฆ์ƒ, ์ง„๋‹จ๋ช…, ์ฒ˜๋ฐฉ์•ฝ ์ž๋™ ์ถ”์ถœ
โ€ข ์˜ํ•™ ์šฉ์–ด ํ‘œ์ค€ํ™” (SNOMED CT, ICD-10)
โ€ข ์•ฝ๋ฌผ ์ƒํ˜ธ์ž‘์šฉ ์ž๋™ ๊ฒฝ๊ณ 
โ€ข ์œ ์‚ฌ ์‚ฌ๋ก€ ๊ฒ€์ƒ‰์œผ๋กœ ์ง„๋‹จ ์ง€์›

๋น„์ฆˆ๋‹ˆ์Šค ํšจ๊ณผ:
โœ… ์ง„๋ฃŒ ๊ธฐ๋ก ์ž‘์„ฑ ์‹œ๊ฐ„ 40% ๋‹จ์ถ•
โœ… ์˜๋ฃŒ ์˜ค๋ฅ˜ 30% ๊ฐ์†Œ
โœ… ์—ฐ๊ตฌ ๋ฐ์ดํ„ฐ ํ™œ์šฉ๋„ ๋Œ€ํญ ํ–ฅ์ƒ

๐Ÿ’ฌ ๊ณ ๊ฐ ์„œ๋น„์Šค: ์ฑ—๋ด‡ ๋ฐ ์ž๋™ ์‘๋‹ต

๋ฌธ์ œ: ๋ฐ˜๋ณต์ ์ธ ๊ณ ๊ฐ ๋ฌธ์˜ ์ฒ˜๋ฆฌ์— ์ธ๋ ฅ ๋‚ญ๋น„
ํ•ด๊ฒฐ: ์ง€๋Šฅํ˜• ์ฑ—๋ด‡ ์‹œ์Šคํ…œ

๊ตฌํ˜„ ๋‚ด์šฉ:
โ€ข ์˜๋„ ๋ถ„๋ฅ˜(Intent Classification)๋กœ ๋ฌธ์˜ ์œ ํ˜• ํŒŒ์•…
โ€ข ๊ฐœ์ฒด๋ช… ์ธ์‹์œผ๋กœ ์ฃผ๋ฌธ๋ฒˆํ˜ธ, ์ œํ’ˆ๋ช… ๋“ฑ ์ถ”์ถœ
โ€ข ์ง€์‹ ๋ฒ ์ด์Šค ๊ฒ€์ƒ‰์œผ๋กœ ์ ์ ˆํ•œ ๋‹ต๋ณ€ ์ œ๊ณต
โ€ข ๊ฐ์„ฑ ๋ถ„์„์œผ๋กœ ๋ถˆ๋งŒ ๊ณ ๊ฐ ์šฐ์„  ์ฒ˜๋ฆฌ

๋น„์ฆˆ๋‹ˆ์Šค ํšจ๊ณผ:
โœ… ๋‹จ์ˆœ ๋ฌธ์˜ 80% ์ž๋™ ์ฒ˜๋ฆฌ
โœ… ์‘๋‹ต ์‹œ๊ฐ„ 90% ๋‹จ์ถ•
โœ… ๊ณ ๊ฐ ๋งŒ์กฑ๋„ 20% ํ–ฅ์ƒ
โœ… ์ƒ๋‹ด์‚ฌ ์—…๋ฌด ํšจ์œจ 2๋ฐฐ ์ฆ๊ฐ€

# ๊ฐ„๋‹จํ•œ ์ฑ—๋ด‡ ์˜๋„ ๋ถ„๋ฅ˜ ์˜ˆ์‹œ
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import LinearSVC

class IntentClassifier:
    def __init__(self):
        self.vectorizer = TfidfVectorizer()
        self.classifier = LinearSVC()
        self.intents = {
            'order_status': '์ฃผ๋ฌธ ์กฐํšŒ',
            'return': '๋ฐ˜ํ’ˆ/๊ตํ™˜',
            'payment': '๊ฒฐ์ œ ๋ฌธ์˜',
            'product_info': '์ œํ’ˆ ์ •๋ณด',
            'complaint': '๋ถˆ๋งŒ ์ ‘์ˆ˜'
        }
    
    def train(self, training_data):
        """ํ•™์Šต ๋ฐ์ดํ„ฐ๋กœ ๋ชจ๋ธ ํ›ˆ๋ จ"""
        texts = [item['text'] for item in training_data]
        labels = [item['intent'] for item in training_data]
        
        X = self.vectorizer.fit_transform(texts)
        self.classifier.fit(X, labels)
    
    def predict(self, user_message):
        """์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€์˜ ์˜๋„ ์˜ˆ์ธก"""
        X = self.vectorizer.transform([user_message])
        intent = self.classifier.predict(X)[0]
        
        return {
            'intent': intent,
            'intent_name': self.intents.get(intent, '๊ธฐํƒ€'),
            'confidence': self.classifier.decision_function(X).max()
        }

# ์‚ฌ์šฉ ์˜ˆ์‹œ
bot = IntentClassifier()
# bot.train(training_data)  # ์‹ค์ œ๋กœ๋Š” ํ•™์Šต ํ•„์š”

user_input = "์ œ ์ฃผ๋ฌธ์ด ์–ธ์ œ ๋„์ฐฉํ•˜๋‚˜์š”?"
result = bot.predict(user_input)
print(f"์˜๋„: {result['intent_name']}, ํ™•์‹ ๋„: {result['confidence']:.2f}")
๐Ÿ“Š ๊ธˆ์œต: ๋ฆฌ์Šคํฌ ๋ถ„์„ ๋ฐ ์‚ฌ๊ธฐ ํƒ์ง€

๋ฌธ์ œ: ๋Œ€์ถœ ์‹ฌ์‚ฌ, ์‚ฌ๊ธฐ ๊ฑฐ๋ž˜ ํƒ์ง€์— ์‹œ๊ฐ„๊ณผ ๋น„์šฉ ๊ณผ๋‹ค
ํ•ด๊ฒฐ: ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ๋ฆฌ์Šคํฌ ํ‰๊ฐ€ ์‹œ์Šคํ…œ

๊ตฌํ˜„ ๋‚ด์šฉ:
โ€ข ๋‰ด์Šค, SNS ๋ถ„์„์œผ๋กœ ๊ธฐ์—… ํ‰ํŒ ๋ชจ๋‹ˆํ„ฐ๋ง
โ€ข ์žฌ๋ฌด์ œํ‘œ ํ…์ŠคํŠธ ๋ถ„์„์œผ๋กœ ๋ฆฌ์Šคํฌ ์š”์ธ ์ถ”์ถœ
โ€ข ๊ฑฐ๋ž˜ ๋ฉ”๋ชจ ๋ถ„์„์œผ๋กœ ์ด์ƒ ํŒจํ„ด ํƒ์ง€
โ€ข ๊ฐ์„ฑ ๋ถ„์„์œผ๋กœ ์‹œ์žฅ ์‹ฌ๋ฆฌ ํŒŒ์•…

๋น„์ฆˆ๋‹ˆ์Šค ํšจ๊ณผ:
โœ… ๋Œ€์ถœ ์‹ฌ์‚ฌ ์‹œ๊ฐ„ 60% ๋‹จ์ถ•
โœ… ์‚ฌ๊ธฐ ํƒ์ง€์œจ 45% ํ–ฅ์ƒ
โœ… ๋ถ€์‹ค ์ฑ„๊ถŒ 30% ๊ฐ์†Œ

๐Ÿ’ก ์‹ค๋ฌด ์ ์šฉ ํŒ 1. ์ž‘๊ฒŒ ์‹œ์ž‘ํ•˜๊ธฐ: ์ „์‚ฌ ์‹œ์Šคํ…œ๋ณด๋‹ค ํŠน์ • ๋ถ€์„œ/ํ”„๋กœ์„ธ์Šค๋ถ€ํ„ฐ
2. ROI ์ธก์ •: ๋ช…ํ™•ํ•œ ์„ฑ๊ณผ ์ง€ํ‘œ ์„ค์ • (์‹œ๊ฐ„ ์ ˆ๊ฐ, ๋น„์šฉ ์ ˆ๊ฐ ๋“ฑ)
3. ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ: ์‹ค์ œ ์‚ฌ์šฉ์ž์˜ ์˜๊ฒฌ์„ ์ง€์†์ ์œผ๋กœ ๋ฐ˜์˜
4. ์ ์ง„์  ๊ฐœ์„ : ์™„๋ฒฝํ•œ ์‹œ์Šคํ…œ๋ณด๋‹ค ๋น ๋ฅธ ์ถœ์‹œ ํ›„ ๊ฐœ์„ 
5. ๋„๋ฉ”์ธ ์ „๋ฌธ๊ฐ€ ํ˜‘์—…: ๊ธฐ์ˆ ๋งŒ์œผ๋กœ๋Š” ๋ถ€์กฑ, ์—…๋ฌด ์ดํ•ด ํ•„์ˆ˜

์žฌ๋Šฅ๋„ท์—์„œ ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ํ”„๋กœ์ ํŠธ๋ฅผ ์ฐพ์•„๋ณด๋ฉด ์‹ค์ œ ๊ธฐ์—…๋“ค์ด ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์–ด.
์ด๋Ÿฐ ์‹ค์ „ ๊ฒฝํ—˜์ด ํฌํŠธํด๋ฆฌ์˜ค์—๋„ ์ข‹๊ณ , ์‹ค๋ ฅ ํ–ฅ์ƒ์—๋„ ์ตœ๊ณ ์•ผ ใ…‡ใ…‡

๐ŸŽฏ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์™€... ์—ฌ๊ธฐ๊นŒ์ง€ ์ฝ๋А๋ผ ์ˆ˜๊ณ ํ–ˆ์–ด ใ…‹ใ…‹ใ…‹
ํ…์ŠคํŠธ ๋งˆ์ด๋‹๊ณผ NLTK, spaCy์— ๋Œ€ํ•ด ์ •๋ง ๋งŽ์€ ๋‚ด์šฉ์„ ๋‹ค๋ค˜์ง€?

๊ฐ„๋‹จํ•˜๊ฒŒ ํ•ต์‹ฌ๋งŒ ์ •๋ฆฌํ•ด๋ณด๋ฉด:

๐ŸŽ“ ํ•ต์‹ฌ ์š”์•ฝ 1. ํ…์ŠคํŠธ ๋งˆ์ด๋‹์ด๋ž€?
โ€ข ๋น„์ •ํ˜• ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์—์„œ ์˜๋ฏธ ์žˆ๋Š” ์ •๋ณด ์ถ”์ถœ
โ€ข ๊ฐ์„ฑ ๋ถ„์„, ํ† ํ”ฝ ๋ชจ๋ธ๋ง, ๋ฌธ์„œ ๋ถ„๋ฅ˜ ๋“ฑ ๋‹ค์–‘ํ•œ ํ™œ์šฉ
โ€ข ๋ฐ์ดํ„ฐ์˜ 80%๊ฐ€ ๋น„์ •ํ˜•์ด๋ผ ์ค‘์š”์„ฑ ๊ธ‰์ฆ

2. NLTK
โ€ข ๊ต์œก์šฉ์œผ๋กœ ์ตœ์ ํ™”๋œ NLP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
โ€ข ํ† ํฐํ™”, ํ’ˆ์‚ฌ ํƒœ๊น…, ๊ฐœ์ฒด๋ช… ์ธ์‹ ๋“ฑ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ ์ถฉ์‹ค
โ€ข ํ•™์Šต๊ณผ ํ”„๋กœํ† ํƒ€์ดํ•‘์— ์ ํ•ฉ

3. spaCy
โ€ข ์‚ฐ์—…์šฉ ๊ณ ์„ฑ๋Šฅ NLP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
โ€ข ๋น ๋ฅธ ์†๋„์™€ ๋†’์€ ์ •ํ™•๋„
โ€ข ์‹ค์ œ ์„œ๋น„์Šค ๋ฐฐํฌ์— ์ตœ์ 

4. ์‹ค์ „ ํ”„๋กœ์ ํŠธ
โ€ข ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ โ†’ ์ „์ฒ˜๋ฆฌ โ†’ ํŠน์ง• ์ถ”์ถœ โ†’ ๋ชจ๋ธ๋ง โ†’ ํ‰๊ฐ€
โ€ข ๊ฐ์„ฑ ๋ถ„์„, ํ† ํ”ฝ ๋ชจ๋ธ๋ง, ๋ฌธ์„œ ๋ถ„๋ฅ˜ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋ฒ•
โ€ข ์‹ค๋ฌด์—์„œ๋Š” ๋„๋ฉ”์ธ ์ง€์‹๊ณผ ๊ธฐ์ˆ ์˜ ์กฐํ•ฉ์ด ํ•ต์‹ฌ

5. ๋ฏธ๋ž˜ ํŠธ๋ Œ๋“œ
โ€ข LLM(๋Œ€๊ทœ๋ชจ ์–ธ์–ด ๋ชจ๋ธ)์˜ ๋ถ€์ƒ
โ€ข ๋‹ค๊ตญ์–ด NLP ๋ฐœ์ „
โ€ข ๋„๋ฉ”์ธ ํŠนํ™” ๋ชจ๋ธ ์ฆ๊ฐ€
โ€ข ์œค๋ฆฌ์™€ ์ฑ…์ž„ ์žˆ๋Š” AI ์ค‘์š”์„ฑ ์ฆ๋Œ€

ํ…์ŠคํŠธ ๋งˆ์ด๋‹์€ ์ด์ œ ์„ ํƒ์ด ์•„๋‹ˆ๋ผ ํ•„์ˆ˜ ๊ธฐ์ˆ ์ด ๋์–ด.
๋ฐ์ดํ„ฐ ๋ถ„์„๊ฐ€, ๊ฐœ๋ฐœ์ž, ๋งˆ์ผ€ํ„ฐ, ์—ฐ๊ตฌ์ž ๋“ฑ ๋‹ค์–‘ํ•œ ๋ถ„์•ผ์—์„œ ํ™œ์šฉ๋˜๊ณ  ์žˆ๊ณ ,
์•ž์œผ๋กœ ๊ทธ ์ค‘์š”์„ฑ์€ ๋”์šฑ ์ปค์งˆ ๊ฑฐ์•ผ ๐Ÿ“ˆ

์ฒ˜์Œ์—” ์–ด๋ ต๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ, ํ•˜๋‚˜์”ฉ ์ฐจ๊ทผ์ฐจ๊ทผ ๋”ฐ๋ผํ•˜๋‹ค ๋ณด๋ฉด ์–ด๋А์ƒˆ ์ „๋ฌธ๊ฐ€๊ฐ€ ๋˜์–ด ์žˆ์„ ๊ฑฐ์ž„ ใ…Žใ…Ž

์‹œ์ž‘์ด ๋ฐ˜์ด๋ผ๊ณ  ํ–ˆ์ž–์•„?
์ง€๊ธˆ ๋ฐ”๋กœ Python ์ผœ๊ณ  NLTK๋‚˜ spaCy ์„ค์น˜ํ•ด์„œ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋ถ€ํ„ฐ ์‹คํ–‰ํ•ด๋ด.
๊ทธ๊ฒŒ ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ์ „๋ฌธ๊ฐ€๋กœ ๊ฐ€๋Š” ์ฒซ๊ฑธ์Œ์ด์•ผ ๐Ÿš€

๊ถ๊ธˆํ•œ ์  ์žˆ์œผ๋ฉด ์–ธ์ œ๋“  ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๋ฌผ์–ด๋ณด๊ณ ,
์‹ค์ „ ๊ฒฝํ—˜ ์Œ“๊ณ  ์‹ถ์œผ๋ฉด ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ํ”„๋กœ์ ํŠธ๋„ ์ฐพ์•„๋ณด๊ณ ,
๊พธ์ค€ํžˆ ํ•™์Šตํ•˜๋ฉด์„œ ํฌํŠธํด๋ฆฌ์˜ค ๋งŒ๋“ค์–ด๊ฐ€๋ฉด ๋ผ!

ํ™”์ดํŒ…! ๐Ÿ’ช๐Ÿ’ช๐Ÿ’ช

๐ŸŽ‰

ํ…์ŠคํŠธ ๋งˆ์ด๋‹์˜ ์„ธ๊ณ„์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!

์ด์ œ ๋‹น์‹ ๋„ ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์˜ ์ˆจ๊ฒจ์ง„ ๋ณด๋ฌผ์„ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ์–ด์š” โœจ

๐Ÿ“š ์ด ๊ธ€์ด ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด ์ฃผ๋ณ€ ์‚ฌ๋žŒ๋“ค๊ณผ ๊ณต์œ ํ•ด์ฃผ์„ธ์š”!
๐Ÿ’ฌ ๊ถ๊ธˆํ•œ ์ ์ด๋‚˜ ์ถ”๊ฐ€๋กœ ์•Œ๊ณ  ์‹ถ์€ ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์„ธ์š”.
๐ŸŒŸ ์—ฌ๋Ÿฌ๋ถ„์˜ ํ…์ŠคํŠธ ๋งˆ์ด๋‹ ์—ฌ์ •์„ ์‘์›ํ•ฉ๋‹ˆ๋‹ค!

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.