Skip to content
eunzee edited this page May 28, 2022 · 6 revisions

Welcome to the review_classifier wiki!

Index

1. 진행단계

  • 데이터 크롤링 => review_data.csv로 저장
  • 데이터 전처리(맞춤법, 토큰화, stemming(기본형으로), 불용어 제거)
  • 데이터 라벨링(0:부정적, 1:긍정적)
  • 나이브 베이즈 계산을 위한 긍정리뷰, 부정리뷰 bow 만들기 (bow 설명)
    # input
    라벨링  데이터 불러오기
    # output example
    pos_index = {"좋아요" : 0, "에이쁠" : 1, ...}
    pos_bow = [5, 10, ...]
    neg_index = {"별로이다" : 0, "C쁠": 1, ...}
    neg_bow = [4, 3, ...]
    만든 후에 result.csv 파일로 저장할 것이다. (데이터 입출력 설명)
  • main.py 작성(사용자가 이용하게 될 파일)
    • input: 강의 아이디(강의평가 url 맨 뒤 5~6자리 숫자)
    • output(예시):
      긍정적 평가-10개
      부정적 평가-40개
      부정적 평가가 80%로 더 많습니다.
  • 피피티, 발표영상

2. 배경지식

참조를 위해 만들어졌으니 따로 읽어볼 필요는 없다

1. BoW(Bag of Words)

bow는 단어 순서에 상관없이 문장이나 글을 구성 단어와 각 단어의 개수만으로 표현하는 것을 말한다. 예를 들면,

sentence = "아직 과제를 다 못했는데 11시네. 과제를 어떡하지?"
...(bow로 제작)
# 결과
index = {"아직" : 0, "과제를" : 1, "다" : 2, "못했는데" : 3, "11시네" : 4, "어떡하지" : 5}
bow = [1, 2, 1, 1, 1, 1]
  • index(dictionary): 등장하는 단어를 중복되지 않게 번호를 붙인다. (dictionary 자료형은 원래도 key 중복은 안된다)
    bow(array): 단어의 등장 횟수를 세어준다.

  • 이때 index에서 각 단어에 매칭된 숫자가 bow의 인덱스(순서)와 같아야 한다. 위의 예시에서, 두 번 등장하는 "과제를"은 index["과제를"]에 넣으면 1이 도출되고, bow[1]은 2인 것을 알 수 있다.

  • 이 과정을 거치면 각 문장(혹은 글 단위)은 정수의 array로 나타내어진다.

  • 주의점⚠️

    • bow를 만들기 전 맞춤법 정리, 문장부호 제거, 토큰화(띄어쓰기 단위로 끊기), 불용어 처리(나, 너 같은 단어 제외)가 필요하다.
    • 한국어는 어미 변화가 다양해서 그냥 사용하면 같은 단어가 다른 단어로 세어진다. ("안녕하세요"랑 "안녕하십니까", "안녕"은 다 같은 의미인데도 다른 단어로 index가 만들어질 것이다)
      따라서 패키지를 이용해서 기본형으로 바꿔줄 것이다!
    • 이러한 전처리 과정은 복잡하므로 함수로 정리해두고 쉽게 사용할 수 있도록 만들어 놓을 것이다. 혹시 원래 방법이 궁금하다면 functions.py 파일을 보면 된다!
  • 돌아가기

2. 데이터 입출력

