TF-IDF 변환 저장

전치



TF-IDF 변환을 미지의 입력에 대해서 사용하기 때문에, 변환한 내용을 보존할 필요가 있기 때문에, 이번은 그 보존 방법에 대해서 남겨 둔다.

mecab에서 형태소 분석



tyamagu2.xyz 님의 기사 을 인용하여 클래스를 정의해 보겠습니다.
MeCab 를 import 잊지 않고
※ 스톱 워드는 교토 대학의 Slothlib을 사용하고 있으므로 당겨주세요.
import MeCab
'''
MeCabで名詞だけを抜き取るクラスの定義
辞書は"mecab-ipadic-neologd"を使用
'''


class WordDividor:
    INDEX_CATEGORY = 0
    TARGET_CATEGORY = ['名詞']

    def __init__(self, dictionary="mecabrc"):
        self.dictionary = dictionary
        self.tagger = MeCab.Tagger(self.dictionary)

    def extract_words(self, text):
        if not text:
            return []

        # テキストの余分なデータの削除(ex : httpなど)
        text = re.sub(r'https?://[\w/:%#\$&\?\(\)~\.=\+\-…]+', "", text)
        text = re.sub(r'[!-~]', "", text)  # 半角記号,数字,英字
        text = re.sub(r'[︰-@]', "", text)  # 全角記号
        text = re.sub('\n', " ", text)  # 改行文字

        words = []
        # 文字列がGCされるのを防ぐ
        self.tagger.parse('')
        node = self.tagger.parseToNode(text)
        while node:
            # ","で文字列の分割を行い, ターゲットになる品詞と比較を行う.
            if node.feature.split(',')[self.INDEX_CATEGORY] in self.TARGET_CATEGORY:
                # ストップワードの判定を行う(stopwordsに引っかかってない名詞を入れる)
                if node.surface not in stopwords:
                    words.append(node.surface)
            node = node.next

        return words


사용할 때는
wd = WordDividor()
extract_word = wd.extract_word(text="ほげほげテスト")

이와 같이 사용하면, 일시적으로 준비한 변수 extract_word 에 mecab 에 의해 형태소 해석되어 명사만 추출된 것이 들어갑니다.

TF-IDF 변환



그런 다음 TF-IDF 변환 을 수행합니다.
이것은 다음과 같이 클래스를 정의합니다.
TfidfVectorizer 를 import 잊지 않고
from sklearn.feature_extraction.text import TfidfVectorizer

'''
TF-IDF変換を行うクラスの定義
1. TfidfVectorizerインスタンスの作成(analyzerにmecabの形態素解析手法を指定)
2. fitメソッドを行ったTfidfVectorizerインスタンスを返す(新しいデータに用いるため)
'''


class WordPreProcessor:

    # コンストラクタ
    def __init__(self, analyze_method):
        self.tfidf = TfidfVectorizer(analyzer=analyze_method, use_idf=True, norm='l2', smooth_idf=True)

    def wordspreprocess(self, raw_data):
        # fitの状態を格納(TfidfVectorizerインスタンスが格納される)
        tfidf_condition = self.tfidf.fit(raw_data)
        # 形態素解析されたワードを、fitで作ったTF-IDF特徴空間行列に変換する
        tfidf_vector = self.tfidf.transform(raw_data).toarray()

        return tfidf_condition, np.matrix(tfidf_vector)

여기에 두 개의 포인트가 있으며,
  • TfidfVectorizer 인스턴스에 MeCab로 형태소 해석하는 클래스 메소드명을 지정해 준다.

  • 영어 등을 형태소 해석하는 경우는 원래 MeCab가 필요하지 않으므로 파이썬 기계 학습 프로그래밍TfidfVectorizer(analyzer='word', use_idf=True, norm='l2', smooth_idf=True)그리고 기본 사양 에서 생성되었습니다.

    그래서 인스턴스 생성시
    wpp = WordPreProcessor(analyze_method=wd.extract_words)
    

    이런 식으로, wd 인스턴스의 메소드를 지정해 줍니다.
  • fit_transform을 사용하지 않고 fit만 사용

  • fit 메소드는 공식 라이브러리 을 인용하면

    Learn vocabulary and idf from training set.

    교육 데이터에서 idf와 어휘를 학습합니다. 반환 값은 학습 후 TfidfVectorizer 인스턴스입니다.
    그 인스턴스를 사용해 TF-IDF 변환을 실시하는 메소드가 transform 메소드가 됩니다.
    공식의 라이브러리에서는 이 2개를 함께 넣었다 fit_transform 메소드가 친절하게 준비되어 있으므로, 용도로 구분해야 한다고 생각합니다.

    그래서 fit한 상태를 pickle 등으로 저장하면 새로운 문장을 저장한 규격으로 TF-IDF 변환할 수 있다는 것입니다.

    TF-IDF 저장


    # オブジェクト保存ライブラリの導入 
    import pickle 
    # インスタンスの生成 
    wpp = WordPreProcessor(analyze_method=wd.extract_words)
    tfidf_condition, feature_matrix = wpp.wordspreprocess(raw_data="ほげほげテスト", is_dimension_compact=is_dimension_compact)
    # 保存 
    pickle.dump(tfidf_condition, open("tfidf.pkl", "wb"))
    

    그러나 이것이라면 오류가 발생합니다.


    SwigPyObject? ? ? ?

    분명히 analyze_method에 형태소 클래스의 메소드를 지정하고 있기 때문에 클래스 인스턴스의 중첩이므로 저장할 수 없다는 것이다.

    그래서 이 솔루션은
    tfidf_condition.set_params(analyzer='word')
    # 保存 
    pickle.dump(tfidf_condition, open("tfidf.pkl", "wb"))
    

    analyzer = 'word'로 대체하여 저장합니다 ( 'word'는 기본값입니다)

    사용할 때,
    from dataPreProcessor import WordDividor
    import pickle
    
    def main():
        wd = WordDividor()
        tfidf_vectorizer = pickle.load(open("tfidf.pkl", "rb"))
        # 一時的に置き換えていたanalyzerを指定
        tfidf_vectorizer.set_params(analyzer=wd.extract_words)
        tfidf_vector = tfidf_vectorizer.transform(['新しくものあるほげほげテスト'])
    
    if __name__ == '__main__':
        main()
    

    이런 식으로, 저장한 것을 로드해, set_params 메소드를 사용해 다시 MeCab 클래스의 메소드를 다시 지정해, 사용해 준다.
    fit에서 학습되었으므로 analyze 메서드가 일시적으로 변경되어도 문제가 없습니다.

    마지막으로



    의외로 돌아다니는 방법을 하고 있으므로, 원래 pickleがナンセンス 라든지 다른 좋은 방법이 있으면 코멘트해 주세요.

    참고


  • MeCab과 scikit-learn으로 일본어 텍스트 분류
  • Keep TFIDF result for predicting new content using Scikit for Python (이 답변 4)
  • 좋은 웹페이지 즐겨찾기