1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# -*- coding: utf-8 -*-
"""Day 10_logistic_regression_Sentiment_Analysis.ipynb
Automatically generated by Colaboratory.
Original file is located at
"""
 
from google.colab import drive
drive.mount('/gdrive')
 
PATH = "/gdrive/My Drive/Colab Notebooks/resources/"
 
# Standard includes
# %matplotlib inline
import numpy as np
import string
import matplotlib
import matplotlib.pyplot as plt
 
# Routines for linear regression
from sklearn import linear_model
from sklearn.metrics import mean_squared_error
 
# Set label size for plots
matplotlib.rc('xtick', labelsize=14
matplotlib.rc('ytick', labelsize=14)
 
# installing packages for interactive graphs
import ipywidgets as widgets
from IPython.display import display
from ipywidgets import interact, interactive, fixed, interact_manual, IntSlider
 
##데이터 로드
with open (PATH + "sentiment-logistic-regression/sentiment_labelled_sentences/"'full_set.txt') as f:
    content = f.readlines()
    
content = [x.strip() for x in content ]
 
## 라벨과 문장으로 분리
sentences = [ x.split("\t")[0for x in content ]
labels    = [ x.split("\t")[1for x in content ]
 
## 타겟 클래스를 0, 1에서 -1과 1로 변경
= np.array(labels, dtype='int8')
= 2*- 1
 
################################
############ 전처리 #############
###############################
 
 
## 지우고자 하는 문자 리스트를 받아서 x에서 지우는 함수.
def full_remove(x, removal_list):
    for w in removal_list:
        x = x.replace(w, ' ')
    return x
 
## 숫자 제거
digits = [str(x) for x in range(10)]
digit_less = [full_remove(x, digits) for x in sentences]
 
## 특수문자 제거
punc_less = [full_remove(x, list(string.punctuation)) for x in digit_less]
 
## 소문자로 변경
sents_lower = [x.lower() for x in punc_less]
 
## 불용어 정의
stop_set = set(['the''a''an''i''he''she''they''to''of''it''from'])
 
## 불용어 제거
 
## 공백으로 분리
sents_split = [x.split() for x in sents_lower]
 
## 불용어에 없는 단어만 띄워쓰기로 재결합 
sents_processed = [" ".join(list(filter(lambda a: a not in stop_set, x))) for x in sents_split]
 
## 불용어가 날아간 문장들
sents_processed[0:10]
 
from sklearn.feature_extraction.text import CountVectorizer
 
## bag of words ( Term frequency ) 만들기
vectorizer = CountVectorizer(analyzer = "word", tokenizer = None, preprocessor = None, stop_words = None, max_features = 4500)
data_features = vectorizer.fit_transform(sents_processed)
 
## 첫 250개 에는 y가 -1인값들의 인덱스가, 다음 250개에는 y가 1인 값들의 인덱스가 들어간다.
test_inds = np.append(np.random.choice((np.where(y==-1))[0], 250, replace=False),
                      np.random.choice((np.where(y==1))[0], 250, replace=False))
 
## 처음 뽑은 500개를 제외한 나머지의 인덱스가 들어가게 된다.
train_inds = list(set(range(len(labels))) - set(test_inds))
 
train_data = data_mat[train_inds,]
train_labels = y[train_inds]
 
test_data = data_mat[test_inds,]
test_labels = y[test_inds]
 
print("train data: ", train_data.shape)
print("test data: ", test_data.shape)
 
from sklearn.linear_model import SGDClassifier
 
## 모델 피팅. 손실함수에는 로그를 적용하고 regularizer를 사용하지 않는다.
clf = SGDClassifier(loss="log", penalty="none", )
clf.fit(train_data, train_labels)
 
## Linear Function으로부터 피처들의 가중치 w와 bias를 추출한다.
= clf.coef_[0, :]
= clf.intercept_
 
## 트레이닝셋과 테스트셋으로부터 예측결과를 받는다.
preds_train = clf.predict(train_data)
preds_test = clf.predict(test_data)
 
 
## 에러를 계산한다.
errs_train = np.sum((preds_train > 0.0!= (train_labels > 0.0))
errs_test = np.sum((preds_test > 0.0!= (test_labels > 0.0))
 
print ("Training error: ", float(errs_train)/len(train_labels)) 
print ("Test error: ", float(errs_test)/len(test_labels))
 
## 0.5로부터 감마만큼 떨어져 있는 포인트들만 다시 리턴한다. 즉 0.5 주변에 있는 확률이 애매한 포인트들은 제외하고
## 확실히 분류될수 있는 포인트 들만 리턴한다.
def margin_counts(clf, test_data, gamma):
    
    ## Compute probability on each test point
    preds = clf.predict_proba(test_data)[:,1]
    
    ## Find data points for which prediction is at least gamma away from 0.5
    margin_inds = np.where((preds > (0.5+gamma)) | (preds < (0.5-gamma)))[0]
    
    return float(len(margin_inds))
 
## 각 마진별 해당되는 요소의 갯수를 시각화
 
gammas = np.arange(0,0.5,0.01)
= np.vectorize(lambda g: margin_counts(clf, test_data, g))
plt.plot(gammas, f(gammas)/500.0, linewidth=2, color='green')
plt.xlabel('Margin', fontsize=14)
plt.ylabel('Fraction of points above margin', fontsize=14)
plt.show()
 
def margin_errors(clf, test_data, test_labels, gamma):
    
    ##각 테스트 포인트에서 1번으로 분류될 확률만 500행의 배열로 리턴한다.
    preds = clf.predict_proba(test_data)[:,1]
    
    ## 해당 조건을 만족하는 배열의 인덱스가 길이가 1인 튜플로 리턴된다.
    margin_inds = np.where((preds > (0.5+gamma)) | (preds < (0.5-gamma)))[0]
    
    ## 에러 검증. preds안에서 1로 분류된것들이 test_label에서 1로 분류가 안되었다면 에러로 취급한다
    num_errors = np.sum((preds[margin_inds] > 0.5!= (test_labels[margin_inds] > 0.0))
    
    return float(num_errors)/len(margin_inds)
 
## 마진 조정 범위
gammas = np.arange(00.50.01)
 
## g값에 따른 에러율 측정함수
= np.vectorize(lambda g: margin_errors(clf, test_data, test_labels, g))
 
## 시각화
plt.plot(gammas, f(gammas), linewidth=2)
plt.ylabel('Error rate', fontsize=14)
plt.xlabel('Margin', fontsize=14)
plt.show()
cs



출처 및 참고자료 : edx -  Machine Learning Fundamentals_week_4 Programming Assignment.1

+ Recent posts