ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Mini Batch Processing 방식의 구현과 학습모델의 임베딩
    Programming & Machine Learning/Python X 머신러닝 2017. 8. 2. 20:34

    아웃 오브 코어 기법 (mini batch processing 방식)

    배치 방식이 아닌 온라인 방식으로 모델을 학습한 뒤, 학습한 모델을 저장해보고 다시 읽어보는 예제를 진행하였다.

    in-memory 방식으로 대용량 데이터를 학습시키고 모델을 만들기에는 한계가 있다.
    따라서 mini batch의 방식으로 데이터를 chunk로 나누어서 처리해야 한다.
    
    감성분석에서 사용한 대용량 데이터를 다시 예제로 사용하였다.
    
    tf-idf를 추출하기 위해서는 TfidfTransformer 클래스를 사용했지만, 
    mini batch 방식(=온라인)에서는 사용할 수가 없다. 하지만 비슷한 일을 해주는 HashingVectorizer가 있다.
    이를 통해 전체 문서에서 tf-idf를 하는 것과 비슷한 작업을 해줄 수 있다.
    참고로, HashingVectorizer의 파라미터인 n_features는 데이터의 피처 수를 나타내는데,
    default가 무려 2의 20승에 달한다. 문서에는 정확한 설명이 나와있지는 않지만, 아마 hashing
    알고리즘으로 구현하는 과정에서, 이 공간이 충분하지 않으면 indexing이 초과되기 때문인 것으로 보인다.
    
    다시 돌아와서 SGDClassifier라는 클래스에서는 모델을 mini batch 방식으로 분류 학습
    시켜주는 기능을 지원하는데, SGD란 Stochastic Gradient Descent의 약자로, 
    미니 배치 방식으로 가중치를 학습시켜준다는 의미이다. 
    loss라는 파라미터는 어떤 분류기를 사용할 것인지에 대한 파라미터이다.
    partial_fit이라는 멤버 함수로 실제적인 partial 학습이 진행된다.
    

    아웃 오브 코어 기법을 사용한 파이썬 코드

    ### 텍스트 정제 및 token화 import numpy as np import re from nltk.corpus import stopwords # import nltk # nltk.download("stopwords") stop = stopwords.words('english') def tokenizer(text): text = re.sub('<[^>]*>', '', text) emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text.lower()) text = re.sub('[\W]+', ' ', text.lower()) + ' '.join(emoticons).replace('-', '') tokenized = [w for w in text.split() if w not in stop] return tokenized ### 문서를 스트리밍 형식으로 읽도록 하는 함수 def stream_docs(path): with open(path, 'r', encoding='utf-8') as csv: next(csv) # skip header for line in csv: text, label = line[:-3], int(line[-2]) yield text, label # yield 키워드를 사용하면 generator를 만들 수 있다 # generator가 잘 동작하는지 테스트 next(stream_docs(path='./movie_data.csv')) ### 미니배치를 얻어오는 함수 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 ### mini batch 방식으로 tf-idf 진행 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, n_iter=1) doc_stream = stream_docs(path='./movie_data.csv') ### mini batch 방식으로 모델 학습 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() ### chunk tf_idf 데이터를 데이터프레임 형태로 변환하기 from scipy import sparse print("{}".format(X_train)) print() tf_idf = X_train.tocoo(copy=False) result = pd.DataFrame(tf_idf.toarray()) ### 성능 평가 X_test, y_test = get_minibatch(doc_stream, size=5000) X_test = vect.transform(X_test) print('Accuracy: %.3f' % clf.score(X_test, y_test))


    ### 임베딩을 위한 모델 파일 저장 import pickle import os dest = os.path.join('test', 'pkl_objects') if not os.path.exists(dest): os.makedirs(dest) pickle.dump(stop, open(os.path.join(dest, 'stopwords.pkl'), 'wb'), protocol=4) pickle.dump(clf, open(os.path.join(dest, 'classifier.pkl'), 'wb'), protocol=4) ### 저장해둔 모델 파일 읽기 clf_read = pickle.load(open(os.path.join('test/pkl_objects', 'classifier.pkl'), 'rb'))


    댓글

분노의 분석실 Y.LAB