{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# **NLP (Natural Language Processing) 분석**\n",
"**뉴스그룹 데이터 Set 분석**\n",
"1. 단어의 지식과 개념을 정리하는 작업으로 **Ontology** 같은 예들이 존재\n",
"1. 낮은 단계로는 **Tagging, POS(Part of Speech)** 이 있다\n",
"1. Python 라이브러리로 **NLTK, Gensim, TextBlob** 등이 있다"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"\n",
"## **1. NLP 개념 익히기**\n",
"\n",
"**NLTK 에서 자연어 분석 작업**\n",
"1. **Tokenization**(토큰화) : 텍스트를 공백문자로 구분하여 조각을 나누는 작업 (Document --> Ngram)\n",
"1. **POS Tagging**(품사태깅) : **Konlpy, NLTK** 에 규격화 된 Tagger를 적용하거나, **POS_TAG**와 같은 함수를 활용\n",
"1. **NER** (개체명 인식) : **Named entity Recognition** 은 텍스트 문장에서 명사를 식별하는 작업이다\n",
"1. **Stemming** (어간추출) : 어간, 어근의 **원형으로** 되돌리는 작업\n",
"1. **Lemmatization**(표제어 원형 복원) : 어간 추출보다 좁은 의미로써 **단어를 유효한 결과로** 출력하는 작업"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'machin'"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 어간의 추출\n",
"from nltk.stem.porter import PorterStemmer\n",
"porter_stemmer = PorterStemmer()\n",
"porter_stemmer.stem('machines')"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'machine'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Token 의 원형을 복구한다\n",
"from nltk.stem import WordNetLemmatizer\n",
"lemmatization = WordNetLemmatizer()\n",
"lemmatization.lemmatize('machines')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Gensim 에서의 자연어 분석 작업**\n",
"문장간 유사도 측정을 위해 2008년 시작된 모듈로써, 다양한 모델링이 가능하다\n",
"1. **Similarity Querying** (유사도 쿼리) : 주어긴 쿼리 객체와 유사한 객체를 검색\n",
"1. **Word vectorization** (단어 벡터화) : 단어의 동시출현 Feacture를 유지하면서 단어를 표현\n",
"1. **Distribution Computing** (분산 컴퓨팅) : 다수의 문서를 효과적으로 학습\n",
"\n",
"### **Text Blob**\n",
"NLTK 기반의 라이브러리로 **맞춤법 확인 및 교정, 언어감지, 번역기능이** 추가"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"## **2. newsgroups 데이터 보기**\n",
"20개의 **News Group을** 대상으로 **11,313 개의** 뉴스 데이터가 담겨있다\n",
"### **01 News Group 데이터 살펴보기**\n",
"> **fetch_20newsgroups()**\n",
"\n",
"1. subset : 적제할 데이터를 정의한다\n",
"1. data_home : 파일을 저장할 폴더 ex) **~/scikit_learn_data**(초기값)\n",
"1. categories : 추출할 목록을 지정"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['alt.atheism',\n",
" 'comp.graphics',\n",
" 'comp.os.ms-windows.misc',\n",
" 'comp.sys.ibm.pc.hardware',\n",
" 'comp.sys.mac.hardware',\n",
" 'comp.windows.x',\n",
" 'misc.forsale',\n",
" 'rec.autos',\n",
" 'rec.motorcycles',\n",
" 'rec.sport.baseball',\n",
" 'rec.sport.hockey',\n",
" 'sci.crypt',\n",
" 'sci.electronics',\n",
" 'sci.med',\n",
" 'sci.space',\n",
" 'soc.religion.christian',\n",
" 'talk.politics.guns',\n",
" 'talk.politics.mideast',\n",
" 'talk.politics.misc',\n",
" 'talk.religion.misc']"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 뉴스 데이터를 가져온다 (약 14MB)\n",
"# 뉴스 그룹 0 ~ 19 (20개 목록)\n",
"from sklearn.datasets import fetch_20newsgroups\n",
"groups = fetch_20newsgroups(data_home='data/news/')\n",
"groups['target_names']"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"data : \n",
"filenames : \n",
"target_names : \n",
"target : \n",
"DESCR : \n"
]
},
{
"data": {
"text/plain": [
"dict_keys(['data', 'filenames', 'target_names', 'target', 'DESCR'])"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# groups Json 데이터 살펴보기\n",
"for key in groups.keys():\n",
" print(key, ':', type(groups[key]))\n",
"groups.keys()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[7 4 4 ... 3 1 8]\n"
]
},
{
"data": {
"text/plain": [
"array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,\n",
" 17, 18, 19])"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 뉴스그룹 Primary Key 값인 정수값 인코딩\n",
"# 정수들이 중복되지 않게 정리된 결과를 출력한다\n",
"import numpy as np\n",
"print(groups.target)\n",
"np.unique(groups.target)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **02 개별 News 데이터 살펴보기**\n",
"0 번 뉴스의 정보를 확인하기"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"News Group 포함된 자료갯수: 11,314 개\n",
"\n",
"0번 샘플보기: \n",
"From: lerxst@wam.umd.edu (where's my thing)\n",
"Subject: WHAT car is this!?\n",
"Nntp-Posting-Host: rac3.wam.umd.edu\n",
"Organization: University of Maryland, College Park\n",
"Lines: 15\n",
"\n",
" I was wondering if anyone out there could enlighten me on this car I saw\n",
"the other day. It was a 2-door sports car, looked to be from the late 60s/\n",
"early 70s. It was called a Bricklin. The doors were really small. In addition,\n",
"the front bumper was separate from the rest of the body. This is \n",
"all I know. If anyone can tellme a model name, engine specs, years\n",
"of production, where this car is made, history, or whatever info you\n",
"have on this funky looking car, please e-mail.\n",
"\n",
"Thanks,\n",
"- IL\n",
" ---- brought to you by your neighborhood Lerxst ----\n",
"\n",
"\n",
"\n",
"\n",
"\n"
]
}
],
"source": [
"# 해당 뉴스의 내용 살펴보기\n",
"print(\"News Group 포함된 자료갯수: {:,} 개\\n\\n0번 샘플보기: \\n{}\".format(\n",
" len(groups.data), groups.data[0]))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'rec.autos'"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 0번 뉴스의 해당 그룹 Category 확인\n",
"groups.target_names[groups.target[0]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **03 데이터 시각화**\n",
"1. Document를 분석하는 경우 **Bag of Words로써** (단어의 집합) 활용한다\n",
"1. **단어 모델링과** 어떠한 차이가 있는지를 확인해 본다\n",
"1. **총 20개 카테고리** 뉴스들을 Histogram으로 시각화 (비슷한 갯수로 모델이 분표)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/markbaum/Python/python/lib/python3.6/site-packages/matplotlib/axes/_axes.py:6521: MatplotlibDeprecationWarning: \n",
"The 'normed' kwarg was deprecated in Matplotlib 2.1 and will be removed in 3.1. Use 'density' instead.\n",
" alternative=\"'density'\", removal=\"3.1\")\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"