from sklearn.datasets import fetch_20newsgroups
news_data = fetch_20newsgroups(subset='all', random_state=156)
fetch_20newsgroups는 사이킷런에서 제공하는 함수 중 하나로, 다양한 기계학습 모델과 데이터셋 제공. => 그 중에서도 fetch_20_newsgroups는 20개의 다른 주제로 분류된 뉴스 그룹 데이터셋 들고온다. subset은 train, test로 설정해서 학습용, 테스트용 데이터 들고온다. all은 모두. print(news_data.keys())
news_data.target_names
news_data.target
import pandas as pd
print('target 클래스의 값과 분포도 \n', pd.Series(news_data.target).value_counts().
sort_index())
print('target 클래스의 이름들 \n', news_data.target_names)


#subset = train으로 학습용 데이터만 추출
train_news = fetch_20newsgroups(subset='train', remove=('headers', 'footers', 'quotes'), random_state = 156)
X_train = train_news.data
y_train = train_news.target
print(type(X_train))
test_news = fetch_20newsgroups(subset='test', remove=('headers', 'footers', 'quotes'), random_state = 156)
X_test = test_news.data
y_test = test_news.target
print('학습 데이터 크기 {0}, 테스트 데이터 크기 {1}'.format(len(train_news.data), len(test_news.data)))
remove 매개변수는 뉴스 그룹 데이터에서 제거할 요소 지정. 여기선 headers, footers, quotes 제거. => header는 이메일의 보내는 사람, 받는 사람 등 / footers는 이메일 끝의 회사 정보 등 / 인용구는 이메일 원문에서 다른 이의 이메일 인용하는 부분.
from sklearn.feature_extraction.text import CountVectorizer
cnt_vect = CountVectorizer()
cnt_vect.fit(X_train)
X_train_cnt_vect = cnt_vect.transform(X_train)
X_test_cnt_vect = cnt_vect.transform(X_test)
print('학습 데이터 Text의 CountVectorizer Shape:', X_train_cnt_vect.shape)
CountVectorizer(): 문서 집합에서 단어 토큰 생성하고, 각 단어의 수를 세서 단어 카운트 벡터를 생성. from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
lr_clf = LogisticRegression(solver='liblinear')
lr_clf.fit(X_train_cnt_vect, y_train)
pred = lr_clf.predict(X_test_cnt_vect)
print('CountVectorized Logistic Regression의 예측 정확도는 {0:.3f}'.format(accuracy_score(y_test, pred)))
solver='liblinear'는 최적화에 사용할 알고리즘. liblinear는 작은 규모 데이터셋에 대해 적합. 
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf_vect = TfidfVectorizer()
tfidf_vect.fit(X_train)
X_train_cnt_vect = tfidf_vect.transform(X_train)
X_test_cnt_vect = tfidf_vect.transform(X_test)
lr_clf = LogisticRegression(solver='liblinear')
lr_clf.fit(X_train_cnt_vect, y_train)
pred = lr_clf.predict(X_test_cnt_vect)
print('TF-IDF Logistic Regression의 예측 정확도는 {0:.3f}'.format(accuracy_score(y_test, pred)))

tfidf_vect = TfidfVectorizer(stop_words = 'english', ngram_range=(1,2), max_df = 300)
tfidf_vect.fit(X_train)
X_train_tfidf_vect = tfidf_vect.transform(X_train)
X_test_tfidf_vect = tfidf_vect.transform(X_test)
lr_clf = LogisticRegression(solver='liblinear')
lr_clf.fit(X_train_tfidf_vect, y_train)
pred = lr_clf.predict(X_test_cnt_vect)
print('TF-IDF Vectorized Logistic Regression의 예측 정확도는 {0:.3f}'.format(accuracy_score(y_test, pred)))

from sklearn.model_selection import GridSearchCV
# 최적 C 값 도출 튜닝 수행. CV는 3 Fold셋으로 설정.
params = { 'C':[0.01, 0.1, 1, 5, 10]}
grid_cv_lr = GridSearchCV(lr_clf ,param_grid=params , cv=3 , scoring='accuracy' , verbose=1 )
grid_cv_lr.fit(X_train_tfidf_vect , y_train)
print('Logistic Regression best C parameter :',grid_cv_lr.best_params_ )
# 최적 C 값으로 학습된 grid_cv로 예측 수행하고 정확도 평가.
pred = grid_cv_lr.predict(X_test_tfidf_vect)
print('TF-IDF Vectorized Logistic Regression 의 예측 정확도는 {0:.3f}'.format(accuracy_score(y_test ,pred)))
GridSearchCV에서 모델(lr_clf), paras로 설정, cv는 교차 검증 위해 3개의 폴드로 나누기, 성능 측정 지표는 accuracy(정확도), verbose=1은 그리드 서치 진행 과정 출력. 
# 전체 81번 돈다 3*3*3*3
from sklearn.pipeline import Pipeline
pipeline = Pipeline([
('tfidf_vect', TfidfVectorizer(stop_words='english')),
('lr_clf', LogisticRegression(solver='liblinear'))
])
params = { 'tfidf_vect__ngram_range': [(1,1), (1,2), (1,3)], #3
'tfidf_vect__max_df': [100, 300, 700], #3
'lr_clf__C': [1,5,10] #3
}
grid_cv_pipe = GridSearchCV(pipeline, param_grid=params, cv=3 , scoring='accuracy',verbose=1) #3겹
grid_cv_pipe.fit(X_train , y_train)
print(grid_cv_pipe.best_params_ , grid_cv_pipe.best_score_)
pred = grid_cv_pipe.predict(X_test)
print('Pipeline을 통한 Logistic Regression 의 예측 정확도는 {0:.3f}'.format(accuracy_score(y_test ,pred)))