From 77eaae8689c7dfaa9aef4bbc696fa76655cf041f Mon Sep 17 00:00:00 2001 From: ChunHajin Date: Tue, 26 May 2026 18:38:30 +0900 Subject: [PATCH] =?UTF-8?q?Add=20Week12=20=EC=98=88=EC=8A=B5=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\353\205\220\354\240\225\353\246\254.pdf" | Bin 0 -> 70950 bytes "Euron_Week12_\354\230\210\354\212\265.ipynb" | 1977 +++++++++++++++++ 2 files changed, 1977 insertions(+) create mode 100644 "Euron_Week12_\352\260\234\353\205\220\354\240\225\353\246\254.pdf" create mode 100644 "Euron_Week12_\354\230\210\354\212\265.ipynb" diff --git "a/Euron_Week12_\352\260\234\353\205\220\354\240\225\353\246\254.pdf" "b/Euron_Week12_\352\260\234\353\205\220\354\240\225\353\246\254.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..5a92ee348fed6128b0aab166bb0892180556e507 GIT binary patch literal 70950 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 literal 0 HcmV?d00001 diff --git "a/Euron_Week12_\354\230\210\354\212\265.ipynb" "b/Euron_Week12_\354\230\210\354\212\265.ipynb" new file mode 100644 index 0000000..6a2f524 --- /dev/null +++ "b/Euron_Week12_\354\230\210\354\212\265.ipynb" @@ -0,0 +1,1977 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "## **ํ…์ŠคํŠธ ๋ถ„์„**" + ], + "metadata": { + "id": "8pUTwBbdfvt3" + } + }, + { + "cell_type": "markdown", + "source": [ + "### 1. ํ…์ŠคํŠธ ์ •๊ทœํ™”" + ], + "metadata": { + "id": "RMzxwhqrTIr7" + } + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mQ0yjKhCSsTi", + "outputId": "7bcd1a2e-759e-4ddd-f226-f1892852ad1e" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "[nltk_data] Downloading package punkt to /root/nltk_data...\n", + "[nltk_data] Unzipping tokenizers/punkt.zip.\n", + "[nltk_data] Downloading package punkt_tab to /root/nltk_data...\n", + "[nltk_data] Unzipping tokenizers/punkt_tab.zip.\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + " 3\n", + "['The Matrix is everywhere its all around us, here even in this room.', 'You can see it out your window or on your television.', 'You feel it when you go to work, or go to church or pay your taxes.']\n" + ] + } + ], + "source": [ + "# 1. ํ…์ŠคํŠธ ์ƒ˜ํ”Œ(Text Sample) ๋กœ๋“œ ๋ฐ ๋ฌธ์žฅ ํ† ํฐํ™”(Sentence Tokenization)\n", + "# ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ NLTK๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ…์ŠคํŠธ๋ฅผ ๋ฌธ์žฅ ๋‹จ์œ„๋กœ ๋ถ„ํ• ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import nltk\n", + "from nltk import sent_tokenize\n", + "\n", + "# ํ† ํฐํ™”์— ํ•„์š”ํ•œ ์ž์›(Resource) ๋‹ค์šด๋กœ๋“œ\n", + "nltk.download('punkt')\n", + "nltk.download('punkt_tab')\n", + "\n", + "# ๋ถ„์„ํ•  ํ…์ŠคํŠธ ์ƒ˜ํ”Œ ์ •์˜\n", + "text_sample = 'The Matrix is everywhere its all around us, here even in this room. \\\n", + " You can see it out your window or on your television. \\\n", + " You feel it when you go to work, or go to church or pay your taxes.'\n", + "\n", + "# NLTK์˜ sent_tokenize๋ฅผ ์ด์šฉํ•ด ๋ฌธ์žฅ ํ† ํฐํ™” ์ˆ˜ํ–‰\n", + "sentences = sent_tokenize(text=text_sample)\n", + "\n", + "# ์ƒ์„ฑ๋œ ํ† ํฐ ๋ฆฌ์ŠคํŠธ์˜ ์ž๋ฃŒํ˜•(Type) ๋ฐ ๋ฌธ์žฅ ๊ฐœ์ˆ˜(Length) ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print(type(sentences), len(sentences))\n", + "\n", + "# ๋ถ„ํ• ๋œ ๋ฌธ์žฅ ๋ฐ์ดํ„ฐ ์ „์ฒด ์ถœ๋ ฅ\n", + "print(sentences)" + ] + }, + { + "cell_type": "code", + "source": [ + "# 2. ๋ฌธ์žฅ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ๋‹จ์–ด ํ† ํฐํ™”(Word Tokenization)\n", + "# NLTK ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹จ์ผ ๋ฌธ์žฅ์„ ๋‹จ์–ด(Word) ๋‹จ์œ„๋กœ ๋ถ„ํ• ํ•˜๊ณ  ๊ตฌ์กฐ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from nltk import word_tokenize\n", + "\n", + "# ๋ถ„์„ํ•  ๋ฌธ์žฅ ์ƒ˜ํ”Œ ์ •์˜\n", + "sentence = \"The Matrix is everywhere its all around us, here even in this room.\"\n", + "\n", + "# NLTK์˜ word_tokenize๋ฅผ ์ด์šฉํ•ด ๋‹จ์–ด ํ† ํฐํ™” ์ˆ˜ํ–‰\n", + "words = word_tokenize(sentence)\n", + "\n", + "# ์ƒ์„ฑ๋œ ํ† ํฐ ๋ฆฌ์ŠคํŠธ์˜ ์ž๋ฃŒํ˜•(Type) ๋ฐ ๋‹จ์–ด ๊ฐœ์ˆ˜(Length) ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print(type(words), len(words))\n", + "\n", + "# ๋ถ„ํ• ๋œ ๋‹จ์–ด ๋ฐ์ดํ„ฐ ์ „์ฒด ์ถœ๋ ฅ\n", + "print(words)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "QQJhNXavTUbU", + "outputId": "857e6659-6e7a-4746-e654-d5c0603de84a" + }, + "execution_count": 2, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + " 15\n", + "['The', 'Matrix', 'is', 'everywhere', 'its', 'all', 'around', 'us', ',', 'here', 'even', 'in', 'this', 'room', '.']\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 3. ๋ฌธ์„œ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ์ข…ํ•ฉ ํ† ํฐํ™”(Text Tokenization) ํ•จ์ˆ˜ ๊ตฌํ˜„\n", + "# ํ…์ŠคํŠธ ์ƒ˜ํ”Œ์„ ๋ฌธ์žฅ๋ณ„๋กœ ๋จผ์ € ๋ถ„ํ• ํ•œ ํ›„, ๊ฐ ๋ฌธ์žฅ์„ ๋‹ค์‹œ ๋‹จ์–ด ๋‹จ์œ„๋กœ ํ† ํฐํ™”ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ณ  ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from nltk import word_tokenize, sent_tokenize\n", + "\n", + "# ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฌธ์žฅ์œผ๋กœ ๋œ ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌธ์žฅ๋ณ„๋กœ ๋‹จ์–ด ํ† ํฐํ™”ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ•จ์ˆ˜ ์ƒ์„ฑ\n", + "def tokenize_text(text):\n", + "\n", + " # ์ž…๋ ฅ๋œ ํ…์ŠคํŠธ๋ฅผ ๋ฌธ์žฅ๋ณ„๋กœ ๋ถ„๋ฆฌ(Sentence Tokenization)\n", + " sentences = sent_tokenize(text)\n", + "\n", + " # ๋ถ„๋ฆฌ๋œ ๊ฐ ๋ฌธ์žฅ๋ณ„๋กœ ๋‹จ์–ด ํ† ํฐํ™”(Word Tokenization) ์ˆ˜ํ–‰ ํ›„ ๋ฆฌ์ŠคํŠธ๋กœ ์ €์žฅ\n", + " word_tokens = [word_tokenize(sentence) for sentence in sentences]\n", + " return word_tokens\n", + "\n", + "# ์—ฌ๋Ÿฌ ๋ฌธ์žฅ์— ๋Œ€ํ•ด ๋ฌธ์žฅ๋ณ„ ๋‹จ์–ด ํ† ํฐํ™” ์ˆ˜ํ–‰\n", + "word_tokens = tokenize_text(text_sample)\n", + "\n", + "# ์ƒ์„ฑ๋œ 2์ฐจ์› ๋ฆฌ์ŠคํŠธ์˜ ์ž๋ฃŒํ˜•(Type) ๋ฐ ๋ฌธ์žฅ ๊ฐœ์ˆ˜(Length) ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print(type(word_tokens), len(word_tokens))\n", + "\n", + "# ๋ฌธ์žฅ๋ณ„๋กœ ๋ถ„ํ• ๋œ ๋‹จ์–ด ํ† ํฐ ๋ฐ์ดํ„ฐ ์ „์ฒด ์ถœ๋ ฅ (2์ฐจ์› ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ)\n", + "print(word_tokens)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "RVxijaXUUAfM", + "outputId": "c47e0fb3-9940-4b81-9c59-fe224c89d11b" + }, + "execution_count": 3, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + " 3\n", + "[['The', 'Matrix', 'is', 'everywhere', 'its', 'all', 'around', 'us', ',', 'here', 'even', 'in', 'this', 'room', '.'], ['You', 'can', 'see', 'it', 'out', 'your', 'window', 'or', 'on', 'your', 'television', '.'], ['You', 'feel', 'it', 'when', 'you', 'go', 'to', 'work', ',', 'or', 'go', 'to', 'church', 'or', 'pay', 'your', 'taxes', '.']]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 4. NLTK ๋ถˆ์šฉ์–ด(Stopwords) ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋‹ค์šด๋กœ๋“œ\n", + "# ํ…์ŠคํŠธ ์ „์ฒ˜๋ฆฌ ๊ณผ์ •์—์„œ ์˜๋ฏธ๊ฐ€ ์—†๋Š” ๋‹จ์–ด๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด NLTK๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ถˆ์šฉ์–ด ์‚ฌ์ „์„ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.\n", + "\n", + "import nltk\n", + "\n", + "# ์˜์–ด, ํ•œ๊ตญ์–ด ๋“ฑ ๋‹ค์–‘ํ•œ ์–ธ์–ด์˜ ๋ถˆ์šฉ์–ด ์‚ฌ์ „ ์ž์›(Resource) ๋‹ค์šด๋กœ๋“œ\n", + "nltk.download('stopwords')" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "fW_ILC9FURN7", + "outputId": "e1fb6732-74f4-4a58-f965-112649562694" + }, + "execution_count": 5, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "[nltk_data] Downloading package stopwords to /root/nltk_data...\n", + "[nltk_data] Unzipping corpora/stopwords.zip.\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "True" + ] + }, + "metadata": {}, + "execution_count": 5 + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 5. ์˜์–ด ๋ถˆ์šฉ์–ด(Stopwords) ๋ฐ์ดํ„ฐ ์„ธํŠธ ๊ตฌ์กฐ ๋ฐ ์ƒ˜ํ”Œ ํ™•์ธ\n", + "# NLTK์— ๋‚ด์žฅ๋œ ์˜์–ด ๋ถˆ์šฉ์–ด์˜ ์ „์ฒด ๊ฐœ์ˆ˜๋ฅผ ํ™•์ธํ•˜๊ณ , ์ƒ์œ„ 20๊ฐœ ์ƒ˜ํ”Œ์„ ์ถœ๋ ฅํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์•…ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "# ๋“ฑ๋ก๋œ ์˜์–ด ๋ถˆ์šฉ์–ด(Stopwords)์˜ ์ „์ฒด ๊ฐœ์ˆ˜(Length) ์ถœ๋ ฅ\n", + "print('์˜์–ด stop words ๊ฐœ์ˆ˜:', len(nltk.corpus.stopwords.words('english')))\n", + "\n", + "# ์˜์–ด ๋ถˆ์šฉ์–ด ๋ชฉ๋ก ์ค‘ ์ƒ์œ„ 20๊ฐœ ๋‹จ์–ด(Row)๋ฅผ ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print(nltk.corpus.stopwords.words('english')[:20])" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-w6haR3ZUTO2", + "outputId": "5a25f07e-28f2-4e6e-e683-2d38faba9a26" + }, + "execution_count": 6, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "์˜์–ด stop words ๊ฐœ์ˆ˜: 198\n", + "['a', 'about', 'above', 'after', 'again', 'against', 'ain', 'all', 'am', 'an', 'and', 'any', 'are', 'aren', \"aren't\", 'as', 'at', 'be', 'because', 'been']\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 6. ๋ถˆ์šฉ์–ด(Stopwords) ์ œ๊ฑฐ๋ฅผ ํ†ตํ•œ ๋‹จ์–ด ํ•„ํ„ฐ๋ง ์ „์ฒ˜๋ฆฌ\n", + "# ์•ž์„œ ์ƒ์„ฑํ•œ ๋ฌธ์žฅ๋ณ„ ๋‹จ์–ด ํ† ํฐ ๋ฆฌ์ŠคํŠธ์—์„œ ์˜์–ด ๋ถˆ์šฉ์–ด๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์‹ค์งˆ์ ์ธ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง„ ๋‹จ์–ด๋งŒ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import nltk\n", + "\n", + "# NLTK ์˜์–ด ๋ถˆ์šฉ์–ด(Stopwords) ๋ชฉ๋ก ๋กœ๋“œ\n", + "stopwords = nltk.corpus.stopwords.words('english')\n", + "all_tokens = []\n", + "\n", + "# 3๊ฐœ์˜ ๋ฌธ์žฅ๋ณ„๋กœ ๋ถ„ํ• ๋œ word_tokens ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ๋ถˆ์šฉ์–ด ์ œ๊ฑฐ ๋ฐ˜๋ณต๋ฌธ ์ˆ˜ํ–‰\n", + "for sentence in word_tokens:\n", + " filtered_words = []\n", + "\n", + " # ๊ฐœ๋ณ„ ๋ฌธ์žฅ ๋‚ด์˜ ํ† ํฐํ™”๋œ ๋‹จ์–ด ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒ\n", + " for word in sentence:\n", + " # ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„์„ ์—†์• ๊ธฐ ์œ„ํ•ด ์†Œ๋ฌธ์ž๋กœ ๋ชจ๋‘ ๋ณ€ํ™˜(Lowercasing)\n", + " word = word.lower()\n", + "\n", + " # ํ† ํฐํ™”๋œ ๊ฐœ๋ณ„ ๋‹จ์–ด๊ฐ€ ์˜์–ด ๋ถˆ์šฉ์–ด ๋ชฉ๋ก์— ํฌํ•จ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ถ”์ถœ\n", + " if word not in stopwords:\n", + " filtered_words.append(word)\n", + "\n", + " # ๋ถˆ์šฉ์–ด๊ฐ€ ์ œ๊ฑฐ๋œ ๋‹จ์–ด ๋ฆฌ์ŠคํŠธ๋ฅผ ์ตœ์ข… ํ† ํฐ ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€\n", + " all_tokens.append(filtered_words)\n", + "\n", + "# ๋ถˆ์šฉ์–ด๊ฐ€ ์ •์ œ๋œ ๋ฌธ์žฅ๋ณ„ ๋‹จ์–ด ํ† ํฐ ๋ฐ์ดํ„ฐ ์ „์ฒด ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print(all_tokens)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "dtZJy7u7UZ9o", + "outputId": "6fd1bc19-2bce-43ae-f90f-e02e6c89fc75" + }, + "execution_count": 7, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[['matrix', 'everywhere', 'around', 'us', ',', 'even', 'room', '.'], ['see', 'window', 'television', '.'], ['feel', 'go', 'work', ',', 'go', 'church', 'pay', 'taxes', '.']]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 7. ์–ด๊ฐ„ ์ถ”์ถœ(Stemming) ๋ชจ๋ธ์„ ํ™œ์šฉํ•œ ๋‹จ์–ด ์›ํ˜• ์ถ”์ถœ\n", + "# LancasterStemmer๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๋กœ ๋ณ€ํ˜•๋œ ๋‹จ์–ด๋“ค์˜ ์–ด๊ฐ„(Stem)์„ ์ถ”์ถœํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from nltk.stem import LancasterStemmer\n", + "\n", + "# LancasterStemmer ๊ฐ์ฒด ์ƒ์„ฑ\n", + "stemmer = LancasterStemmer()\n", + "\n", + "# 'work' ๊ด€๋ จ ๋™์‚ฌ ๋ณ€ํ˜•๋“ค์˜ ์–ด๊ฐ„ ์ถ”์ถœ ๊ฒฐ๊ณผ ์ถœ๋ ฅ\n", + "print(stemmer.stem('working'), stemmer.stem('works'), stemmer.stem('worked'))\n", + "\n", + "# 'amuse' ๊ด€๋ จ ๋™์‚ฌ ๋ณ€ํ˜•๋“ค์˜ ์–ด๊ฐ„ ์ถ”์ถœ ๊ฒฐ๊ณผ ์ถœ๋ ฅ\n", + "print(stemmer.stem('amusing'), stemmer.stem('amuses'), stemmer.stem('amused'))\n", + "\n", + "# 'happy' ๊ด€๋ จ ํ˜•์šฉ์‚ฌ ๋น„๊ต๊ธ‰/์ตœ์ƒ๊ธ‰ ๋ณ€ํ˜•๋“ค์˜ ์–ด๊ฐ„ ์ถ”์ถœ ๊ฒฐ๊ณผ ์ถœ๋ ฅ\n", + "print(stemmer.stem('happier'), stemmer.stem('happiest'))\n", + "\n", + "# 'fancy' ๊ด€๋ จ ํ˜•์šฉ์‚ฌ ๋น„๊ต๊ธ‰/์ตœ์ƒ๊ธ‰ ๋ณ€ํ˜•๋“ค์˜ ์–ด๊ฐ„ ์ถ”์ถœ ๊ฒฐ๊ณผ ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print(stemmer.stem('fancier'), stemmer.stem('fanciest'))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8ppfMZmoU1SC", + "outputId": "df1c731e-5772-4a2b-e442-6d7088df66ea" + }, + "execution_count": 8, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "work work work\n", + "amus amus amus\n", + "happy happiest\n", + "fant fanciest\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 8. ํ‘œ์ œ์–ด ์ถ”์ถœ(Lemmatization) ๋ชจ๋ธ์„ ํ™œ์šฉํ•œ ๋‹จ์–ด ์›ํ˜• ๋ณต์›\n", + "# WordNetLemmatizer๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹จ์–ด์˜ ํ’ˆ์‚ฌ(POS) ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ •ํ™•ํ•œ ํ‘œ์ œ์–ด(Lemma)๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import nltk\n", + "from nltk.stem import WordNetLemmatizer\n", + "\n", + "# ํ‘œ์ œ์–ด ์ถ”์ถœ์— ํ•„์š”ํ•œ WordNet ๋ฐ์ดํ„ฐ ์„ธํŠธ(Resource) ๋‹ค์šด๋กœ๋“œ\n", + "nltk.download('wordnet')\n", + "\n", + "# WordNetLemmatizer ๊ฐ์ฒด ์ƒ์„ฑ\n", + "lemma = WordNetLemmatizer()\n", + "\n", + "# ๋™์‚ฌ('v') ํ’ˆ์‚ฌ ์ •๋ณด๋ฅผ ์ง€์ •ํ•˜์—ฌ 'amuse' ๊ด€๋ จ ๋‹จ์–ด๋“ค์˜ ํ‘œ์ œ์–ด ์ถ”์ถœ ๊ฒฐ๊ณผ ์ถœ๋ ฅ\n", + "print(lemma.lemmatize('amusing', 'v'), lemma.lemmatize('amuses', 'v'), lemma.lemmatize('amused', 'v'))\n", + "\n", + "# ํ˜•์šฉ์‚ฌ('a') ํ’ˆ์‚ฌ ์ •๋ณด๋ฅผ ์ง€์ •ํ•˜์—ฌ 'happy' ๊ด€๋ จ ๋‹จ์–ด๋“ค์˜ ํ‘œ์ œ์–ด ์ถ”์ถœ ๊ฒฐ๊ณผ ์ถœ๋ ฅ\n", + "print(lemma.lemmatize('happier', 'a'), lemma.lemmatize('happiest', 'a'))\n", + "\n", + "# ํ˜•์šฉ์‚ฌ('a') ํ’ˆ์‚ฌ ์ •๋ณด๋ฅผ ์ง€์ •ํ•˜์—ฌ 'fancy' ๊ด€๋ จ ๋‹จ์–ด๋“ค์˜ ํ‘œ์ œ์–ด ์ถ”์ถœ ๊ฒฐ๊ณผ ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print(lemma.lemmatize('fancier', 'a'), lemma.lemmatize('fanciest', 'a'))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "21ukCWsNU_PY", + "outputId": "6090a79d-d54e-4a42-de73-94e7b65956bd" + }, + "execution_count": 9, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "[nltk_data] Downloading package wordnet to /root/nltk_data...\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "amuse amuse amuse\n", + "happy happy\n", + "fancy fancy\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 2. Bag of Words - BOW" + ], + "metadata": { + "id": "EVFM5d11VWRL" + } + }, + { + "cell_type": "code", + "source": [ + "# 1. ๋„˜ํŒŒ์ด(NumPy) ๊ธฐ๋ฐ˜ ๋ฐ€์ง‘ ํ–‰๋ ฌ(Dense Matrix) ์ƒ์„ฑ ๋ฐ ๋ฐ์ดํ„ฐ ์ •์˜\n", + "# ํฌ์†Œ ํ–‰๋ ฌ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ „, ๋‹ค์ฐจ์› ๋ฐฐ์—ด์„ ํ™œ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ ๋ฐ€์ง‘ ํ–‰๋ ฌ์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import numpy as np\n", + "\n", + "# 2ํ–‰ 3์—ด ๊ตฌ์กฐ์˜ 2์ฐจ์› ๋ฐ€์ง‘ ํ–‰๋ ฌ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ\n", + "dense = np.array([[3, 0, 1], [0, 2, 0]])" + ], + "metadata": { + "id": "1n-6Scc-VUe8" + }, + "execution_count": 10, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# 2. COO(Coordinate) ํ˜•์‹์„ ํ™œ์šฉํ•œ ํฌ์†Œ ํ–‰๋ ฌ(Sparse Matrix) ์ƒ์„ฑ\n", + "# SciPy ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ coo_matrix๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ 0์ด ์•„๋‹Œ ๋ฐ์ดํ„ฐ์™€ ํ•ด๋‹น ์œ„์น˜(ํ–‰, ์—ด) ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํฌ์†Œ ํ–‰๋ ฌ์„ ๊ตฌ์กฐํ™”ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from scipy import sparse\n", + "\n", + "# 0์ด ์•„๋‹Œ ์‹ค์ œ ๋ฐ์ดํ„ฐ ๊ฐ’(Data) ๋ฐฐ์—ด ์ƒ์„ฑ\n", + "data = np.array([3, 1, 2])\n", + "\n", + "# ๋ฐ์ดํ„ฐ๊ฐ€ ์œ„์น˜ํ•œ ํ–‰ ์ธ๋ฑ์Šค(Row Position)์™€ ์—ด ์ธ๋ฑ์Šค(Column Position) ๋ฐฐ์—ด์„ ๊ฐ๊ฐ ์ƒ์„ฑ\n", + "row_pos = np.array([0, 0, 1])\n", + "col_pos = np.array([0, 2, 1])\n", + "\n", + "# SciPy์˜ coo_matrix๋ฅผ ์ด์šฉํ•˜์—ฌ COO ํ˜•์‹์˜ ํฌ์†Œ ํ–‰๋ ฌ ๋ณ€ํ™˜ ์ˆ˜ํ–‰\n", + "sparse_coo = sparse.coo_matrix((data, (row_pos, col_pos)))" + ], + "metadata": { + "id": "BYPUYKoJVg57" + }, + "execution_count": 11, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# 3. ํฌ์†Œ ํ–‰๋ ฌ(Sparse Matrix)์˜ ๋ฐ€์ง‘ ํ–‰๋ ฌ(Dense Matrix) ๋ณ€ํ™˜ ๋ฐ ๊ตฌ์กฐ ํ™•์ธ\n", + "# COO ํ˜•์‹์œผ๋กœ ์••์ถ•๋œ ํฌ์†Œ ํ–‰๋ ฌ์„ toarray() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋‹ค์‹œ ์›๋ž˜์˜ ๋„˜ํŒŒ์ด ๋ฐฐ์—ด๋กœ ๋ณต์›ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "# COO ํ˜•์‹์˜ ํฌ์†Œ ํ–‰๋ ฌ์„ ์ผ๋ฐ˜ ๋‹ค์ฐจ์› ๋„˜ํŒŒ์ด ๋ฐฐ์—ด(Array) ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ถœ๋ ฅ\n", + "sparse_coo.toarray()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "4A469JXuVmU8", + "outputId": "5e25a6fc-1246-41d0-9947-95834c444b06" + }, + "execution_count": 12, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([[3, 0, 1],\n", + " [0, 2, 0]])" + ] + }, + "metadata": {}, + "execution_count": 12 + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 4. COO ๋ฐ CSR ํ˜•์‹์„ ํ™œ์šฉํ•œ ํฌ์†Œ ํ–‰๋ ฌ(Sparse Matrix) ๋ณ€ํ™˜ ๋ฐ ๊ฒ€์ฆ\n", + "# 6x6 ๋ฐ€์ง‘ ํ–‰๋ ฌ์„ COO ํ˜•์‹๊ณผ ๊ณ ์œ  ์ธ๋ฑ์Šค ๋ฐฐ์—ด์„ ํ™œ์šฉํ•œ CSR ํ˜•์‹์œผ๋กœ ๊ฐ๊ฐ ๋ณ€ํ™˜ํ•˜๊ณ , ์›๋ž˜ ๋ฐฐ์—ด๋กœ ๋ณต์›ํ•˜์—ฌ ์ •ํ™•์„ฑ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import numpy as np\n", + "from scipy import sparse\n", + "\n", + "# 6ํ–‰ 6์—ด ๊ตฌ์กฐ์˜ 2์ฐจ์› ๋ฐ€์ง‘ ํ–‰๋ ฌ(Dense Matrix) ๋ฐ์ดํ„ฐ ์ •์˜\n", + "dense2 = np.array([[0, 0, 1, 0, 0, 5],\n", + " [1, 4, 0, 3, 2, 5],\n", + " [0, 6, 0, 3, 0, 0],\n", + " [2, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 7, 0, 8],\n", + " [1, 0, 0, 0, 0, 0]])\n", + "\n", + "# ํ–‰๋ ฌ ๋‚ด์—์„œ 0์ด ์•„๋‹Œ ์‹ค์ œ ๋ฐ์ดํ„ฐ ๊ฐ’(Data) ๋ฐฐ์—ด ์ƒ์„ฑ\n", + "data2 = np.array([1, 5, 1, 4, 3, 2, 5, 6, 3, 2, 7, 8, 1])\n", + "\n", + "# ๋ฐ์ดํ„ฐ๊ฐ€ ์œ„์น˜ํ•œ ํ–‰ ์ธ๋ฑ์Šค(Row Position)์™€ ์—ด ์ธ๋ฑ์Šค(Column Position) ๋ฐฐ์—ด์„ ๊ฐ๊ฐ ์ƒ์„ฑ\n", + "row_pos = np.array([0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5])\n", + "coI_pos = np.array([2, 5, 0, 1, 3, 4, 5, 1, 3, 0, 3, 5, 0])\n", + "\n", + "# SciPy์˜ coo_matrix๋ฅผ ์ด์šฉํ•˜์—ฌ COO ํ˜•์‹์˜ ํฌ์†Œ ํ–‰๋ ฌ ๋ณ€ํ™˜ ์ˆ˜ํ–‰\n", + "sparse_coo = sparse.coo_matrix((data2, (row_pos, coI_pos)))\n", + "\n", + "# ํ–‰ ์œ„์น˜ ๋ฐฐ์—ด ๋‚ด ๊ณ ์œ ํ•œ ๊ฐ’์˜ ์‹œ์ž‘ ์œ„์น˜ ์ธ๋ฑ์Šค(Row Position Index) ๋ฐฐ์—ด ์ƒ์„ฑ (CSR ์••์ถ•์šฉ)\n", + "row_pos_ind = np.array([0, 2, 7, 9, 10, 12, 13])\n", + "\n", + "# SciPy์˜ csr_matrix๋ฅผ ์ด์šฉํ•˜์—ฌ CSR ํ˜•์‹์˜ ํฌ์†Œ ํ–‰๋ ฌ ๋ณ€ํ™˜ ์ˆ˜ํ–‰\n", + "sparse_csr = sparse.csr_matrix((data2, coI_pos, row_pos_ind))\n", + "\n", + "# COO ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜๋œ ํฌ์†Œ ํ–‰๋ ฌ์„ ๋‹ค์‹œ ๋ฐ€์ง‘ ํ–‰๋ ฌ(Dense Matrix)๋กœ ๋ณต์›ํ•˜์—ฌ ๊ฒฐ๊ณผ ์ถœ๋ ฅ\n", + "print('COO ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ œ๋Œ€๋กœ ๋˜์—ˆ๋Š”์ง€ ๋‹ค์‹œ Dense๋กœ ์ถœ๋ ฅ ํ™•์ธ')\n", + "print(sparse_coo.toarray())\n", + "\n", + "# CSR ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜๋œ ํฌ์†Œ ํ–‰๋ ฌ์„ ๋‹ค์‹œ ๋ฐ€์ง‘ ํ–‰๋ ฌ(Dense Matrix)๋กœ ๋ณต์›ํ•˜์—ฌ ๊ฒฐ๊ณผ ์ถœ๋ ฅ ๋ฐ ๊ตฌ์กฐ ํ™•์ธ\n", + "print('CSR ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ œ๋Œ€๋กœ ๋˜์—ˆ๋Š”์ง€ ๋‹ค์‹œ Dense๋กœ ์ถœ๋ ฅ ํ™•์ธ')\n", + "print(sparse_csr.toarray())" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "69hfeAnhV9YS", + "outputId": "bc83e992-e602-4813-bcaa-a154e7867b3e" + }, + "execution_count": 13, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "COO ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ œ๋Œ€๋กœ ๋˜์—ˆ๋Š”์ง€ ๋‹ค์‹œ Dense๋กœ ์ถœ๋ ฅ ํ™•์ธ\n", + "[[0 0 1 0 0 5]\n", + " [1 4 0 3 2 5]\n", + " [0 6 0 3 0 0]\n", + " [2 0 0 0 0 0]\n", + " [0 0 0 7 0 8]\n", + " [1 0 0 0 0 0]]\n", + "CSR ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ œ๋Œ€๋กœ ๋˜์—ˆ๋Š”์ง€ ๋‹ค์‹œ Dense๋กœ ์ถœ๋ ฅ ํ™•์ธ\n", + "[[0 0 1 0 0 5]\n", + " [1 4 0 3 2 5]\n", + " [0 6 0 3 0 0]\n", + " [2 0 0 0 0 0]\n", + " [0 0 0 7 0 8]\n", + " [1 0 0 0 0 0]]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 5. SciPy ํ•จ์ˆ˜ ๊ธฐ๋ฐ˜ COO ๋ฐ CSR ํฌ์†Œ ํ–‰๋ ฌ(Sparse Matrix) ์ž๋™ ๋ณ€ํ™˜\n", + "# ์œ„์น˜ ๋ฐฐ์—ด์„ ์ง์ ‘ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ , SciPy ๋‚ด์žฅ ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฐ€์ง‘ ํ–‰๋ ฌ์„ COO์™€ CSR ํ˜•์‹์œผ๋กœ ํšจ์œจ์ ์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import numpy as np\n", + "from scipy import sparse\n", + "\n", + "# 6ํ–‰ 6์—ด ๊ตฌ์กฐ์˜ 2์ฐจ์› ๋ฐ€์ง‘ ํ–‰๋ ฌ(Dense Matrix) ๋ฐ์ดํ„ฐ ์ •์˜\n", + "dense3 = np.array([[0, 0, 1, 0, 0, 5],\n", + " [1, 4, 0, 3, 2, 5],\n", + " [0, 6, 0, 3, 0, 0],\n", + " [2, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 7, 0, 8],\n", + " [1, 0, 0, 0, 0, 0]])\n", + "\n", + "# SciPy์˜ coo_matrix ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋ฐ€์ง‘ ํ–‰๋ ฌ์„ COO ํ˜•์‹ ํฌ์†Œ ํ–‰๋ ฌ๋กœ ์ž๋™ ๋ณ€ํ™˜\n", + "coo = sparse.coo_matrix(dense3)\n", + "\n", + "# SciPy์˜ csr_matrix ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋ฐ€์ง‘ ํ–‰๋ ฌ์„ CSR ํ˜•์‹ ํฌ์†Œ ํ–‰๋ ฌ๋กœ ์ž๋™ ๋ณ€ํ™˜ํ•˜์—ฌ ๊ตฌ์กฐํ™”\n", + "csr = sparse.csr_matrix(dense3)" + ], + "metadata": { + "id": "_P4y5zPFWBdj" + }, + "execution_count": 14, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "### 3. ๊ฐ์„ฑ ๋ถ„์„" + ], + "metadata": { + "id": "svu6eh11Xhyu" + } + }, + { + "cell_type": "code", + "source": [ + "# 1. ๊ฐ์„ฑ ๋ถ„์„(Sentiment Analysis) ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋กœ๋“œ ๋ฐ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ๋ณ€ํ™˜\n", + "# ์ง€๋„ํ•™์Šต ๊ธฐ๋ฐ˜์˜ ๊ฐ์„ฑ ๋ถ„์„ ๋ชจ๋ธ ํ•™์Šต์„ ์œ„ํ•ด ํƒญ(\\t)์œผ๋กœ ๊ตฌ๋ถ„๋œ ์˜ํ™” ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ๊ตฌ์กฐ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import pandas as pd\n", + "\n", + "# ์˜ํ™” ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ ์„ธํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ (TSV ํŒŒ์ผ ๋กœ๋“œ)\n", + "review_df = pd.read_csv('/content/labeledTrainData.tsv', header=0, sep='\\t', quoting=3)\n", + "\n", + "# ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„(DataFrame)์˜ ์ƒ์œ„ 3๊ฐœ ํ–‰(Row) ์ถœ๋ ฅํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ํ™•์ธ\n", + "review_df.head(3)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 143 + }, + "id": "DPGBkDokXRWj", + "outputId": "fb4aa88b-dbd1-4a7c-8a24-293ce0009919" + }, + "execution_count": 16, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " id sentiment review\n", + "0 \"5814_8\" 1 \"With all this stuff going down at the moment ...\n", + "1 \"2381_9\" 1 \"\\\"The Classic War of the Worlds\\\" by Timothy ...\n", + "2 \"7759_3\" 0 \"The film starts with a manager (Nicholas Bell..." + ], + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idsentimentreview
0\"5814_8\"1\"With all this stuff going down at the moment ...
1\"2381_9\"1\"\\\"The Classic War of the Worlds\\\" by Timothy ...
2\"7759_3\"0\"The film starts with a manager (Nicholas Bell...
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + "
\n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "review_df", + "summary": "{\n \"name\": \"review_df\",\n \"rows\": 13923,\n \"fields\": [\n {\n \"column\": \"id\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 13923,\n \"samples\": [\n \"\\\"3552_2\\\"\",\n \"\\\"10354_9\\\"\",\n \"\\\"7326_10\\\"\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"sentiment\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0,\n \"min\": 0,\n \"max\": 1,\n \"num_unique_values\": 2,\n \"samples\": [\n 0,\n 1\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"review\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 13884,\n \"samples\": [\n \"\\\"Well, What can I say, other than these people are Super in every way. I quite like Sharon Mcreedy, I enjoy this pure Nostalgic Series And I have the boxed set of 9 discs 30 episodes, I did not realise that they had made so many, I also think that it is a great shame, that they have not made any more. I wish that I got given these powers, Imagine me, being knocked off my cycle, somewhere and being knocked out cold, then waking up in a special hospital. Later on, I discover that my body has been enhanced. Just like Richard Barrat. These stories are 50 Minutes of pure action and suspense all the way, You cannot fight these 3 people, as they would defeat you in all forms of weaponry. The music is well written, and to me, puts a wonderful picture of 3 super beings in my mind, The sort of powers that the champions have are the same as our domestic dog or cats, Improved sight, Improved hearing and touch. and the strength of 10 men for Richard and Craig and the strength of 3 women for Sharon. Who I thought was beautiful and intelligent. When I was a boy, I had a huge crush on her!!!! Now I can see why, on my DVD set. The box is very nice and it comes with a free booklet all about the series. I also thought that Trymane was a good boss, firm but he got things done!\\\"\",\n \"\\\"The \\\\\\\"Trivia\\\\\\\" page on IMDb claims the filmmakers protested because this film was re-cut by the studio to \\\\\\\"simplify the plot\\\\\\\". If so, that effort was a total failure, as this is one of the most incoherent narratives I've ever seen in a film -- I'd hate to have seen it before the plot was \\\\\\\"simplified.\\\\\\\"

It's sad to see Warren with so little character to go on that even he can't do anything with the inept material. It's interesting to see Caron in '70s mode instead of her Hollywood-era glamour garb and persona, but it's sad to see her haplessly wander through this doing-a- favor-to-her-producer-husband dreck. She would actually later hook up with and marry the director, instead -- who, you'll note, never directed anything again, but did strictly 1st or 2nd A.D. work in TV from here on out. That oughta tell you enough right there.

I call this \\\\\\\"interesting\\\\\\\" because I have an automatic fondness for American films of this period, and this role does add perspective to Oates' otherwise fantastic 1971 output (Two- Lane Blacktop, The Hired Hand). But the \\\\\\\"1940s detective as fish-out-of-water in 1970s L.A.\\\\\\\" theme, which is the only thing the movie really has to say, is sold in way too heavy- handed a manner. A similar theme would be far more effectively handled two years later in Altman's The Long Goodbye. And as far as Oates playing a hard-bitten guy on a doomed errand, three years on, he would give his definitive performance in Bring Me the Head of Alfredo Garcia. If you haven't seen those, don't waste your time with this!\\\"\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 16 + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 2. ๊ฐœ๋ณ„ ๋ฆฌ๋ทฐ ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ ์ถ”์ถœ ๋ฐ ์›๋ฌธ ํ™•์ธ\n", + "# ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์˜ 'review' ์ปฌ๋Ÿผ์—์„œ ์ฒซ ๋ฒˆ์งธ ์ธ๋ฑ์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์„ ํƒํ•˜์—ฌ ๋ถ„์„ ๋Œ€์ƒ ํ…์ŠคํŠธ์˜ ํ˜•ํƒœ๋ฅผ ํŒŒ์•…ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "# ์ฒซ ๋ฒˆ์งธ ํ–‰(Row)์˜ ์˜ํ™” ๋ฆฌ๋ทฐ ํ…์ŠคํŠธ(Text) ๋ฐ์ดํ„ฐ๋ฅผ ์„ ํƒํ•˜์—ฌ ์ฝ˜์†”์— ์ถœ๋ ฅ ๋ฐ ํ™•์ธ\n", + "print(review_df['review'][0])" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "y_bNZVCwYiqh", + "outputId": "bc808736-cce8-4571-f381-56f36db1f1c6" + }, + "execution_count": 17, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\"With all this stuff going down at the moment with MJ i've started listening to his music, watching the odd documentary here and there, watched The Wiz and watched Moonwalker again. Maybe i just want to get a certain insight into this guy who i thought was really cool in the eighties just to maybe make up my mind whether he is guilty or innocent. Moonwalker is part biography, part feature film which i remember going to see at the cinema when it was originally released. Some of it has subtle messages about MJ's feeling towards the press and also the obvious message of drugs are bad m'kay.

Visually impressive but of course this is all about Michael Jackson so unless you remotely like MJ in anyway then you are going to hate this and find it boring. Some may call MJ an egotist for consenting to the making of this movie BUT MJ and most of his fans would say that he made it for the fans which if true is really nice of him.

The actual feature film bit when it finally starts is only on for 20 minutes or so excluding the Smooth Criminal sequence and Joe Pesci is convincing as a psychopathic all powerful drug lord. Why he wants MJ dead so bad is beyond me. Because MJ overheard his plans? Nah, Joe Pesci's character ranted that he wanted people to know it is he who is supplying drugs etc so i dunno, maybe he just hates MJ's music.

Lots of cool things in this like MJ turning into a car and a robot and the whole Speed Demon sequence. Also, the director must have had the patience of a saint when it came to filming the kiddy Bad sequence as usually directors hate working with one kid let alone a whole bunch of them performing a complex dance scene.

Bottom line, this movie is for people who like MJ on one level or another (which i think is most people). If not, then stay away. It does try and give off a wholesome message and ironically MJ's bestest buddy in this movie is a girl! Michael Jackson is truly one of the most talented people ever to grace this planet but is he guilty? Well, with all the attention i've gave this subject....hmmm well i don't know because people can be different behind closed doors, i know this for a fact. He is either an extremely nice but stupid guy or one of the most sickest liars. I hope he is not the latter.\"\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 3. ์ •๊ทœ ํ‘œํ˜„์‹(Regular Expression)์„ ํ™œ์šฉํ•œ ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ ์ •์ œ ๋ฐ ์ „์ฒ˜๋ฆฌ\n", + "# ํ…์ŠคํŠธ ๋‚ด์˜ ๋ถˆํ•„์š”ํ•œ HTML ํƒœ๊ทธ์™€ ์˜๋ฌธ์ด ์•„๋‹Œ ํŠน์ˆ˜๋ฌธ์ž, ์ˆซ์ž ๋“ฑ์„ ์ œ๊ฑฐํ•˜์—ฌ ๊ฐ์„ฑ ๋ถ„์„์— ์ ํ•ฉํ•œ ํ˜•ํƒœ๋กœ ์ •์ œํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import re\n", + "\n", + "#
HTML ํƒœ๊ทธ๋ฅผ replace ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ณต๋ฐฑ(Space)์œผ๋กœ ๋ณ€ํ™˜\n", + "review_df['review'] = review_df['review'].str.replace('
', ' ')\n", + "\n", + "# ํŒŒ์ด์ฌ์˜ ์ •๊ทœ ํ‘œํ˜„์‹ ๋ชจ๋“ˆ์ธ re๋ฅผ ์ด์šฉํ•ด ์˜์–ด ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ๋ชจ๋“  ๋ฌธ์ž๋ฅผ ๊ณต๋ฐฑ์œผ๋กœ ๋ณ€ํ™˜ (์ •์ œ ๊ณผ์ • ์ˆ˜ํ–‰)\n", + "review_df['review'] = review_df['review'].apply(lambda x : re.sub(\"[^a-zA-Z]\", \" \", x))" + ], + "metadata": { + "id": "4vkQ1HR0Ylet" + }, + "execution_count": 18, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# 4. ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋ถ„ํ•  ๋ฐ ํ•™์Šต/ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ(Train/Test Dataset) ์ƒ์„ฑ\n", + "# ํ•™์Šต์šฉ ํ”ผ์ฒ˜/ํด๋ž˜์Šค ๋ฐ์ดํ„ฐ์™€ ๊ฒ€์ฆ์šฉ ํ”ผ์ฒ˜/ํด๋ž˜์Šค ๋ฐ์ดํ„ฐ๋ฅผ 7:3 ๋น„์œจ๋กœ ๋ถ„ํ• ํ•˜๊ณ  ์ตœ์ข… ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "# ํƒ€๊นƒ ๋ ˆ์ด๋ธ”์ธ ๊ฐ์„ฑ(Sentiment) ํด๋ž˜์Šค ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ์ถ”์ถœ\n", + "class_df = review_df['sentiment']\n", + "\n", + "# ์›๋ณธ ๋ฐ์ดํ„ฐ์—์„œ ๋ถˆํ•„์š”ํ•œ ๊ณ ์œ  ID์™€ ํƒ€๊นƒ ์‹๋ณ„์ž๋ฅผ ์‚ญ์ œํ•˜์—ฌ ํ”ผ์ฒ˜(Feature) ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ์ƒ์„ฑ\n", + "feature_df = review_df.drop(['id', 'sentiment'], axis=1, inplace=False)\n", + "\n", + "# train_test_split์„ ์ด์šฉํ•˜์—ฌ ํ•™์Šต ๋ฐ์ดํ„ฐ ์„ธํŠธ์™€ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋กœ ๋ถ„ํ•  (ํ…Œ์ŠคํŠธ ๋น„์œจ 30%)\n", + "X_train, X_test, y_train, y_test = train_test_split(feature_df, class_df, test_size=0.3, random_state=156)\n", + "\n", + "# ๋ถ„ํ• ๋œ ํ•™์Šต ํ”ผ์ฒ˜ ๋ฐ์ดํ„ฐ์™€ ํ…Œ์ŠคํŠธ ํ”ผ์ฒ˜ ๋ฐ์ดํ„ฐ์˜ ํ–‰๋ ฌ ๊ตฌ์กฐ(Shape) ํ™•์ธ\n", + "X_train.shape, X_test.shape" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Ib3REJ93Y1cK", + "outputId": "c500c8c4-6721-4171-8076-a5956aba0900" + }, + "execution_count": 19, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "((9746, 1), (4177, 1))" + ] + }, + "metadata": {}, + "execution_count": 19 + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 5. ํŒŒ์ดํ”„๋ผ์ธ(Pipeline)์„ ํ™œ์šฉํ•œ ์นด์šดํŠธ ๊ธฐ๋ฐ˜ ํ”ผ์ฒ˜ ๋ฒกํ„ฐํ™” ๋ฐ ๋กœ์ง€์Šคํ‹ฑ ํšŒ๊ท€ ํ•™์Šต/ํ‰๊ฐ€\n", + "# ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์˜ Count ๋ฒกํ„ฐํ™”์™€ ๋กœ์ง€์Šคํ‹ฑ ํšŒ๊ท€(Logistic Regression) ๋ชจ๋ธ์˜ ํ•™์Šต, ์˜ˆ์ธก, ์„ฑ๋Šฅ ํ‰๊ฐ€๋ฅผ ๋‹จ์ผ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ๊ฒฐํ•ฉํ•˜์—ฌ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer\n", + "from sklearn.pipeline import Pipeline\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.metrics import accuracy_score, roc_auc_score\n", + "\n", + "# CountVectorizer(ํ”ผ์ฒ˜ ๋ฒกํ„ฐํ™”)์™€ LogisticRegression(๋ถ„๋ฅ˜ ๋ชจ๋ธ)์„ ๊ฒฐํ•ฉํ•œ ํŒŒ์ดํ”„๋ผ์ธ ๊ฐ์ฒด ์ƒ์„ฑ\n", + "# ์Šคํ†ฑ ์›Œ๋“œ๋Š” English, n-gram์€ (1, 2), ๋ถ„๋ฅ˜๊ธฐ์˜ ๊ทœ์ œ ๊ณ„์ˆ˜ C๋Š” 10์œผ๋กœ ์„ค์ •\n", + "pipeline = Pipeline([\n", + " ('cnt_vect', CountVectorizer(stop_words='english', ngram_range=(1, 2))),\n", + " ('lr_clf', LogisticRegression(solver='liblinear', C=10))\n", + "])\n", + "\n", + "# ํ•™์Šต ๋ฐ์ดํ„ฐ์˜ ๋ฆฌ๋ทฐ ํ…์ŠคํŠธ๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ํŒŒ์ดํ”„๋ผ์ธ ์ „์ฒด ํ”„๋กœ์„ธ์Šค(๋ฒกํ„ฐํ™” ๋ฐ ๋ชจ๋ธ) ํ•™์Šต(Fit) ์ˆ˜ํ–‰\n", + "pipeline.fit(X_train['review'], y_train)\n", + "\n", + "# ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•ด ํด๋ž˜์Šค ์˜ˆ์ธก(Predict) ๋ฐ ๊ธ์ • ํ™•๋ฅ (Predict Proba) ์ถ”์ถœ\n", + "pred = pipeline.predict(X_test['review'])\n", + "pred_probs = pipeline.predict_proba(X_test['review'])[:, 1]\n", + "\n", + "# ๋ชจ๋ธ์˜ ์ตœ์ข… ์„ฑ๋Šฅ ์ง€ํ‘œ์ธ ์˜ˆ์ธก ์ •ํ™•๋„(Accuracy) ๋ฐ ROC-AUC ์ˆ˜์น˜๋ฅผ ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print('์˜ˆ์ธก ์ •ํ™•๋„๋Š” {0:.4f}, ROC-AUC๋Š” {1:.4f}'.format(accuracy_score(y_test, pred), roc_auc_score(y_test, pred_probs)))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ZhIMQONUZEH9", + "outputId": "8546d09c-4017-4526-8e71-5bce06931e87" + }, + "execution_count": 20, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "์˜ˆ์ธก ์ •ํ™•๋„๋Š” 0.8753, ROC-AUC๋Š” 0.9377\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 6. NLTK ์ „์ฒด ์ฝ”ํผ์Šค(Corpus) ๋ฐ ๋ฐ์ดํ„ฐ ์„ธํŠธ ํ†ตํ•ฉ ๋‹ค์šด๋กœ๋“œ\n", + "# ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ์— ํ•„์š”ํ•œ NLTK ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ชจ๋“  ํŒจํ‚ค์ง€, ์‚ฌ์ „ ๋ฐ์ดํ„ฐ, ์–ธ์–ด ๋ชจ๋ธ ์ž์›(Resource)์„ ์ผ๊ด„ ๋‹ค์šด๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import nltk\n", + "\n", + "# NLTK๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ „์ฒด ๋ฐ์ดํ„ฐ ์„ธํŠธ('all') ์ผ๊ด„ ๋‹ค์šด๋กœ๋“œ ์ˆ˜ํ–‰\n", + "nltk.download('all')" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "cHfmrCxEcfHO", + "outputId": "e771ecc0-80f0-4bbf-a3c5-c0501f823c49" + }, + "execution_count": 21, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "[nltk_data] Downloading collection 'all'\n", + "[nltk_data] | \n", + "[nltk_data] | Downloading package abc to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/abc.zip.\n", + "[nltk_data] | Downloading package alpino to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/alpino.zip.\n", + "[nltk_data] | Downloading package averaged_perceptron_tagger to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping taggers/averaged_perceptron_tagger.zip.\n", + "[nltk_data] | Downloading package averaged_perceptron_tagger_eng to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping\n", + "[nltk_data] | taggers/averaged_perceptron_tagger_eng.zip.\n", + "[nltk_data] | Downloading package averaged_perceptron_tagger_ru to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping\n", + "[nltk_data] | taggers/averaged_perceptron_tagger_ru.zip.\n", + "[nltk_data] | Downloading package averaged_perceptron_tagger_rus to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping\n", + "[nltk_data] | taggers/averaged_perceptron_tagger_rus.zip.\n", + "[nltk_data] | Downloading package basque_grammars to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping grammars/basque_grammars.zip.\n", + "[nltk_data] | Downloading package bcp47 to /root/nltk_data...\n", + "[nltk_data] | Downloading package biocreative_ppi to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/biocreative_ppi.zip.\n", + "[nltk_data] | Downloading package bllip_wsj_no_aux to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping models/bllip_wsj_no_aux.zip.\n", + "[nltk_data] | Downloading package book_grammars to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping grammars/book_grammars.zip.\n", + "[nltk_data] | Downloading package brown to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/brown.zip.\n", + "[nltk_data] | Downloading package brown_tei to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/brown_tei.zip.\n", + "[nltk_data] | Downloading package cess_cat to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/cess_cat.zip.\n", + "[nltk_data] | Downloading package cess_esp to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/cess_esp.zip.\n", + "[nltk_data] | Downloading package chat80 to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/chat80.zip.\n", + "[nltk_data] | Downloading package city_database to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/city_database.zip.\n", + "[nltk_data] | Downloading package cmudict to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/cmudict.zip.\n", + "[nltk_data] | Downloading package comparative_sentences to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/comparative_sentences.zip.\n", + "[nltk_data] | Downloading package comtrans to /root/nltk_data...\n", + "[nltk_data] | Downloading package conll2000 to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/conll2000.zip.\n", + "[nltk_data] | Downloading package conll2002 to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/conll2002.zip.\n", + "[nltk_data] | Downloading package conll2007 to /root/nltk_data...\n", + "[nltk_data] | Downloading package crubadan to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/crubadan.zip.\n", + "[nltk_data] | Downloading package dependency_treebank to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/dependency_treebank.zip.\n", + "[nltk_data] | Downloading package dolch to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/dolch.zip.\n", + "[nltk_data] | Downloading package english_wordnet to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/english_wordnet.zip.\n", + "[nltk_data] | Downloading package europarl_raw to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/europarl_raw.zip.\n", + "[nltk_data] | Downloading package extended_omw to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Downloading package floresta to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/floresta.zip.\n", + "[nltk_data] | Downloading package framenet_v15 to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/framenet_v15.zip.\n", + "[nltk_data] | Downloading package framenet_v17 to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/framenet_v17.zip.\n", + "[nltk_data] | Downloading package gazetteers to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/gazetteers.zip.\n", + "[nltk_data] | Downloading package genesis to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/genesis.zip.\n", + "[nltk_data] | Downloading package gutenberg to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/gutenberg.zip.\n", + "[nltk_data] | Downloading package ieer to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/ieer.zip.\n", + "[nltk_data] | Downloading package inaugural to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/inaugural.zip.\n", + "[nltk_data] | Downloading package indian to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/indian.zip.\n", + "[nltk_data] | Downloading package jeita to /root/nltk_data...\n", + "[nltk_data] | Downloading package kimmo to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/kimmo.zip.\n", + "[nltk_data] | Downloading package knbc to /root/nltk_data...\n", + "[nltk_data] | Downloading package large_grammars to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping grammars/large_grammars.zip.\n", + "[nltk_data] | Downloading package lin_thesaurus to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/lin_thesaurus.zip.\n", + "[nltk_data] | Downloading package mac_morpho to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/mac_morpho.zip.\n", + "[nltk_data] | Downloading package machado to /root/nltk_data...\n", + "[nltk_data] | Downloading package masc_tagged to /root/nltk_data...\n", + "[nltk_data] | Downloading package maxent_ne_chunker to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping chunkers/maxent_ne_chunker.zip.\n", + "[nltk_data] | Downloading package maxent_ne_chunker_tab to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping chunkers/maxent_ne_chunker_tab.zip.\n", + "[nltk_data] | Downloading package maxent_treebank_pos_tagger to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping taggers/maxent_treebank_pos_tagger.zip.\n", + "[nltk_data] | Downloading package maxent_treebank_pos_tagger_tab to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping\n", + "[nltk_data] | taggers/maxent_treebank_pos_tagger_tab.zip.\n", + "[nltk_data] | Downloading package mock_corpus to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/mock_corpus.zip.\n", + "[nltk_data] | Downloading package moses_sample to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping models/moses_sample.zip.\n", + "[nltk_data] | Downloading package movie_reviews to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/movie_reviews.zip.\n", + "[nltk_data] | Downloading package mte_teip5 to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/mte_teip5.zip.\n", + "[nltk_data] | Downloading package mwa_ppdb to /root/nltk_data...\n", + "[nltk_data] | Unzipping misc/mwa_ppdb.zip.\n", + "[nltk_data] | Downloading package names to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/names.zip.\n", + "[nltk_data] | Downloading package nombank.1.0 to /root/nltk_data...\n", + "[nltk_data] | Downloading package nonbreaking_prefixes to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/nonbreaking_prefixes.zip.\n", + "[nltk_data] | Downloading package nps_chat to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/nps_chat.zip.\n", + "[nltk_data] | Downloading package omw to /root/nltk_data...\n", + "[nltk_data] | Downloading package omw-1.4 to /root/nltk_data...\n", + "[nltk_data] | Downloading package opinion_lexicon to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/opinion_lexicon.zip.\n", + "[nltk_data] | Downloading package panlex_swadesh to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Downloading package paradigms to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/paradigms.zip.\n", + "[nltk_data] | Downloading package pe08 to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/pe08.zip.\n", + "[nltk_data] | Downloading package perluniprops to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping misc/perluniprops.zip.\n", + "[nltk_data] | Downloading package pil to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/pil.zip.\n", + "[nltk_data] | Downloading package pl196x to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/pl196x.zip.\n", + "[nltk_data] | Downloading package porter_test to /root/nltk_data...\n", + "[nltk_data] | Unzipping stemmers/porter_test.zip.\n", + "[nltk_data] | Downloading package ppattach to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/ppattach.zip.\n", + "[nltk_data] | Downloading package problem_reports to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/problem_reports.zip.\n", + "[nltk_data] | Downloading package product_reviews_1 to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/product_reviews_1.zip.\n", + "[nltk_data] | Downloading package product_reviews_2 to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/product_reviews_2.zip.\n", + "[nltk_data] | Downloading package propbank to /root/nltk_data...\n", + "[nltk_data] | Downloading package pros_cons to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/pros_cons.zip.\n", + "[nltk_data] | Downloading package ptb to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/ptb.zip.\n", + "[nltk_data] | Downloading package punkt to /root/nltk_data...\n", + "[nltk_data] | Package punkt is already up-to-date!\n", + "[nltk_data] | Downloading package punkt_tab to /root/nltk_data...\n", + "[nltk_data] | Package punkt_tab is already up-to-date!\n", + "[nltk_data] | Downloading package qc to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/qc.zip.\n", + "[nltk_data] | Downloading package reuters to /root/nltk_data...\n", + "[nltk_data] | Downloading package rslp to /root/nltk_data...\n", + "[nltk_data] | Unzipping stemmers/rslp.zip.\n", + "[nltk_data] | Downloading package rte to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/rte.zip.\n", + "[nltk_data] | Downloading package sample_grammars to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping grammars/sample_grammars.zip.\n", + "[nltk_data] | Downloading package semcor to /root/nltk_data...\n", + "[nltk_data] | Downloading package senseval to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/senseval.zip.\n", + "[nltk_data] | Downloading package sentence_polarity to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/sentence_polarity.zip.\n", + "[nltk_data] | Downloading package sentiwordnet to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/sentiwordnet.zip.\n", + "[nltk_data] | Downloading package shakespeare to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/shakespeare.zip.\n", + "[nltk_data] | Downloading package sinica_treebank to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/sinica_treebank.zip.\n", + "[nltk_data] | Downloading package smultron to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/smultron.zip.\n", + "[nltk_data] | Downloading package snowball_data to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Downloading package spanish_grammars to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping grammars/spanish_grammars.zip.\n", + "[nltk_data] | Downloading package state_union to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/state_union.zip.\n", + "[nltk_data] | Downloading package stopwords to /root/nltk_data...\n", + "[nltk_data] | Package stopwords is already up-to-date!\n", + "[nltk_data] | Downloading package subjectivity to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/subjectivity.zip.\n", + "[nltk_data] | Downloading package swadesh to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/swadesh.zip.\n", + "[nltk_data] | Downloading package switchboard to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/switchboard.zip.\n", + "[nltk_data] | Downloading package tagsets to /root/nltk_data...\n", + "[nltk_data] | Unzipping help/tagsets.zip.\n", + "[nltk_data] | Downloading package tagsets_json to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping help/tagsets_json.zip.\n", + "[nltk_data] | Downloading package timit to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/timit.zip.\n", + "[nltk_data] | Downloading package toolbox to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/toolbox.zip.\n", + "[nltk_data] | Downloading package treebank to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/treebank.zip.\n", + "[nltk_data] | Downloading package twitter_samples to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/twitter_samples.zip.\n", + "[nltk_data] | Downloading package udhr to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/udhr.zip.\n", + "[nltk_data] | Downloading package udhr2 to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/udhr2.zip.\n", + "[nltk_data] | Downloading package unicode_samples to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/unicode_samples.zip.\n", + "[nltk_data] | Downloading package universal_tagset to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping taggers/universal_tagset.zip.\n", + "[nltk_data] | Downloading package universal_treebanks_v20 to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Downloading package vader_lexicon to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Downloading package verbnet to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/verbnet.zip.\n", + "[nltk_data] | Downloading package verbnet3 to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/verbnet3.zip.\n", + "[nltk_data] | Downloading package webtext to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/webtext.zip.\n", + "[nltk_data] | Downloading package wmt15_eval to /root/nltk_data...\n", + "[nltk_data] | Unzipping models/wmt15_eval.zip.\n", + "[nltk_data] | Downloading package word2vec_sample to\n", + "[nltk_data] | /root/nltk_data...\n", + "[nltk_data] | Unzipping models/word2vec_sample.zip.\n", + "[nltk_data] | Downloading package wordnet to /root/nltk_data...\n", + "[nltk_data] | Package wordnet is already up-to-date!\n", + "[nltk_data] | Downloading package wordnet2021 to /root/nltk_data...\n", + "[nltk_data] | Downloading package wordnet2022 to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/wordnet2022.zip.\n", + "[nltk_data] | Downloading package wordnet31 to /root/nltk_data...\n", + "[nltk_data] | Downloading package wordnet_ic to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/wordnet_ic.zip.\n", + "[nltk_data] | Downloading package words to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/words.zip.\n", + "[nltk_data] | Downloading package ycoe to /root/nltk_data...\n", + "[nltk_data] | Unzipping corpora/ycoe.zip.\n", + "[nltk_data] | \n", + "[nltk_data] Done downloading collection all\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "True" + ] + }, + "metadata": {}, + "execution_count": 21 + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 7. WordNet ๊ธฐ๋ฐ˜ ๋‹จ์–ด์˜ ์‹œ์…‹(Synset) ์ถ”์ถœ ๋ฐ ์˜๋ฏธ ์ง‘ํ•ฉ ๊ตฌ์กฐ ํ™•์ธ\n", + "# NLTK์˜ WordNet์„ ํ™œ์šฉํ•˜์—ฌ ํŠน์ • ๋‹จ์–ด๊ฐ€ ๋‚ดํฌํ•˜๋Š” ๋‹ค์˜์–ด/๋™์Œ์ด์˜์–ด ์‚ฌ์ „ ๊ตฌ์กฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ๊ฐœ์ˆ˜๋ฅผ ํŒŒ์•…ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from nltk.corpus import wordnet as wn\n", + "\n", + "# ๋ถ„์„ํ•  ๊ธฐ์ค€ ๋‹จ์–ด(Term) ์ •์˜\n", + "term = 'present'\n", + "\n", + "# 'present'๋ผ๋Š” ๋‹จ์–ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ WordNet์— ๋“ฑ๋ก๋œ ์‹œ์…‹(Synsets) ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ\n", + "synsets = wn.synsets(term)\n", + "\n", + "# ๋ฐ˜ํ™˜๋œ ์‹œ์…‹ ๊ฐ์ฒด์˜ ์ž๋ฃŒํ˜•(Type) ์ถœ๋ ฅ\n", + "print('synsets() ๋ฐ˜ํ™˜ type :', type(synsets))\n", + "\n", + "# ํ•ด๋‹น ๋‹จ์–ด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ณ ์œ ํ•œ ์˜๋ฏธ ์ง‘ํ•ฉ์˜ ๊ฐœ์ˆ˜(Length) ์ถœ๋ ฅ\n", + "print('synsets() ๋ฐ˜ํ™˜ ๊ฐ’ ๊ฐฏ์ˆ˜:', len(synsets))\n", + "\n", + "# ๋‹จ์–ด๊ฐ€ ๊ฐ€์ง„ ๋ชจ๋“  ์–ดํœ˜์  ์˜๋ฏธ(Synset) ๋ชฉ๋ก ์ „์ฒด ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print('synsets() ๋ฐ˜ํ™˜ ๊ฐ’ :', synsets)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "FyqXFemrc1MF", + "outputId": "1d48a255-43e5-44a6-c9d6-d089a6c382aa" + }, + "execution_count": 22, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "synsets() ๋ฐ˜ํ™˜ type : \n", + "synsets() ๋ฐ˜ํ™˜ ๊ฐ’ ๊ฐฏ์ˆ˜: 18\n", + "synsets() ๋ฐ˜ํ™˜ ๊ฐ’ : [Synset('present.n.01'), Synset('present.n.02'), Synset('present.n.03'), Synset('show.v.01'), Synset('present.v.02'), Synset('stage.v.01'), Synset('present.v.04'), Synset('present.v.05'), Synset('award.v.01'), Synset('give.v.08'), Synset('deliver.v.01'), Synset('introduce.v.01'), Synset('portray.v.04'), Synset('confront.v.03'), Synset('present.v.12'), Synset('salute.v.06'), Synset('present.a.01'), Synset('present.a.02')]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 8. ์‹œ์…‹(Synset) ๊ฐ์ฒด๋ณ„ ์–ดํœ˜ ์„ธ๋ถ€ ์ •๋ณด ๋ฐ ์˜๋ฏธ๋ก ์  ๊ตฌ์กฐ ๋ถ„์„\n", + "# ์ถ”์ถœ๋œ ๋‹จ์–ด ์˜๋ฏธ ์ง‘ํ•ฉ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ๊ฐ ์‹œ์…‹์˜ ์ด๋ฆ„, ํ’ˆ์‚ฌ ๋ถ„๋ฅ˜(POS), ๊ฐœ๋… ์ •์˜(Definition), ํ‘œ์ œ์–ด ๋ชฉ๋ก์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "# ๋‹จ์–ด 'present'๋กœ ์ƒ์„ฑ๋œ ๋ชจ๋“  ์‹œ์…‹(Synsets) ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋Š” ๋ฐ˜๋ณต๋ฌธ\n", + "for synset in synsets:\n", + " # ๊ฐœ๋ณ„ ์‹œ์…‹์˜ ๊ณ ์œ  ์‹๋ณ„ ๋ช…์นญ(Name) ์ถœ๋ ฅ\n", + " print('##### Synset name : ', synset.name(), '#####')\n", + "\n", + " # ํ•ด๋‹น ์˜๋ฏธ๊ฐ€ ์†ํ•œ ๋ฌธ๋งฅ์ƒ์˜ ํ’ˆ์‚ฌ ๋ฐ ๋ถ„๋ฅ˜ ๊ทธ๋ฃน(Lexicographer Name) ์ถœ๋ ฅ\n", + " print('POS :', synset.lexname())\n", + "\n", + " # ํ•ด๋‹น ์–ดํœ˜ ์˜๋ฏธ์— ๋Œ€ํ•œ ์‚ฌ์ „์  ์ฃผ์„ ๋ฐ ๊ฐœ๋… ์ •์˜(Definition) ์ถœ๋ ฅ\n", + " print('Definition:', synset.definition())\n", + "\n", + " # ๋™์ผํ•œ ์˜๋ฏธ๋ฅผ ๊ณต์œ ํ•˜๋Š” ์œ ์˜์–ด ๋ฐ ํ‘œ์ œ์–ด(Lemmas) ๋ฆฌ์ŠคํŠธ๋ฅผ ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + " print('Lemmas:', synset.lemma_names())" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "M5s4qKY5dJhi", + "outputId": "4aaa627e-93dc-4a8a-a67e-c4e5dd8017cc" + }, + "execution_count": 23, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "##### Synset name : present.n.01 #####\n", + "POS : noun.time\n", + "Definition: the period of time that is happening now; any continuous stretch of time including the moment of speech\n", + "Lemmas: ['present', 'nowadays']\n", + "##### Synset name : present.n.02 #####\n", + "POS : noun.possession\n", + "Definition: something presented as a gift\n", + "Lemmas: ['present']\n", + "##### Synset name : present.n.03 #####\n", + "POS : noun.communication\n", + "Definition: a verb tense that expresses actions or states at the time of speaking\n", + "Lemmas: ['present', 'present_tense']\n", + "##### Synset name : show.v.01 #####\n", + "POS : verb.perception\n", + "Definition: give an exhibition of to an interested audience\n", + "Lemmas: ['show', 'demo', 'exhibit', 'present', 'demonstrate']\n", + "##### Synset name : present.v.02 #####\n", + "POS : verb.communication\n", + "Definition: bring forward and present to the mind\n", + "Lemmas: ['present', 'represent', 'lay_out']\n", + "##### Synset name : stage.v.01 #####\n", + "POS : verb.creation\n", + "Definition: perform (a play), especially on a stage\n", + "Lemmas: ['stage', 'present', 'represent']\n", + "##### Synset name : present.v.04 #####\n", + "POS : verb.possession\n", + "Definition: hand over formally\n", + "Lemmas: ['present', 'submit']\n", + "##### Synset name : present.v.05 #####\n", + "POS : verb.stative\n", + "Definition: introduce\n", + "Lemmas: ['present', 'pose']\n", + "##### Synset name : award.v.01 #####\n", + "POS : verb.possession\n", + "Definition: give, especially as an honor or reward\n", + "Lemmas: ['award', 'present']\n", + "##### Synset name : give.v.08 #####\n", + "POS : verb.possession\n", + "Definition: give as a present; make a gift of\n", + "Lemmas: ['give', 'gift', 'present']\n", + "##### Synset name : deliver.v.01 #####\n", + "POS : verb.communication\n", + "Definition: deliver (a speech, oration, or idea)\n", + "Lemmas: ['deliver', 'present']\n", + "##### Synset name : introduce.v.01 #####\n", + "POS : verb.communication\n", + "Definition: cause to come to know personally\n", + "Lemmas: ['introduce', 'present', 'acquaint']\n", + "##### Synset name : portray.v.04 #####\n", + "POS : verb.creation\n", + "Definition: represent abstractly, for example in a painting, drawing, or sculpture\n", + "Lemmas: ['portray', 'present']\n", + "##### Synset name : confront.v.03 #####\n", + "POS : verb.communication\n", + "Definition: present somebody with something, usually to accuse or criticize\n", + "Lemmas: ['confront', 'face', 'present']\n", + "##### Synset name : present.v.12 #####\n", + "POS : verb.communication\n", + "Definition: formally present a debutante, a representative of a country, etc.\n", + "Lemmas: ['present']\n", + "##### Synset name : salute.v.06 #####\n", + "POS : verb.communication\n", + "Definition: recognize with a gesture prescribed by a military regulation; assume a prescribed position\n", + "Lemmas: ['salute', 'present']\n", + "##### Synset name : present.a.01 #####\n", + "POS : adj.all\n", + "Definition: temporal sense; intermediate between past and future; now existing or happening or in consideration\n", + "Lemmas: ['present']\n", + "##### Synset name : present.a.02 #####\n", + "POS : adj.all\n", + "Definition: being or existing in a specified place\n", + "Lemmas: ['present']\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 9. WordNet ์‹œ์…‹(Synset) ๊ฐ„์˜ ๊ฒฝ๋กœ ์œ ์‚ฌ๋„(Path Similarity) ์ธก์ • ๋ฐ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ๋งคํ•‘\n", + "# ๊ฐœ๋ณ„ ๋‹จ์–ด์˜ ์‹œ์…‹ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ƒํ˜ธ ๊ฐ„์˜ ์˜๋ฏธ๋ก ์  ๊ฒฝ๋กœ ์œ ์‚ฌ๋„๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ํ–‰๋ ฌ ๊ตฌ์กฐ์˜ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์œผ๋กœ ์‹œ๊ฐํ™”ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import pandas as pd\n", + "from nltk.corpus import wordnet as wn\n", + "\n", + "# ๋น„๊ต ๋ถ„์„ํ•  ์ฃผ์š” ๋‹จ์–ด๋ณ„ ์‹œ์…‹(Synset) ๊ฐ์ฒด ์ƒ์„ฑ\n", + "tree = wn.synset('tree.n.01')\n", + "lion = wn.synset('lion.n.01')\n", + "tiger = wn.synset('tiger.n.02')\n", + "cat = wn.synset('cat.n.01')\n", + "dog = wn.synset('dog.n.01')\n", + "\n", + "# ์‹œ์…‹ ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ ๋ฐ ์œ ์‚ฌ๋„ ์ธก์ •๊ฐ’ ์ €์žฅ์šฉ ๋ฆฌ์ŠคํŠธ ์ •์˜\n", + "entities = [tree, lion, tiger, cat, dog]\n", + "similarities = []\n", + "\n", + "# ๊ฐ ์‹œ์…‹์˜ ๊ณ ์œ  ์‹๋ณ„ ๋ช…์นญ์—์„œ ์ˆœ์ˆ˜ ๋‹จ์–ด๋ช…(Entity Name)๋งŒ ์ถ”์ถœํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ ๊ตฌ์„ฑ\n", + "entity_names = [entity.name().split('.')[0] for entity in entities]\n", + "\n", + "# ๋‹จ์–ด๋ณ„ ์‹œ์…‹ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ๋‹ค๋ฅธ ๋‹จ์–ด์˜ ์‹œ์…‹๊ณผ์˜ ๊ฒฝ๋กœ ์œ ์‚ฌ๋„(Path Similarity) ๋ฐ˜๋ณต ์ธก์ •\n", + "for entity in entities:\n", + " # ์†Œ์ˆ˜์  ๋‘˜์งธ ์ž๋ฆฌ๊นŒ์ง€ ๋ฐ˜์˜ฌ๋ฆผํ•˜์—ฌ ์ƒํ˜ธ ๊ฐ„์˜ ์œ ์‚ฌ๋„ ํ–‰๋ ฌ ๊ณ„์‚ฐ\n", + " similarity = [round(entity.path_similarity(compared_entity), 2)\n", + " for compared_entity in entities]\n", + " similarities.append(similarity)\n", + "\n", + "# ๊ณ„์‚ฐ๋œ ๋‹จ์–ด๋ณ„ ์œ ์‚ฌ๋„ ๋ฆฌ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ํŒ๋‹ค์Šค ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„(DataFrame) ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜ ๋ฐ ์ปฌ๋Ÿผ/์ธ๋ฑ์Šค ๋ช…๋ช…\n", + "similarity_df = pd.DataFrame(similarities, columns=entity_names, index=entity_names)\n", + "\n", + "# ์ƒ์„ฑ๋œ ์œ ์‚ฌ๋„ ํ–‰๋ ฌ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ์ „์ฒด๋ฅผ ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "similarity_df" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "id": "W4iRtpX3dXXZ", + "outputId": "97597558-31c9-4b68-d844-e43386879b78" + }, + "execution_count": 24, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " tree lion tiger cat dog\n", + "tree 1.00 0.07 0.07 0.08 0.12\n", + "lion 0.07 1.00 0.33 0.25 0.17\n", + "tiger 0.07 0.33 1.00 0.25 0.17\n", + "cat 0.08 0.25 0.25 1.00 0.20\n", + "dog 0.12 0.17 0.17 0.20 1.00" + ], + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
treeliontigercatdog
tree1.000.070.070.080.12
lion0.071.000.330.250.17
tiger0.070.331.000.250.17
cat0.080.250.251.000.20
dog0.120.170.170.201.00
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + " \n", + " \n", + "
\n", + "\n", + "
\n", + "
\n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "similarity_df", + "summary": "{\n \"name\": \"similarity_df\",\n \"rows\": 5,\n \"fields\": [\n {\n \"column\": \"tree\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.40971941618624813,\n \"min\": 0.07,\n \"max\": 1.0,\n \"num_unique_values\": 4,\n \"samples\": [\n 0.07,\n 0.12,\n 1.0\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"lion\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.3683476618630828,\n \"min\": 0.07,\n \"max\": 1.0,\n \"num_unique_values\": 5,\n \"samples\": [\n 1.0,\n 0.17,\n 0.33\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"tiger\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.3683476618630828,\n \"min\": 0.07,\n \"max\": 1.0,\n \"num_unique_values\": 5,\n \"samples\": [\n 0.33,\n 0.17,\n 1.0\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"cat\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.36664696916789047,\n \"min\": 0.08,\n \"max\": 1.0,\n \"num_unique_values\": 4,\n \"samples\": [\n 0.25,\n 0.2,\n 0.08\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"dog\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.3745263675630862,\n \"min\": 0.12,\n \"max\": 1.0,\n \"num_unique_values\": 4,\n \"samples\": [\n 0.17,\n 1.0,\n 0.12\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 24 + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 10. SentiWordNet ๊ธฐ๋ฐ˜ ๊ฐ์„ฑ ์‹œ์…‹(SentiSynset) ์ถ”์ถœ ๋ฐ ์–ดํœ˜ ๊ฐ์„ฑ ๊ตฌ์กฐ ํ™•์ธ\n", + "# ๋‹จ์–ด๊ฐ€ ๊ฐ€์ง„ ๋ฌธ๋งฅ๋ณ„ ๊ฐ์„ฑ ์ง€์ˆ˜(๊ธ์ •/๋ถ€์ •/๊ฐ๊ด€์„ฑ)๋ฅผ ๋ถ„์„ํ•˜๊ธฐ ์œ„ํ•ด ํŠน์ • ๋‹จ์–ด์˜ ๊ฐ์„ฑ ์‹œ์…‹ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import nltk\n", + "from nltk.corpus import sentiwordnet as swn\n", + "\n", + "# 'slow'๋ผ๋Š” ๋‹จ์–ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ SentiWordNet์— ๋“ฑ๋ก๋œ ๊ฐ์„ฑ ์‹œ์…‹(SentiSynsets) ๋ชฉ๋ก์„ ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜\n", + "senti_synsets = list(swn.senti_synsets('slow'))\n", + "\n", + "# ๋ฐ˜ํ™˜๋œ ๊ฐ์„ฑ ์‹œ์…‹ ๋ฆฌ์ŠคํŠธ์˜ ์ž๋ฃŒํ˜•(Type) ์ถœ๋ ฅ\n", + "print('senti_synsets() ๋ฐ˜ํ™˜ type :', type(senti_synsets))\n", + "\n", + "# ํ•ด๋‹น ๋‹จ์–ด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ณ ์œ ํ•œ ๊ฐ์„ฑ ์˜๋ฏธ ์ง‘ํ•ฉ์˜ ๊ฐœ์ˆ˜(Length) ์ถœ๋ ฅ\n", + "print('senti_synsets() ๋ฐ˜ํ™˜ ๊ฐ’ ๊ฐฏ์ˆ˜:', len(senti_synsets))\n", + "\n", + "# ์–ดํœ˜๋ณ„ ๊ฐ์„ฑ ์ฃผ์„์ด ํฌํ•จ๋œ ๊ฐ์„ฑ ์‹œ์…‹ ๋ฐ์ดํ„ฐ ์ „์ฒด๋ฅผ ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print('senti_synsets() ๋ฐ˜ํ™˜ ๊ฐ’ :', senti_synsets)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BR9Z8f7Nd3Hl", + "outputId": "5728a943-4f48-456d-c690-cbbe23f642d1" + }, + "execution_count": 25, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "senti_synsets() ๋ฐ˜ํ™˜ type : \n", + "senti_synsets() ๋ฐ˜ํ™˜ ๊ฐ’ ๊ฐฏ์ˆ˜: 11\n", + "senti_synsets() ๋ฐ˜ํ™˜ ๊ฐ’ : [SentiSynset('decelerate.v.01'), SentiSynset('slow.v.02'), SentiSynset('slow.v.03'), SentiSynset('slow.a.01'), SentiSynset('slow.a.02'), SentiSynset('dense.s.04'), SentiSynset('slow.a.04'), SentiSynset('boring.s.01'), SentiSynset('dull.s.08'), SentiSynset('slowly.r.01'), SentiSynset('behind.r.03')]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 11. SentiSynset ๊ฐ์ฒด์˜ ๊ฐ์„ฑ ์ง€์ˆ˜(Sentiment Score) ์ถ”์ถœ ๋ฐ ์ˆ˜์น˜ ๋ถ„์„\n", + "# ํŠน์ • ์–ดํœ˜ ์‹œ์…‹์˜ ๊ธ์ • ์ง€์ˆ˜(Positive Score), ๋ถ€์ • ์ง€์ˆ˜(Negative Score), ๊ฐ๊ด€์„ฑ ์ง€์ˆ˜(Objective Score)๋ฅผ ์กฐํšŒํ•˜์—ฌ ๊ฐ์ • ์ƒํƒœ๋ฅผ ์ •๋Ÿ‰ํ™”ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "import nltk\n", + "from nltk.corpus import sentiwordnet as swn\n", + "\n", + "# ๋ช…์‚ฌ('n') ํ’ˆ์‚ฌ ์ •๋ณด๋ฅผ ๊ฐ€์ง„ 'father'์˜ ์ฒซ ๋ฒˆ์งธ ๊ฐ์„ฑ ์‹œ์…‹ ๊ฐ์ฒด ์ƒ์„ฑ\n", + "father = swn.senti_synset('father.n.01')\n", + "\n", + "# 'father' ์‹œ์…‹์˜ ๊ฐ์„ฑ ์ง€์ˆ˜(๊ธ์ •, ๋ถ€์ •, ๊ฐ๊ด€์„ฑ)๋ฅผ ๊ฐ๊ฐ ์ถ”์ถœํ•˜์—ฌ ์ถœ๋ ฅ\n", + "print('father ๊ธ์ •๊ฐ์„ฑ ์ง€์ˆ˜:', father.pos_score())\n", + "print('father ๋ถ€์ •๊ฐ์„ฑ ์ง€์ˆ˜:', father.neg_score())\n", + "print('father ๊ฐ๊ด€์„ฑ ์ง€์ˆ˜:', father.obj_score())\n", + "\n", + "print('\\n')\n", + "\n", + "# ํ˜•์šฉ์‚ฌ('a') ํ’ˆ์‚ฌ ์ •๋ณด๋ฅผ ๊ฐ€์ง„ 'fabulous'์˜ ์ฒซ ๋ฒˆ์งธ ๊ฐ์„ฑ ์‹œ์…‹ ๊ฐ์ฒด ์ƒ์„ฑ\n", + "fabulous = swn.senti_synset('fabulous.a.01')\n", + "\n", + "# 'fabulous' ์‹œ์…‹์˜ ๊ฐ์„ฑ ์ง€์ˆ˜(๊ธ์ •, ๋ถ€์ •)๋ฅผ ๊ฐ๊ฐ ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print('fabulous ๊ธ์ •๊ฐ์„ฑ ์ง€์ˆ˜:', fabulous.pos_score())\n", + "print('fabulous ๋ถ€์ •๊ฐ์„ฑ ์ง€์ˆ˜:', fabulous.neg_score())" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "JDb3tmP-d6eN", + "outputId": "0200af87-6f9c-47e4-be64-9785bcd4e901" + }, + "execution_count": 26, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "father ๊ธ์ •๊ฐ์„ฑ ์ง€์ˆ˜: 0.0\n", + "father ๋ถ€์ •๊ฐ์„ฑ ์ง€์ˆ˜: 0.0\n", + "father ๊ฐ๊ด€์„ฑ ์ง€์ˆ˜: 1.0\n", + "\n", + "\n", + "fabulous ๊ธ์ •๊ฐ์„ฑ ์ง€์ˆ˜: 0.875\n", + "fabulous ๋ถ€์ •๊ฐ์„ฑ ์ง€์ˆ˜: 0.125\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 12. Penn Treebank ํ’ˆ์‚ฌ ํƒœ๊ทธ์˜ WordNet ํ’ˆ์‚ฌ ์‹๋ณ„์ž ๋ณ€ํ™˜ ํ•จ์ˆ˜ ๊ตฌํ˜„\n", + "# NLTK์˜ pos_tag()๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” Penn Treebank ํ˜•์‹์˜ ์ ‘๋‘์‚ฌ๋ฅผ ํŒ๋ณ„ํ•˜์—ฌ WordNet ์–ธ์–ด ๋ชจ๋ธ ํ˜ธํ™˜ ํ’ˆ์‚ฌ(POS) ํƒœ๊ทธ๋กœ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from nltk.corpus import wordnet as wn\n", + "\n", + "# Penn Treebank ํ’ˆ์‚ฌ Tag๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ WordNet ๊ธฐ๋ฐ˜์˜ ํ’ˆ์‚ฌ Tag๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ ์ƒ์„ฑ\n", + "def penn_to_wn(tag):\n", + "\n", + " # ์ ‘๋‘์‚ฌ๊ฐ€ 'J'๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ ํ˜•์šฉ์‚ฌ(Adjective) ์‹๋ณ„์ž ๋ฐ˜ํ™˜\n", + " if tag.startswith('J'):\n", + " return wn.ADJ\n", + "\n", + " # ์ ‘๋‘์‚ฌ๊ฐ€ 'N'์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ ๋ช…์‚ฌ(Noun) ์‹๋ณ„์ž ๋ฐ˜ํ™˜\n", + " elif tag.startswith('N'):\n", + " return wn.NOUN\n", + "\n", + " # ์ ‘๋‘์‚ฌ๊ฐ€ 'R'๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ ๋ถ€์‚ฌ(Adverb) ์‹๋ณ„์ž ๋ฐ˜ํ™˜\n", + " elif tag.startswith('R'):\n", + " return wn.ADV\n", + "\n", + " # ์ ‘๋‘์‚ฌ๊ฐ€ 'V'๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ ๋™์‚ฌ(Verb) ์‹๋ณ„์ž ๋ฐ˜ํ™˜ ๊ตฌ์กฐ ์ •์˜\n", + " elif tag.startswith('V'):\n", + " return wn.VERB" + ], + "metadata": { + "id": "n9yFiyoxeUuB" + }, + "execution_count": 27, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# 13. SentiWordNet ๊ธฐ๋ฐ˜ ๋ฌธ์„œ ๊ฐ์„ฑ ๊ทน์„ฑ(Polarity) ์˜ˆ์ธก ํ•จ์ˆ˜ ๊ตฌํ˜„\n", + "# ๋ฌธ์žฅ์„ ํ† ํฐํ™”ํ•˜๊ณ  ํ’ˆ์‚ฌ ํƒœ๊น…๊ณผ ์–ด๊ฐ„ ์ถ”์ถœ์„ ๊ฑฐ์ณ ๋‹จ์–ด๋ณ„ ๊ธ์ •/๋ถ€์ • ์ง€์ˆ˜๋ฅผ ํ•ฉ์‚ฐํ•œ ๋’ค, ์ตœ์ข… ๊ฐ์„ฑ ์Šค์ฝ”์–ด๋ฅผ ํŒ๋ณ„ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from nltk.stem import WordNetLemmatizer\n", + "from nltk.corpus import sentiwordnet as swn\n", + "from nltk.corpus import wordnet as wn\n", + "from nltk import sent_tokenize, word_tokenize, pos_tag\n", + "\n", + "# ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ ๊ฐ์„ฑ ๊ทน์„ฑ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ•จ์ˆ˜ ์ƒ์„ฑ\n", + "def swn_polarity(text):\n", + " # ๊ฐ์„ฑ ์ง€์ˆ˜ ๋ฐ ์—ฐ์‚ฐ์— ์‚ฌ์šฉ๋œ ํ† ํฐ ๊ฐœ์ˆ˜(Count) ์ดˆ๊ธฐํ™”\n", + " sentiment = 0.0\n", + " tokens_count = 0\n", + "\n", + " lemmatizer = WordNetLemmatizer()\n", + " raw_sentences = sent_tokenize(text)\n", + "\n", + " # ๋ถ„ํ•ด๋œ ๋ฌธ์žฅ๋ณ„๋กœ ๋‹จ์–ด ํ† ํฐํ™” ํ›„ ํ’ˆ์‚ฌ ํƒœ๊น…, SentiSynset ์ƒ์„ฑ ๋ฐ ๊ฐ์„ฑ ์ง€์ˆ˜ ํ•ฉ์‚ฐ ๋ฃจํ”„ ์ˆ˜ํ–‰\n", + " for raw_sentence in raw_sentences:\n", + " # NLTK ๊ธฐ๋ฐ˜์˜ ํ’ˆ์‚ฌ ํƒœ๊น…(POS Tagging) ์ˆ˜ํ–‰\n", + " tagged_sentence = pos_tag(word_tokenize(raw_sentence))\n", + " for word, tag in tagged_sentence:\n", + "\n", + " # ์ด์ „์— ์ •์˜ํ•œ penn_to_wn ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•ด WordNet ๊ธฐ๋ฐ˜ ํ’ˆ์‚ฌ ํƒœ๊ทธ๋กœ ๋ณ€ํ™˜\n", + " wn_tag = penn_to_wn(tag)\n", + " if wn_tag not in (wn.NOUN, wn.ADJ, wn.ADV):\n", + " continue\n", + "\n", + " # ๋ณ€ํ™˜๋œ ํ’ˆ์‚ฌ ์ •๋ณด('pos')๋ฅผ ์ง€์ •ํ•˜์—ฌ ๋‹จ์–ด ์–ด๊ทผ ์ถ”์ถœ(Lemmatization) ์ˆ˜ํ–‰\n", + " lemma = lemmatizer.lemmatize(word, pos=wn_tag)\n", + " if not lemma:\n", + " continue\n", + "\n", + " # ์–ด๊ทผ์„ ์ถ”์ถœํ•œ ๋‹จ์–ด์™€ WordNet ๊ธฐ๋ฐ˜ ํ’ˆ์‚ฌ ํƒœ๊น…์„ ์ž…๋ ฅํ•ด ์‹œ์…‹(Synset) ๊ฐ์ฒด ์ƒ์„ฑ\n", + " synsets = wn.synsets(lemma, pos=wn_tag)\n", + " if not synsets:\n", + " continue\n", + "\n", + " # SentiWordNet์˜ ๊ฐ์„ฑ ๋‹จ์–ด ๋ถ„์„์„ ์œ„ํ•ด ๋งค์นญ๋˜๋Š” ์ฒซ ๋ฒˆ์งธ ๊ฐ์„ฑ ์‹œ์…‹(SentiSynset) ์ถ”์ถœ\n", + " synset = synsets[0]\n", + " swn_synset = swn.senti_synset(synset.name())\n", + "\n", + " # ๋ชจ๋“  ๋‹จ์–ด์— ๋Œ€ํ•ด ๊ธ์ • ๊ฐ์„ฑ ์ง€์ˆ˜๋Š” ๋”ํ•˜๊ณ (+) ๋ถ€์ • ๊ฐ์„ฑ ์ง€์ˆ˜๋Š” ๋นผ์„œ(-) ๊ฐ์„ฑ ์ดํ•ฉ ๊ณ„์‚ฐ\n", + " sentiment += (swn_synset.pos_score() - swn_synset.neg_score())\n", + " tokens_count += 1\n", + "\n", + " # ๋ถ„์„์— ์œ ํšจํ•œ ๊ฐ์„ฑ ํ† ํฐ์ด ์ „ํ˜€ ์—†์„ ๊ฒฝ์šฐ 0 ๋ฐ˜ํ™˜\n", + " if not tokens_count:\n", + " return 0\n", + "\n", + " # ์ด ์Šค์ฝ”์–ด(Score)๊ฐ€ 0 ์ด์ƒ์ผ ๊ฒฝ์šฐ ๊ธ์ •(Positive)์ธ 1, ๊ทธ๋ ‡์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋ถ€์ •(Negative)์ธ 0 ๋ฐ˜ํ™˜ ๊ตฌ์กฐ ์ •์˜\n", + " if sentiment >= 0:\n", + " return 1\n", + "\n", + " return 0" + ], + "metadata": { + "id": "uusU5PKvepE0" + }, + "execution_count": 28, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# 14. ์ „์ฒด ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋Œ€์ƒ ๊ฐ์„ฑ ๊ทน์„ฑ ์˜ˆ์ธก ์ˆ˜ํ–‰ ๋ฐ ๊ฒฐ๊ณผ ๋ฐฐ์—ด ์ถ”์ถœ\n", + "# ์ •์˜๋œ ๊ฐ์„ฑ ๋ถ„์„ ํ•จ์ˆ˜๋ฅผ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์˜ ๋ชจ๋“  ๋ฆฌ๋ทฐ์— ์ ์šฉ(Apply)ํ•˜์—ฌ ์˜ˆ์ธก ํ‰์ (Prediction)์„ ๋„์ถœํ•˜๊ณ  ์ตœ์ข… ๋ถ„๋ฅ˜์šฉ ํƒ€๊นƒ/์˜ˆ์ธก ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "# ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์˜ 'review' ์ปฌ๋Ÿผ ์ „์ฒด ํ…์ŠคํŠธ์— ๊ฐ์„ฑ ๋ถ„์„ ๋žŒ๋‹ค(Lambda) ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•˜์—ฌ 'preds' ์ปฌ๋Ÿผ์— ๊ฒฐ๊ณผ ์ €์žฅ\n", + "review_df['preds'] = review_df['review'].apply(lambda x : swn_polarity(x))\n", + "\n", + "# ์„ฑ๋Šฅ ํ‰๊ฐ€ ๋น„๊ต๋ฅผ ์œ„ํ•ด ์‹ค์ œ ์ •๋‹ต ๋ ˆ์ด๋ธ”์ธ ๊ฐ์„ฑ(Sentiment) ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜ํŒŒ์ด ๋ฐฐ์—ด(Values) ํ˜•ํƒœ๋กœ ์ถ”์ถœ\n", + "y_target = review_df['sentiment'].values\n", + "\n", + "# ๋ชจ๋ธ์„ ํ†ตํ•ด ์˜ˆ์ธก๋œ ๊ฐ์„ฑ ๊ทน์„ฑ ๊ฒฐ๊ณผ(Predictions) ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜ํŒŒ์ด ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์ถ”์ถœํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "preds = review_df['preds'].values" + ], + "metadata": { + "id": "Wb06Szi2f9eV" + }, + "execution_count": 29, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# 15. ์˜ค์ฐจ ํ–‰๋ ฌ(Confusion Matrix) ์ถœ๋ ฅ ๋ฐ ๋ถ„๋ฅ˜ ๋ชจ๋ธ ํ•ต์‹ฌ ์„ฑ๋Šฅ ์ง€ํ‘œ ํ‰๊ฐ€\n", + "# ์˜ˆ์ธก๋œ ๊ฒฐ๊ณผ ๋ฐฐ์—ด์„ ๋ฐ”ํƒ•์œผ๋กœ ์˜ค์ฐจ ํ–‰๋ ฌ์„ ์ƒ์„ฑํ•˜๊ณ  ์ •ํ™•๋„, ์ •๋ฐ€๋„, ์žฌํ˜„์œจ ๋“ฑ์˜ ๋‹ค๊ฐ์  ๋ถ„๋ฅ˜ ์ง€ํ‘œ๋ฅผ ์—ฐ์‚ฐํ•˜์—ฌ ์ตœ์ข… ๋ชจ๋ธ ์„ฑ๋Šฅ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from sklearn.metrics import accuracy_score, confusion_matrix, precision_score\n", + "from sklearn.metrics import recall_score, f1_score, roc_auc_score\n", + "import numpy as np\n", + "\n", + "# ์‹ค์ œ ์ •๋‹ต๊ณผ ์˜ˆ์ธก๊ฐ’์„ ๋น„๊ตํ•˜์—ฌ ๋ถ„๋ฅ˜ ๊ฒฐ๊ณผ์˜ ์˜ค์ฐจ ํ–‰๋ ฌ(Confusion Matrix) ๊ตฌ์กฐ ์ถœ๋ ฅ\n", + "print(confusion_matrix(y_target, preds))\n", + "\n", + "# ํ‰๊ฐ€ ์ง€ํ‘œ ์ˆ˜์น˜๋“ค์„ ์†Œ์ˆ˜์  ๋„ท์งธ ์ž๋ฆฌ๊นŒ์ง€ ๋ฐ˜์˜ฌ๋ฆผ(Round)ํ•˜์—ฌ ์ตœ์ข… ์ถœ๋ ฅ ๋ฐ ํ™•์ธ\n", + "print(\"์ •ํ™•๋„:\", np.round(accuracy_score(y_target, preds), 4))\n", + "print(\"์ •๋ฐ€๋„:\", np.round(precision_score(y_target, preds), 4))\n", + "print(\"์žฌํ˜„์œจ:\", np.round(recall_score(y_target, preds), 4))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mESgwNQ0gaMY", + "outputId": "4ed51620-28b0-4a73-a521-cdcaa5bd841b" + }, + "execution_count": 30, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[[4244 2686]\n", + " [2056 4937]]\n", + "์ •ํ™•๋„: 0.6594\n", + "์ •๋ฐ€๋„: 0.6476\n", + "์žฌํ˜„์œจ: 0.706\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 16. VADER ๊ฐ์„ฑ ๋ถ„์„๊ธฐ(Sentiment Intensity Analyzer)๋ฅผ ํ™œ์šฉํ•œ ๋ฆฌ๋ทฐ ๊ฐ์„ฑ ์ง€์ˆ˜ ์‚ฐ์ถœ\n", + "# ์†Œ์…œ ๋ฏธ๋””์–ด ๋ฐ ํ…์ŠคํŠธ ๋ฌธ๋งฅ ๋ถ„์„์— ํŠนํ™”๋œ VADER ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์–ด์˜ ๊ทน์„ฑ ์ ์ˆ˜๋ฅผ ๊ตฌํ•˜๊ณ  ๋‹ค๊ฐ์  ๊ฐ์„ฑ ๊ตฌ์กฐ๋ฅผ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from nltk.sentiment.vader import SentimentIntensityAnalyzer\n", + "\n", + "# VADER ๊ฐ์„ฑ ๋ถ„์„๊ธฐ(SentimentIntensityAnalyzer) ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐ ์ธ์Šคํ„ด์Šคํ™”\n", + "senti_analyzer = SentimentIntensityAnalyzer()\n", + "\n", + "# ์ฒซ ๋ฒˆ์งธ ์˜ํ™” ๋ฆฌ๋ทฐ ํ…์ŠคํŠธ ์›๋ฌธ์„ ์ž…๋ ฅํ•˜์—ฌ ๊ฐ์„ฑ ๊ทน์„ฑ ์ ์ˆ˜(Polarity Scores) ๊ณ„์‚ฐ\n", + "senti_scores = senti_analyzer.polarity_scores(review_df['review'][0])\n", + "\n", + "# ๊ณ„์‚ฐ๋œ ์„ธ๋ถ€ ๊ฐ์„ฑ ์ง€์ˆ˜(๊ธ์ •/๋ถ€์ •/์ค‘๋ฆฝ/๋ณตํ•ฉ ์Šค์ฝ”์–ด) ๋”•์…”๋„ˆ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜์—ฌ ๊ตฌ์กฐ ํ™•์ธ\n", + "print(senti_scores)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "k4Lonht9hqCJ", + "outputId": "a6c9351f-7e56-4db5-f97d-be7668a9d4fb" + }, + "execution_count": 31, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "{'neg': 0.13, 'neu': 0.743, 'pos': 0.127, 'compound': -0.7943}\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# 17. VADER ๊ธฐ๋ฐ˜ ๋ฌธ์„œ ๊ฐ์„ฑ ๊ทน์„ฑ(Polarity) ๋ถ„๋ฅ˜ ํ•จ์ˆ˜ ๊ตฌํ˜„ ๋ฐ ์ตœ์ข… ์„ฑ๋Šฅ ๊ฒ€์ฆ\n", + "# ์ž„๊ณ„๊ฐ’(Threshold) ์„ค์ •์„ ํ†ตํ•ด ๋ณตํ•ฉ ๊ฐ์„ฑ ์ง€์ˆ˜์ธ compound ์Šค์ฝ”์–ด๋ฅผ 0(๋ถ€์ •) ๋˜๋Š” 1(๊ธ์ •)๋กœ ์ด์ง„ ๋ถ„๋ฅ˜ํ•˜๊ณ  ์ตœ์ข… ํ‰๊ฐ€์ง€ํ‘œ๋ฅผ ์—ฐ์‚ฐํ•ฉ๋‹ˆ๋‹ค.\n", + "\n", + "from sklearn.metrics import accuracy_score, confusion_matrix, precision_score\n", + "from sklearn.metrics import recall_score, f1_score, roc_auc_score\n", + "import numpy as np\n", + "\n", + "# ๋ฆฌ๋ทฐ ํ…์ŠคํŠธ์™€ ์ž„๊ณ„๊ฐ’์„ ์ž…๋ ฅ๋ฐ›์•„ VADER ๊ฐ์„ฑ ๊ทน์„ฑ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ•จ์ˆ˜ ์ƒ์„ฑ\n", + "def vader_polarity(review, threshold=0.1):\n", + " analyzer = SentimentIntensityAnalyzer()\n", + " scores = analyzer.polarity_scores(review)\n", + "\n", + " # ๋ณตํ•ฉ ๊ฐ์„ฑ ์ง€์ˆ˜์ธ compound ๊ฐ’์— ๊ธฐ๋ฐ˜ํ•ด threshold ์ž…๋ ฅ๊ฐ’๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์œผ๋ฉด 1, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด 0 ๋ฐ˜ํ™˜\n", + " agg_score = scores['compound']\n", + " final_sentiment = 1 if agg_score >= threshold else 0\n", + " return final_sentiment\n", + "\n", + "# apply lambda ์‹์„ ์ด์šฉํ•˜์—ฌ ๋ ˆ์ฝ”๋“œ๋ณ„๋กœ vader_polarity()๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ 'vader_preds' ์ปฌ๋Ÿผ์— ์ €์žฅ\n", + "review_df['vader_preds'] = review_df['review'].apply(lambda x : vader_polarity(x, 0.1))\n", + "\n", + "# ์„ฑ๋Šฅ ํ‰๊ฐ€ ๋น„๊ต๋ฅผ ์œ„ํ•ด ์‹ค์ œ ์ •๋‹ต ๋ ˆ์ด๋ธ”๊ณผ VADER ์˜ˆ์ธก๊ฐ’ ๋ฐฐ์—ด์„ ๊ฐ๊ฐ ์ถ”์ถœ\n", + "y_target = review_df['sentiment'].values\n", + "vader_preds = review_df['vader_preds'].values\n", + "\n", + "# VADER ๋ชจ๋ธ์˜ ์˜ค์ฐจ ํ–‰๋ ฌ(Confusion Matrix) ๊ตฌ์กฐ ์ถœ๋ ฅ\n", + "print(confusion_matrix(y_target, vader_preds))\n", + "\n", + "# ์ตœ์ข… ๋ถ„๋ฅ˜ ๋ชจ๋ธ ํ•ต์‹ฌ ์„ฑ๋Šฅ ์ง€ํ‘œ(์ •ํ™•๋„, ์ •๋ฐ€๋„, ์žฌํ˜„์œจ)๋ฅผ ๋ฐ˜์˜ฌ๋ฆผํ•˜์—ฌ ์ถœ๋ ฅ ๋ฐ ํ™•์ธ\n", + "print(\"์ •ํ™•๋„:\", np.round(accuracy_score(y_target, vader_preds), 4))\n", + "print(\"์ •๋ฐ€๋„:\", np.round(precision_score(y_target, vader_preds), 4))\n", + "print(\"์žฌํ˜„์œจ:\", np.round(recall_score(y_target, vader_preds), 4))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "OOYKJNjeh8ad", + "outputId": "489e42ac-34c3-454a-e5f2-8c5111ebc519" + }, + "execution_count": 32, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[[3742 3188]\n", + " [ 993 6000]]\n", + "์ •ํ™•๋„: 0.6997\n", + "์ •๋ฐ€๋„: 0.653\n", + "์žฌํ˜„์œจ: 0.858\n" + ] + } + ] + } + ] +} \ No newline at end of file