ABOUT ME

Today
Yesterday
Total
  • (5) 자연어처리_ 워드 임베딩 시각화
    자연어처리 2023. 7. 30. 00:19
    728x90
    #표에 한글을 쓰기위해 폰트 다운로드
    !sudo apt-get install -y fonts-nanum
    !sudo fc-cache -fv
    !rm ~/.cache/matplotlib -rf

    1. 네이버 영화 리뷰 데이터셋

    • 총 200,000개의 리뷰로 구성된 데이터로, 영화 리뷰를 긍/부정으로 분류하기 위해 만들어진 데이터셋
    • 리뷰가 긍정인 경우 1, 부정인 경우 0으로 표시한 레이블로 구성되어 있음
    import urllib.request
    import pandas as pd
    urllib.request.urlretrieve('https://raw.githubusercontent.com/e9t/nsmc/master/ratings_train.txt', filename='ratings_train.txt')
    urllib.request.urlretrieve('https://raw.githubusercontent.com/e9t/nsmc/master/ratings_test.txt', filename='ratings_test.txt')
    train_dataset = pd.read_table('ratings_test.txt')
    train_dataset

    2. 데이터 전처리

    # 결측치 확인하고 결측치를 제거
    train_dataset.replace('', float('NaN'), inplace=True)
    print(train_dataset.isnull().values.any())

    train_dataset = train_dataset.dropna().reset_index(drop=True)
    print(f'필터링된 데이터셋 총 개수: {len(train_dataset)}')

    # 열을 기준으로 중복 데이터를 제거
    train_dataset = train_dataset.drop_duplicates(['document']).reset_index(drop=True)
    train_dataset

    # 한글이 아닌 문자를 포함하는 데이터 제거(ㅋㅋㅋ 제거하지 않음)
    train_dataset['document'] = train_dataset['document'].str.replace('[^ㄱ-ㅎㅏ-ㅣ가-힣]', ' ')
    # train_dataset['document'] = train_dataset['document'].str.replace(pat=r'[^\w]', repl=r' ', regex=True)
    # train_dataset['document'] = train_dataset['document'].str.replace(pat=r'[a-zA-Z]', repl=r' ', regex=True)
    train_dataset['document']

    # 너무 짧은 단어를 제거(단어의 길이가 1이하)
    train_dataset['document'] = train_dataset['document'].apply(lambda x: ' '.join([token for token in x.split() if len(token) > 1]))
    train_dataset

    # 전체 길이가 100 이하이거나 전체 단어 개수가 5개 이하인 데이터를 제거
    train_dataset = train_dataset[train_dataset.document.apply(lambda x: len(str(x)) > 100 and len(str(x).split()) > 5)].reset_index(drop=True)
    train_dataset

    !pip install konlpy
    from konlpy.tag import Okt
    # 불용어 정의
    stopwords = ['의', '가', '이', '은', '들', '는', '좀', '잘', '걍', '과', '도', '를', '으로', '자', '에', '와', '한', '하다']
    train_dataset = list(train_dataset['document'])
    # train_dataset
    okt = Okt()

    tokenized_data = []

    for sentence in train_dataset:
      tokenized_sentence = okt.morphs(sentence, stem = True)
      stopwords_removed_sentence = [word for word in tokenized_sentence if not word in stopwords]
      tokenized_data.append(stopwords_removed_sentence)
    tokenized_data[0]

    # matplotlib hist 함수로 length of smaples 와 number of samples를 표현
    # 리뷰의 최대 길이와 평균길이를 출력
    import matplotlib.pyplot as plt
    import numpy as np

    # Step 2: 데이터 준비
    sample_lengths = [len(sample) for sample in tokenized_data]
    max_length = max(sample_lengths)
    average_length = sum(sample_lengths) / len(sample_lengths)

    # Step 3: 히스토그램 그리기
    plt.hist(sample_lengths, bins='auto')
    plt.xlabel('샘플의 길이')
    plt.ylabel('샘플의 개수')
    plt.title('샘플 길이 분포')
    plt.show()

    # Step 4: 최대 길이와 평균 길이 출력하기
    print('최대 길이:', max_length)
    print('평균 길이:', average_length)

     

    3. 워드 임베딩 구축

    from gensim.models import Word2Vec
    embedding_dim = 100

    # sg: 0(CBOW), 1(Skip-gram)

    model = Word2Vec(
        sentences = tokenized_data,
        vector_size = embedding_dim,
        window = 5,
        min_count = 5,
        workers = 4,
        sg = 0
    )
    # 임베딩 행렬의 크기
    # 단어 사전에는 총 12381개의 단어가 존재하고, 각각의 단어는 미리 설정한 embedding_dim = 100  차원으로 구성되어있음\

    model.wv.vectors.shape

    word_vectors = model.wv
    vocabs = list(word_vectors.index_to_key)
    vocabs[:20]

    for sim_word in model.wv.most_similar('좋다'):
      print(sim_word)

    model.wv.similarity('좋다','괜찮다')

    4. 워드 임베딩 시각화

    import matplotlib.font_manager
    font_list = matplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf')
    [matplotlib.font_manager.FontProperties(fname=font).get_name() for font in font_list if 'Nanum' in font]

    plt.rc('font',family = 'NanumBarunGothic')
    word_vector_list = [word_vectors[word] for word in vocabs]
    word_vector_list[0]

    # PCA가 자주 이용되는 차원 축소 방식이긴 하지만 군집의 변별력을 해친다는 단점이 있음
    #PCA를 개선한 방법이 t-SNE 차원 축소 방식
    from sklearn.manifold import TSNE
     
    tsne = TSNE(learning_rate = 100)
    transformed = tsne.fit_transform(np.array(word_vector_list))


    x_axis_tsne = transformed[:,0]
    y_axis_tsne = transformed[:,1]
     
    def plot_tsne_graph(vocabs, x_asix, y_asix):
      plt.figure(figsize=(30, 30))
      plt.scatter(x_asix, y_asix, marker = 'o')
      for i, v in enumerate(vocabs):
        plt.annotate(v, xy=(x_asix[i], y_asix[i]))
     
    plot_tsne_graph(vocabs, x_axis_tsne, y_axis_tsne)

     

    5.TSNE 고도화

    • Python에서 제공하는 interactive visualization library인 bokey를 사용하여 시각화 고도화
    import pickle
    tsne_df = pd.DataFrame(transformed, columns = ['x_coord', 'y_coord'])
     
     
    from bokeh.plotting import figure, show, output_notebook
    from bokeh.models import HoverTool, ColumnDataSource, value
     
    def plot_tsne_graph(vocabs, x_asix, y_asix):
      plt.figure(figsize=(30, 30))
      plt.scatter(x_asix, y_asix, marker = 'o')
      for i, v in enumerate(vocabs):
        plt.annotate(v, xy=(x_asix[i], y_asix[i]))
    output_notebook()
    # prepare the data in a form suitable for bokeh.
    plot_data = ColumnDataSource(tsne_df)

    # create the plot and configure it
    tsne_plot = figure(title='t-SNE Word Embeddings',
      plot_width = 800,
      plot_height = 800,
      active_scroll='wheel_zoom'
    )

    # add a hover tool to display words on roll-over
    tsne_plot.add_tools( HoverTool(tooltips = '@word') )
    tsne_plot.circle(
        'x_coord', 'y_coord', source=plot_data,
        color='red', line_alpha=0.2, fill_alpha=0.1,
        size=10, hover_line_color='orange'
      )

    # adjust visual elements of the plot
    tsne_plot.xaxis.visible = False
    tsne_plot.yaxis.visible = False
    tsne_plot.grid.grid_line_color = None
    tsne_plot.outline_line_color = None

    # show time!
    show(tsne_plot);

    from gensim.models import KeyedVectors
    model.wv.save_word2vec_format('samle_word2vec_embedding')
    !python -m gensim.scripts.word2vec2tensor --input sample_word2vec_embedding --output sample_word2vec_embedding

    '자연어처리' 카테고리의 다른 글

    댓글

Designed by Tistory.