GridSearchCV
- 머신러닝에서 모델의 성능향상을 위해 쓰이는 기법
- 사용자가 모델의 하이퍼파라미터 값을 리스트로 입력
- 입력 값에 대한 경우의 수마다 예측 성능을 측정 평가하여 비교 -> 최적의 하이퍼파라미터 값을 찾음
훈련 코드
ngram_range
: 1어절 1-gram 표현
- 첫번째
param_grid
- TfidfVectorizer 기본 매개변수 세팅(use_idf=True, norm='l2') -> 해당 설정으로 tf-idf 계산
- 두번째
param_grid
- 단어 빈도를 사용하여 모델 훈련(use_idf=False, norm=None)
- 로지스틱 회귀 분류기는
penalty
매개변수를 통해 L1,L2 규제를 적용.
- 규제 강도는 C에 여러 값을 지정하여 비교
GridSearchCV
파라미터
cv
: 교차검증을 위한 fold 횟수
verbose
: 수행결과 메세지 출력
scoring
: 성능을 측정할 평가 방법
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import GridSearchCV
tfidf = TfidfVectorizer(strip_accents=None,
lowercase=False,
preprocessor=None)
param_grid = [{'vect__ngram_range': [(1, 1)],
'vect__stop_words': [stop, None],
'vect__tokenizer': [tokenizer, tokenizer_porter],
'clf__penalty': ['l1', 'l2'],
'clf__C': [1.0, 10.0, 100.0]},
{'vect__ngram_range': [(1, 1)],
'vect__stop_words': [stop, None],
'vect__tokenizer': [tokenizer, tokenizer_porter],
'vect__use_idf':[False],
'vect__norm':[None],
'clf__penalty': ['l1', 'l2'],
'clf__C': [1.0, 10.0, 100.0]},
]
lr_tfidf = Pipeline([('vect', tfidf),
('clf', LogisticRegression(random_state=0, solver='liblinear'))])
gs_lr_tfidf = GridSearchCV(lr_tfidf, param_grid,
scoring='accuracy',
cv=5, verbose=1
n_jobs=1)
gs_lr_tfidf.fit(X_train, y_train)
대용량 데이터 처리: 온라인 알고리즘과 외부 메모리학습
- 그리드서치안에서 5만개 영화 리뷰 벡터를 만들면 많은 시간 소요
- 대량 데이터셋을 다룰 수 있는 외부 메모리 학습 기법을 사용하여 시간 감소
- 다음과 가티 한번에 문서 하나씩 읽어 반환하는 메소드 정의
def stream_docs(path):
with open(path, 'r', encoding='utf-8') as csv:
next(csv)
for line in csv:
text, label = line[:-3], int(line[-2])
yield text, label
- 문서를 읽어 size 매개변수에서 지정한 만큼 문서를 반환하는
get_minibatch
함수 정의
def get_minibatch(doc_stream, size):
docs, y = [], []
try:
for _ in range(size):
text, label = next(doc_stream)
docs.append(text)
y.append(label)
except StopIteration:
return None, None
return docs, y
- 외부 메모리 학습에
CountVectorizer
, TfidfVectorizer
를 사용할 수 없다.
- (어휘사전, 특성 벡터를 메모리에 적재해야해서)
- 대신
HashingVectorizer
를 사용. 데이터 종류 상관없이 사용 가능.
- 어휘 사전을 저장할 필요가 없기 때문에 대규모 데이터 세트로 확장 가능. 메모리 사용량 적음
- 생성자 매개변수 외에는 상태를 보유하지 않으므로 피클, 언피클 속도 빠름
- 해시 함수를 사용하기 때문에 원본 단어의 의미 정보가 완전히 유지되지 않을 수 있음.
- 충돌로 인해 서로 다른 단어가 동일한 해시 값으로 매핑될 수 있음
from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.linear_model import SGDClassifier
vect = HashingVectorizer(decode_error='ignore',
n_features=2**21,
preprocessor=None,
tokenizer=tokenizer)
clf = SGDClassifier(loss='log', random_state=1)
doc_stream = stream_docs(path='movie_data.csv')
--------------------
import pyprind
pbar = pyprind.ProgBar(45)
classes = np.array([0, 1])
for _ in range(45):
X_train, y_train = get_minibatch(doc_stream, size=1000)
if not X_train:
break
X_train = vect.transform(X_train)
clf.partial_fit(X_train, y_train, classes=classes)
pbar.update()
LDA (Latent Disrichlet Allocation)
- 잠재 디리클레 할당
- 주어진 문서들에서 주제를 추출하는 방법론
- 문서가 포함하는 단어에 기반 하여 주제별로 문서를 분류할 수 있음
- 십만개 이상의 문서가 있는 경우는 직접 토픽을 찾아내는 것이 어렵기 때문에 LDA를 이용하여 토픽 추출
LDA 과정
- 데이터 불러오기 및 전처리
- 단어 추출
- 벡터 변환 및 토픽 추정
- 토픽에 할당된 키워드 및 문서 추출
데이터 불러오기 및 전처리
문서1 : 저는 사과랑 바나나를 먹어요.
문서2 : 우리는 귀여운 강아지가 좋아요.
문서3 : 저의 깜찍하고 귀여운 강아지가 바나나를 먹어요.
단어 추출
문서1 : 사과, 바나나, 먹어요
문서2 : 우리, 귀여운, 강아지, 좋아요
문서3 : 깜직하고, 귀여운, 강아지, 바나나, 먹어요
벡터 변환 및 토픽 추정
- LDA는 각문서의 토픽 분포와 토픽 내 단어 분포를 추정
- 2개 토픽을 추출한다고 가정(하이퍼파라미터 설정)
- 각 단어를 벡터로 변환
from sklearn.feature_extraction.text import CountVectorizer
count = CounVectorizer(stop_words='english', max_df=.1, max_features=7)
X = count.fit_transform(df['review'].values)
- 토픽 추정
- batch는 lda 추정기가 한번 반복할 때 가능한 모든 훈련 데이터를 사용하여 학습
from sklearn.decomposition import LatentDirichletAllocation
lda = LatentDirichletAllocation(n_components=2, random_state=123, learning_method='batch')
X_topics = lda.fit_transform(X)
문서1 : 토픽 A 100%
문서2 : 토픽 B 100%
문서3 : 토픽 B 60%, 토픽 A 40%
토픽A : 사과 20%, 바나나 40%, 먹어요 40%, 귀여운 0%, 강아지 0%, 깜찍하고 0%, 좋아요 0%
토픽B : 사과 0%, 바나나 0%, 먹어요 0%, 귀여운 33%, 강아지 33%, 깜찍하고 16%, 좋아요 16%