아마도 곧 컴사코에서 배울 것이다. 여기에선 csv 파일을 입출력하는 것만 설명하겠음.

  • CSV
    csv 파일은 ,(comma)로 구분된 파일을 말한다. 파이썬에서 통계자료나 인공지능 데이터를 csv 파일로 주로 저장하고 이용한다.
    간단히 표 형식이라고 생각하면 되는데, 위에서 아래로 내려오는 열(Column)과 왼쪽에서 오른쪽으로 가는 행(row)이 있다.
    보통 맨 첫 행에는 무슨 column인지 쓴다.

    _id, review, label
    1, 좋아요~~, 1
    .
    .
    .
    
  • 파일 입출력
    csv 파일 입출력을 위해서는 CSV라는 이름의 패키지가 사용된다. 기본으로 내장되어있으니 따로 설치할 필요는 없다.

    import CSV
    # 파일에 내용을 쓰려고 할 때
    
    file = open('파일명.csv', 'w', newline='', buffering=-1, encoding='utf-8')
    
    writer = csv.writer(file)
    writer.writerow(['_id', 'review', 'label']) # 이렇게 행 단위로 넣을 수 있음
    
    rows = [[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]]
    writer.writerows(rows) # 여러 행을 한꺼번에 넣을 수도 있음. 여기에선 [1, 2, 3]이 첫 행이 되는 것!
    # 파일을 읽기만 할 때
    
    file = open('파일명.csv', 'r', newline='', buffering=-1, encoding='utf-8')
    reader = csv.reader(file) # reader 객체는 각 행을 나열한 list 형태(iteration)이다. 따라서 for문, index([i]) 이용가능
    >>> print(reader[0])
    ['_id', 'review', 'label']
  • 돌아가기

3. functions.py

로그인과 크롤링, 데이터 전처리를 위한 함수를 모아놓은 파일이다. 이제부터 작성해야하는 main.py에서 import해서 쓰면 된다. 아마 12주차 컴사코를 들으면 이해가 될 것!

import functions
or
from functions import *

그래서 functions.py에 들어있는 함수가 어떤 함수인지, 어떤 인수를 넣어야하는지, 어떤 값을 리턴하는지 설명하려고 함!

요약

함수 인자 리턴값
login(id, pw) (string) id, (string) pw (webdriver) driver
ran_sleep() null null
get_review(driver, class_num) (webdriver) driver, (string) class_num (list) review
get_token(reviews) (list) reviews (list) token
correct_review(review_list) (list)review_list (list) correct_spell
bow_and_dict(review) (list) review(여기는 이중 리스트가 아니다) (list)bow, (dictionary) dict

1. login(string id, string pw)

이 함수는 가상드라이버를 켜서 로그인을 해준다.

에브리타임은 각 학교마다 따로 게시판이나 강평 등등이 만들어져 있다. 그리고 에브리타임 내의 url 주소를 안다고 해서 바로 들어가면 막히기 때문에 강의평가 자료를 가져오기 위해서는 실제로 로그인을 해야했다. 그래서 이 함수는 Selenium 패키지의 가상드라이버를 이용해 자동으로 크롬을 키고 조종하여 로그인을 수행한다.

리턴값: selenium webdriver.chrome (webdriver 객체)

import functions

# id, pw는 input으로 사용자한테 받아야겠지?
driver = functions.login(id, pw)

2. ran_sleep()

이 함수는 랜덤한 시간(2~4초) 동안 진행을 멈추게 한다.

가상드라이버에서 로그인하고, 강평 페이지를 찾아가는 과정에서 너무 빨리 진행하면 자동화 봇이라는 것을 에브리타임 측에서 알아채고 계정을 막아버릴 것이다... 때문에 중간에 한번씩 쉬어주려고 만든 함수다. 근데 다른 함수들에 이미 넣어놔서 이걸 main에서 쓸 일은 없다!

리턴값: 없음

3. get_review(webdriver driver, string class_num)

강평을 불러오는 함수.

beautifulsoup 패키지를 이용해서 class_num에 맞는 강평 페이지의 html소스를 가져온다. 거기서 강평 부분만 자르고, string으로 바꿔서 리스트로 저장한다.

  • 여기서 driver는 위의 login() 함수에서 리턴된 '로그인이 적용된' webdriver 상태여야한다.
  • 리턴값: list
review = functions.get_review(driver, "43666")

4. get_token(list reviews)

문장을 토큰화시키는 함수. 토큰화 하는 과정에서 맞춤법 검사, 불용어 제거 등의 전처리도 이루어진다.

