<jupyter_start><jupyter_text>기말고사 대비용 Jupyter Notebook<jupyter_code>!pip install konlpy
import nltk
import re
import random
nltk.download('book')
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('gutenberg')
nltk.download('words')
from nltk.book import *
from nltk.corpus import brown
from nltk.corpus import stopwords
from nltk.corpus import gutenberg
from nltk.corpus import inaugural
from nltk.corpus import PlaintextCorpusReader
from nltk.corpus.reader.plaintext import CategorizedPlaintextCorpusReader
names = nltk.corpus.names
from nltk.corpus import movie_reviews
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/MyDrive/CSW4020<jupyter_output>Mounted at /content/drive
/content/drive/MyDrive/CSW4020<jupyter_text>정보처리및자연어처리 2차과제> 20161482 박준용<jupyter_code>import nltk
from nltk.corpus import PlaintextCorpusReader
from nltk.corpus.reader.plaintext import CategorizedPlaintextCorpusReader
import re<jupyter_output><empty_output><jupyter_text>1번: 배점 5점다음을 수행하여 변수 tagged_paragraphs 를 만드시오. 1. data.txt 불러오기2. 본문 영역 (`````` … ``````) 내 문단 단위 (``````… ``````)로 구분 된 어절과 형태분석 쌍의 튜플을 원소로 하는 리스트 구성*   tagged_paragraphs = [[문단1] , [문단2], [문단3], ….]*   각 문단 = [(어절1, 형태분석1), (어절2, 형태분석2), …]<jupyter_code># 1번
data = open('./data.txt', encoding = 'utf-8').read()
body = re.search('<body.*/body>', data, re.I|re.S).group()
p = re.findall('<p.*?/p>', body, re.I|re.S)
tagged_paragraphs = []
for i in range(0, len(p)):
    temp1 = re.findall(r'\t(.*?)\n',p[i])
    temp2 = [tuple(re.split(r'\t+', w)) for w in temp1]
    tagged_paragraphs.append(temp2)
print(tagged_paragraphs[2:3])
len(tagged_paragraphs)
type(tagged_paragraphs)
import pickle
answer1 = pickle.load(open('answer1.pkl','rb'))
tagged_paragraphs == answer1<jupyter_output><empty_output><jupyter_text>2번: 배점 2점다음을 수행하는 일련의 코드를 제시하시오. 1. 문제 1번의 변수 tagged_paragraphs로부터 전체 문단 중 90%(앞부분) 문단을 변수 train으로(training data), 나머지 10%(뒷부분) 문단을 변수 test로(test data) 만들기2. 변수 train(training data)을 이용하여 unigram tagger, bigram tagger, trigram tagger로 구성된 combining tagger 만들고 변수는 combining_tagger로 설정(default tagger는 포함하지 않음)3. 변수 test (test data)을 이용하여 combining tagger 변수 combining_tagger의 정확도를 측정하시오.<jupyter_code># 2번
size = int(len(tagged_paragraphs)*0.9)
train_sents = tagged_paragraphs[:size]
test_sents = tagged_paragraphs[size:]
t1 = nltk.UnigramTagger(train_sents)
t2 = nltk.BigramTagger(train_sents, backoff = t1)
combining_tagger = nltk.TrigramTagger(train_sents, backoff = t2)
combining_tagger.evaluate(test_sents)<jupyter_output><empty_output><jupyter_text>3번: 배점 1점문제 2번의 변수 test로부터 어절만 순서대로 추출한 변수 test_words 를 만드시오.(반드시 네모칸에 들어갈 한 줄 코드로 작성하시오)<jupyter_code># 3번
test_words = [j[0] for i in test_sents for j in i]
print(test_words[:20])
print(test_words[-20:])
len(test_words)<jupyter_output><empty_output><jupyter_text>4번: 배점 2점위쪽 그림으로부터 아래 그림을 도출할 수 있는 함수 defaultNNG 네모칸에 들어갈 한 줄 코드로 작성하시오. (None ⇒ ‘어휘/NNG’)<jupyter_code># 4번
print(combining_tagger.tag(test_words[:10]))
def defaultNNG(x):
    return([(j[0],j[0]+'/NNG') if j[1] is None else j for j in x])