한국어 자연어처리를 위해 만들어진 konlpy 패키지의 okt(트위터) 모듈을 사용하였다. 이 모듈은 맞춤법 확인(normalize), 형태소 분석(tagging) 등등의 기능을 할 수 있다.

  • 인수: list 형태의 review
    ["오늘은 참 기분이 좋은 날이다!", "배가 고파 그리고 졸린 날이야"]
  • 리턴값: list
    result = get_token(review)
    result => [['오늘', '참', '기분', '좋다', '날'], ['배', '고프다', '그리고', '졸리다', '날']]
    # 이런식으로 기본형(~이다 or 명사형태)으로 바뀜

5. correct_review(list review)

맞춤법 검사 함수. get_token() 함수 안에서 이미 호출되므로 실제 사용시에는 get_token() 만으로도 맞춤법이 맞게 나옴. (물론...기능의 한계로 완벽하진 않다ㅠㅠ)

konlpy okt 모듈 사용해서 normalize.

  • 인수: list 형태의 review
  • 리턴값: list (spell checked)

6. bow_and_dict(list tokenized_review)

bow와 dict를 만드는 함수.

# ex
review = ["이 강의는 정말 좋네요. 하지만 이 강의는 정말 졸려요.", ...]
...(토큰화)...
tokenized = ["강의", "정말", "좋다", "하지만", "강의" "정말", "졸리다", ...] # 이 함수를 이용할 때는 반드시 이중리스트가 아닌 단일 리스트로 넣어야한다.
bow, dict = bow_and_dict(tokenized)

dict => {"강의": 0, "정말": 1, "좋다": 2, "하지만": 3, "졸리다": 4, ...}
bow => [2, 2, 1, 1, 1, ...]

위의 참고자료에서 bow 부분을 참고해도 좋다.

예제를 보고 이해해보자. dict는 텍스트에 나오는 단어들(또는 토큰화한 것)을 사전처럼 정리한 것이다. dict의 key는 단어(토큰)이고, value는 그 단어가 bow에서 갖는 index 값이다. 그러니까, "강의"라는 단어는 2번 나왔는데, 그것은 bow[0], 즉 bow[dict["강의"]] 값으로 표현될 수 있다.
결국 dict와 bow의 길이는 같겠고, 원래 '글'이었던 문장은 숫자의 배열(bow)로 표현할 수 있게 된다.
labeling한 데이터도 이러한 과정을 거쳐 긍정적 bow, dict/ 부정적 bow, dict로 만들어 저장해놓았다.

  • 인수: list형태 (토큰화된)
  • 리턴값: list, dictionary (2개가 리턴되는 것임)

4. crawling_reviews.py

학습 데이터 생성을 위해 6개 강의의 강평을 가져와서 csv 파일로 저장하는 코드이다.

5. Bow.py

라벨링 한 데이터를 가지고 전처리, 토큰화를 거친 후 긍정적 평가와 부정적 평가로 나눠서 bow와 dict를 생성함.
생성 결과(2개의 list, 2개의 dict)는 csv 파일(train_data.csv)로 저장함.

  • 저장할 때 list랑 dict를 string으로 바꿔서 저장했기 때문에 다시 불러왔을 때 list랑 dict로 바꿔줘야함. 그것과 관련해서는 링크 참조 바람.

6. main.py

실제로 작성해야 할 코드. 이 코드는 두 가지 부분으로 나눌 수 있다.

  • 사용자의 id, pw 입력받고 강평을 보고싶은 강의의 번호를 입력받아서 강평을 받아오고, 토큰화하여 bow와 dict를 만든다.
  • labeled된 데이터 csv파일을 가져와서 긍정적 강평과 부정적 강평 개수를 출력한다.

만드는 과정

역할분담하기.


  • 사용자 id, pw 입력받기
  • 강평 번호 입력받기
  • 로그인하고 강평 받아오기(functions 모듈 이용)
  • 강평 토큰화, 전처리(functions 모듈 이용)

  • 각 강평이 긍정적인지 부정적인지 베이즈정리 이용해서 계산
  • 긍정적/부정적 강평 개수, 비율 출력