print(defaultNNG(combining_tagger.tag(test_words[:10])))<jupyter_output>[('내', '나/NP + 의/JKG'), ('계산은', '계산/NNG + 은/JX'), ('들어맞았다.', '들어맞았다./NNG'), ('나는', '나/NP + 는/JX'), ('우리', '우리/NP'), ('가족들이', '가족/NNG + 들/XSN + 이/JKS'), ('마음으로는', '마음으로는/NNG'), ('다들', '다들/NNG'), ('원하면서도', '원하면서도/NNG'), ('선뜻', '선뜻/NNG')]<jupyter_text>2019년 기말고사<jupyter_code>#5번
import re, os, nltk
a = os.listdir('./11_data')
a
len(a)
#6번
b = [open('./11_data/'+a[7]).read()]
b[0][:100]
#7번
c = [w for w in nltk.word_tokenize(b[0])]
print(c[:21])
#8번
d = nltk.pos_tag(c)
print(d[:21])
#9번
e = list(nltk.bigrams(d))
e[:10]
#10번
f = nltk.ConditionalFreqDist((b,a[1]) for (a,b) in e)
f[('far', 'RB')]
#11번
g = [(k,v) for k,v in f.items()]
g[:5]
#12번
h = [(wt, F.max()) for (wt,F) in g]
h[:5]
#13번
def y(x):
    x = x.lower()
    features = {}
    for i in 'aeiou':
        features[f'count({i})'] = x.count(i)
    return features
y('seagUll')
labeled_names = [(name, file.replace('.txt', ''))
                for file in names.fileids()
                for name in names.words(file)]
featuresets = [(y(n), gender) for (n,gender) in labeled_names]
featuresets[:2]
#14번
z = nltk.NaiveBayesClassifier.train(featuresets)
z.classify(y("Trinity"))<jupyter_output><empty_output><jupyter_text>기타 이론사항  NLTK_ RawText처리 ASCII문자 코드: 컴퓨터에서 각 문자를 대응하는 코드 체계미국 정보교환 표준부호, 영문 알파벳 문자 인코딩, 8bit 이진수 연쇄를 통한 알파벳, 문장부호, 제어문자 부호화한글 코드조합형 코드* 16bit = MSB + 초(5) + 중(5) + 종(5)* 음절 모두 표현 가능완성형 코드* 16bit, 미리 정의된 문자 이외는 사용 불가능* EUC-KR (기본 완성형) ~ 20%만 사용* cp949 (확장 완성형)Unicode전세계 문자를 하나의 코드 체계로 표준화한 문자코드세트 (한자, 한글, ASCII, 기호 등등) ex) UTF-8* EUC-KR의 경우 코드번호순서와 사전 정렬순서 일치, cp949는 아님* unicode는 한글 음절문자 11,172개를 사전정렬순에 의해 코드번호 부여Tokenization어휘 단위 분리, 소문자변환, 소유격 제거, 문장부호/숫자 분리/제거 등* 대문자가 필요할 때* 특수문자가 사용된 단어분포 가설같은 contexts 내에서 발생하고 사용되어지는 단어들은 같은 의미를 말하고 있는 경향이 있다. 전산언어학, 인지과학 등에서 어휘 의미를 접근하는 토대연어(collocation)동일 문장, 동일 맥락에서 빈번하게 함께 사용되는 어휘쌍두 어휘의 습득은 대부분 함께 습득* 특정 맥락, 주제와 관련* 문화적 맥락과 관련 * 머릿속 사전에서 연관친숙성/빈도 효과, 촉발효과와 관련 있다.   NLTK_영어어휘품사분석 **자연어 처리의 어휘처리의 중요성*** 어휘: 기본적 의미 단위* 어휘는 형식적 식별의 용이성 보유형태소* 형태소: 의미의 최소 단위 ex) prefix, suffix* 독립 형태소/의존 형태소 etc.어근, 어간* 어휘 = 어근 + 접사 ex) **paint**er, con**cieve*** 어간 = 굴절 접사 등등파생 형태소* 굴절 형태소: 품사 변화 X* but 파생 형태소: 품사 변화 O (pure -> pur**ify**)내용어와 기능어* 내용어: 의미 내용을 가짐 (ex: n. v. open class)* 기능어: 문법 기능 (conj. prep. pron. closed class)* 문법 형태소: 양화, 형식, 시제 등등...* nltk Text에서 findall 기능을 적용 가능* string: findall 기능 적용 불가능 (re.findall 사용)* 그러나  각괄호 사용 불가**Tokenization의 필요성*** 문자변환, 문장부호, 숫자제거 등등...* 형태론적 표준화 (stemming/lemmatization) 역시 포함* **nltk.word_tokenize(text)**Stemming* 굴절접사의 제거 (ex: cars->car, but supplies->supplie)* nltk.PorterStemmer() / LancasterStemmer()Lemmatization* 어간의 사전 표제형 (lemma) 추출 - 형태소분석 要* nltk.WordNetLemmatizer()굴절어와 교착어* 굴절어: 품사분석, PoS (형태론적 복잡성 낮음) ex) 영어* 교착어: morphological tag ex) 한국어**영어 POS*** 형태적, 통사적 기능에 근거한 정의* close class / open classbi-gram* list(nltk.bigrams(words))**tagger*** 빈도와 중의성: can (cans/canned/can't)* rule-based(regex), stochastic, hybird* tagger 함수: **nltk.pos_tag(text)**, nltk.DefaultTagger('NN'), nltk.RegexpTagger(patterns)* pickle 등으로 저장 및 불러오기 가능.Unigram Tagger* 모든 어휘 목록에서 높은 확률, 자체 training* Trigram으로 갈수록 중의성 제거 확률 높아짐.Combining tagger* Trigram have ```None?``` -> bi -> uni -> default..* tagger에 따라 정확도 떨어질 수 있음, 저빈도 cutoff  NLTK_분류 **기계학습의 종류*** **Supervised ML*** training data의 입출력쌍 학습* 분류 회귀모형 (현 nltk 모델)* **Unsupervised ML*** 입력만 있고 출력은 없는 경우, 패턴 탐색* Clustering, AssociationSupervised ML 과정* 입출력쌍 mapping (feature extract) - 학습* label(정답) - classifier model 예측어떤 모형을 선택하고 적절한 Feature를 추출하는 것이 중요하다. 연습문제  NLTK_영어어휘품사분석--- 영어어휘품사분석I (연습문제 1)<jupyter_code>def stem1(word):
    for suffix in ['ing', 'ed','s']:
        if word.endswith(suffix):
            return(word[:-len(suffix)])
    return word
def stem2(word):
    return re.sub('(ing|ed|s)$','',word)<jupyter_output><empty_output><jupyter_text>영어어휘품사분석III (연습문제 1, 2)해당 Chapter에서 tabulate, ConditionalFreqDist, [링크 텍스트](https://)n-gram 활용 관련 예제 참조<jupyter_code>words = nltk.corpus.brown.tagged_words(categories='news', tagset='universal')
words[:5]
verbs = [x[0] for x in nltk.FreqDist(w for w,t in words if t == 'VERB').most_common()][:10]
print(verbs)
noun_modifiers = [x[1] for x,b in nltk.bigrams(words) if b[1] == 'NOUN']
noun_modifiers = [tag for (tag,_) in nltk.FreqDist(noun_modifiers).most_common()]
print(noun_modifiers)
cfd1 = nltk.ConditionalFreqDist(words)
cfd1['yield'].most_common() #dictionary임<jupyter_output><empty_output><jupyter_text>영어어휘품사분석IV, V (Practice)<jupyter_code>fd = nltk.FreqDist(brown.words(categories='news'))
cfd = nltk.ConditionalFreqDist(brown.tagged_words(categories='news'))
cfd['the']
likely_tags = dict((word, cfd[word].max())
        for (word,_) in fd.most_common(50))
tagged_sents = list(brown.tagged_sents(categories='news'))
random.shuffle(tagged_sents)
precision = [nltk.UnigramTagger(model=dict((word, cfd[word].max()) 
            for (word, _) in fd.most_common(i))).evaluate(tagged_sents) 
            for i in range(100, len(fd.most_common()), 100)] #고빈도 어휘를 얼마만큼 사용하는지?<jupyter_output><empty_output><jupyter_text>KoNLPy (연습문제 1)<jupyter_code>from konlpy.tag import Kkma
kkma = Kkma()
a = os.getcwd()
b = os.listdir('./15_data')
tagged = [j for i in b 
          for j in kkma.pos(open('/'.join([a, '15_data', i]), encoding='utf8').read())]
len(tagged)
print(tagged[:10])<jupyter_output>[('북미', 'NNG'), ('양국', 'NNG'), ('이', 'JKS'), ('3', 'NR'), ('일', 'NNM'), ('오후', 'NNG'), ('판문점', 'NNG'), ('에서', 'JKM'), ('12', 'NR'), ('일', 'NNM')]<jupyter_text>한글자소처리 (연습문제 1)<jupyter_code>ord('힣')-ord('가')
[chr(i) for i in range(44032, 44042)]
def test1(a, b):
    suffix = jaso1(b)[0]
    stem = jaso1(a[-1])[-1]
    if stem != '':
        if suffix == 'ㅇ':
            return '결합가능'
        else:
            return '결합불가'
    else:
        if suffix != 'ㅇ':
            return '결합가능'
        else:
            return '결합불가'
test1('사과','이')
def test2(x):
    import re
    final = jaso2(x[-1])
    if re.search('ㄴ$|ㄹ$',final[-1]):
        stemming = final[:-1]+['']
        return(x[:-1] + jaso1(*stemming))
    else:
        return(x)
test2("사관")<jupyter_output><empty_output><jupyter_text>NLTK_분류---<jupyter_code>labeled_names = [(name, file.replace('.txt', ''))
                for file in names.fileids()
                for name in names.words(file)]
random.shuffle(labeled_names)
features = [({'last_letter': name[-1]}, gender) for (name,gender) in labeled_names]
train_set, test_set = features[:500], features[:500]
classifier = nltk.NaiveBayesClassifier.train(train_set)
nltk.classify.accuracy(classifier, test_set)
classifier.show_most_informative_features()
classifier.classify({'last_letter': 'e'})<jupyter_output><empty_output><jupyter_text>**분류 I** (연습문제 1, 2 ,3)<jupyter_code>labeled_names = [(name, file.replace('.txt', ''))
                for file in names.fileids()
                for name in names.words(file)]
random.shuffle(labeled_names)
len(labeled_names)
labeled_names[:10]
features = [({'first_letter': name[0].lower()}, {'last_letter': name[-1]}, {'name_length': len(name)}, gender) for (name,gender) in labeled_names]
features[:5]
size = int(len(features) *0.9)
def gender_features1(name):
    features = {}
    features['name_length'] = len(name)
    features["first_letter"] = name[0].lower()
    features["last_letter"] = name[-1].lower()
    return features
features = [(gender_features1(name), gender) for name, gender in labeled_names]
size = int(len(features) *0.9)
train_set, test_set = features[:size], features[size:]
classifier = nltk.NaiveBayesClassifier.train(train_set)
nltk.classify.accuracy(classifier, test_set)
classifier.show_most_informative_features(20)
classifier.classify(gender_features1('John'))<jupyter_output><empty_output><jupyter_text>**분류 II** (연습문제 1, 2)<jupyter_code>train_names = labeled_names[1500:]
devtest_names = labeled_names[500:1500]
test_names = labeled_names[:500]
def gender_features_ex(name):
    features = {}
    features["last_two_letters"] = name[-2:].lower()
    features["last_letter"] = name[-1:].lower()
    return features 
train_set = [(gender_features_ex(n), gender) for (n, gender) in train_names]
devtest_set = [(gender_features_ex(n), gender) for (n, gender) in devtest_names]
test_set = [(gender_features_ex(n), gender) for (n, gender) in test_names]
classifier = nltk.NaiveBayesClassifier.train(train_set)
nltk.classify.accuracy(classifier, devtest_set)
nltk.classify.accuracy(classifier, test_set)
def gender_features(word):
    return {'suffix1': word[-1], 'suffix2':word[-2]}
train_set = [(gender_features(n), gender) for (n, gender) in train_names]
devtest_set = [(gender_features(n), gender) for (n, gender) in devtest_names]
test_set = [(gender_features(n), gender) for (n, gender) in test_names]
classifier = nltk.NaiveBayesClassifier.train(train_set)
nltk.classify.accuracy(classifier, devtest_set)
nltk.classify.accuracy(classifier, test_set)<jupyter_output><empty_output><jupyter_text>NLTK_분류 III (연습문제 1, 2, 3)<jupyter_code>all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
word_features = list(all_words)[:1000] #일반적인 형태를 feature extraction하기 쉬움
def document_features(document):
    document_words = set(document)
    features = {}
    for word in word_features:
        features[f'contains({word})'] = word in document_words
    return features 
featuresets = [(document_features(d), c) for (d,c) in documents]
train_set, test_set = featuresets[100:], featuresets[:100]
classifier = nltk.NaiveBayesClassifier.train(train_set)
nltk.classify.accuracy(classifier,test_set)
classifier.show_most_informative_features(5) 
def document_features(document):
    document_words = set(document)
    features = {}
    word_features = ['stretched', 'turkey', 'singers','unravel', 'awful', 'wasted']
    for word in word_features:
        features[f'contains({word})'] = word in document_words
    return features 
featuresets = [(document_features(d), c) for (d,c) in documents]
train_set, test_set = featuresets[100:], featuresets[:100]
classifier = nltk.NaiveBayesClassifier.train(train_set)
nltk.classify.accuracy(classifier,test_set)
def document_features(document):
    import re
    letters = ''.join(document)
    features = {
        'ratio_alphabet': len(re.findall('[a-z]', letters, re.I))/len(letters),
        'ratio_digit': len(re.findall('\d', letters))/len(letters),
        'ratio_punct': len(re.findall('[^\w]', letters))/len(letters)
    }
    return features 
featuresets = [(document_features(d), c) for (d,c) in documents]
train_set, test_set = featuresets[100:], featuresets[:100]
classifier = nltk.NaiveBayesClassifier.train(train_set)
nltk.classify.accuracy(classifier,test_set)
classifier.show_most_informative_features(5)<jupyter_output>Most Informative Features
             ratio_digit = 0.0026666666666666666    pos : neg    =      1.7 : 1.0
          ratio_alphabet = 0.9523809523809523    neg : pos    =      1.7 : 1.0
          ratio_alphabet = 0.9583333333333334    neg : pos    =      1.7 : 1.0
             ratio_punct = 0.03959731543624161    neg : pos    =      1.7 : 1.0
             ratio_digit = 0.0032502708559046588    neg : pos    =      1.7 : 1.0<jupyter_text>NLTK_분류 IV (연습문제 1, 2, 3)<jupyter_code>suffix_fdist = nltk.FreqDist()
for word in brown.words():
    word = word.lower()
    suffix_fdist[word[-1:]] += 1 #Unigram 빈도
    suffix_fdist[word[-2:]] += 1 #Bigram 빈도
    suffix_fdist[word[-3:]] += 1 #Trigram 빈도
common_suffixes = [suffix for (suffix, count) in suffix_fdist.most_common(100)]
common_suffixes[:10]
#문자길이 1, 2 등일 경우 중복 count가 될 때 정확도가 낮아질 수 있다. 
suffix_fdist = nltk.FreqDist()
for word in ['','a','ab','abc']:
    word = word.lower()
    if len(word) != 0:
        suffix_fdist[word[-1:]] += 1
    if len(word) > 1:
        suffix_fdist[word[-2:]] += 1 
    if len(word) > 2:
        suffix_fdist[word[-3:]] += 1   
suffix_fdist
errors_Naive =[]
for (word,tag) in tagged_words[-1000:]:
    guess = classifier.classify(pos_features(word))
    guess1 = classifier1.classify(pos_features(word))
    if guess != tag and guess1 == tag: 
        errors_Naive.append((word,tag,guess,guess1))
errors_Naive[:10]
errors_Decision =[]
for (word,tag) in tagged_words[-1000:]:
    guess = classifier.classify(pos_features(word))
    guess1 = classifier1.classify(pos_features(word))
    if guess == tag and guess1 != tag: 
        errors_Decision.append((word,tag,guess,guess1))
errors_Decision[:10]<jupyter_output><empty_output><jupyter_text>NLTK_감성분석--- Movie Review<jupyter_code>all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
word_features = list(all_words)[:1000]
print(word_features[:100])
print(nltk.corpus.stopwords.words('english'[:50]))
len(word_features)
word_ranking = set(word_features) - set(nltk.corpus.stopwords.words('english'))
len(word_ranking)
word_ranking = sorted(word_ranking)
print(word_ranking[:40])
import re
word_ranking = [i for i in word_ranking if re.search('[a-z]', i)]
len(word_ranking)
documents = [(list(movie_reviews.words(fileid)), category) 
            for category in movie_reviews.categories() 
            for fileid in movie_reviews.fileids(category)]
random.shuffle(documents)
def document_features(document):
    document_words = set(document)
    features = {}
    for word in word_features:
        features[f'contains({word})'] = word in document_words
    return features 
featuresets = [(document_features(d), c) for (d,c) in documents]
train_set, test_set = featuresets[100:], featuresets[:100]
classifier = nltk.NaiveBayesClassifier.train(train_set)
nltk.classify.accuracy(classifier, test_set)
classifier.show_most_informative_features(15)
negative = movie_reviews.words(categories='neg')
positive = movie_reviews.words(categories='pos')
A = {word for word,_ in nltk.FreqDist(w.lower() for w in negative).most_common(1000)}
B = {word for word,_ in nltk.FreqDist(w.lower() for w in positive).most_common(1000)}
XOR = A^B 
len(XOR) #매우 줄어듬-Stopword 방식 이외에도 사용 방법에 따라 이득을 볼 수 있음
XOR = sorted(XOR)
print(XOR[:80])
positive_words = B-A
negative_words = A-B
print(sorted(positive_words)[:40])
print(sorted(negative_words)[:40])
def value_of (word):
    if word in positive_words:
        return 1
    elif word in negative_words:
        return -1
    return 0
def sentiment_score(document):
    return(sum(value_of(word) for word in document))
sentiment_score(movie_reviews.words(
    random.sample(
        movie_reviews.fileids(categories='neg'), 1)))
sum(sentiment_score(movie_reviews.words(fileid)) 
    for fileid in movie_reviews.fileids(categories='neg'))<jupyter_output><empty_output><jupyter_text>VADER Sentiment Analysis Tool<jupyter_code>nltk.download('vader_lexicon')
from nltk.sentiment import SentimentIntensityAnalyzer
sia = SentimentIntensityAnalyzer()
sia.polarity_scores("Wow, NLTK is really powerful!!") #dict type
sia.polarity_scores(movie_reviews.raw(random.sample(movie_reviews.fileids(categories='pos'), 1))) 
sum(sia.polarity_scores(movie_reviews.raw(fileid))['compound']
    for fileid in movie_reviews.fileids(categories='neg'))/len(movie_reviews.fileids(categories='neg'))
sum(sia.polarity_scores(movie_reviews.raw(fileid))['compound']
    for fileid in movie_reviews.fileids(categories='pos'))/len(movie_reviews.fileids(categories='pos'))
nltk.download('twitter_samples')
from nltk.corpus import twitter_samples
all_positive_tweets = twitter_samples.strings('positive_tweets.json')
all_negative_tweets = twitter_samples.strings('negative_tweets.json')
all_positive_tweets[:2]
sia.polarity_scores(random.sample(all_positive_tweets, 1)[0]) 
sia.polarity_scores(random.sample(all_negative_tweets, 1)[0])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15289145669501952, 'fraction_numerical': 0.025143101695821967, 'mean_word_length': 5.117146596858639, 'pattern_counts': {'":': 0, '<': 75, '<?xml version=': 0, '>': 84, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 7, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '628350', 'license': 'MIT', 'n_tokens_mistral': 8771, 'n_tokens_neox': 9426, 'n_words': 1608, 'path': 'CSW4020_Final.ipynb', 'repo_name': 'jyjoon001/CSW4020', 'size': '18693'}