2. 이상탐지를 적용할 알고리즘 선정 및 구현

2.1. 이상탐지 알고리즘을 선정 과정

  1. 딥러닝으로 해결하기 위해 Paperwithcode에 접속하여 Task에 관련된 키워드를 입력한다. -> Anomaly Detection 을 검색한다.
  2. Task와 유사한 데이터셋을 찾아 클릭한다. -> MVTec AD
  3. 유사한 데이터셋을 평가했을때 순위를 나타낸 리더보드에서 SOTA 알고리즘을 선정한다. -> PaDim 알고리즘 선정
  4. 선정한 알고리즘에 대해 학습과 추론할 수 있게 구현한다.
    • 해당 알고리즘에 대해 논문을 읽고 공부하고나서, github를 참고하여 해결하고자 하는 Task에 맞게 코드를 수정한다.
  5. 각자 환경에서 구동시켜 학습시킨다. -> 리눅스 서버로 가져와서 학습

2.2 이상탐지 알고리즘

1. PaDim을 선정한 이유

2021.08월 당시 MVTec 데이터셋으로 이상탐지를 하였을때, 4위(2021.11월 시점 6위)를 자치한 SOTA 모델이었고, 사전조사를 했을때 PaDim이라는 알고리즘이 One-Class Classification 방식으로 정상 데이터로 부터 학습 후 정상과 비정상을 판단한다는 점과 사전 학습된 CNN 모델을 가져와서 특성을 추출하고 뽑힌 특징을 가지고 평균과 공분산을 구하고, 정상 샘플에 대한 Gaussian distribution이 존재한다는 가정으로 비정상 샘플을 구별한다는 점에서 매력적으로 느껴졌고 주조 공정에서 발생한 임펠러 데이터에 적용해도 MVTec 데이터에서 보여주는 성능을 나타낼 것으로 기대되어 해당 알고리즘을 선정하였다.

2. PaDim 이란

  • One-Class Classification 방식으로 학습되고, 사전 학습된 CNN 모델을 통해 정상 샘플에 대한 Embedding 정보를 뽑아내고, Random Dimensionality Reduction을 진행하여 정상 샘플에 대한 평균과 공분산 정보를 추출한다.
  • 정상 샘플이 Gaussian distribution을 따른다는 가정하에, 테스트 데이터와 정상 샘플의 특징을 Mahalanobis distance를 사용해 정상과 비정상 샘플을 구별한다.

3. 주조 공정에 대해 평가한 성능 결과.

2.3 PaDim 코드 구현

1. custom_dataset.py
소스코드

프로젝트 개요

  • 제조 현장에서 지속적으로 활용 가능한 AI 기반 이상탐지 알고리즘 및 플랫폼 개발

프로젝트 목적

  1. 산업현장 속 이상탐지 문제를 해결하고, 이를 다방면으로 활용할 수 있는 Web 플랫폼 구축
  2. 수동으로 결합여부를 탐지하는 것보다 AVI를 적용하여 속도와 정확성을 높여 생산효율을 높이고 품질 관리 비용을 절감
    (* AVI : 이미지를 기반으로 하여 불량을 탐지하는 자동 육안 품질 검사)

프로젝트 워크 플로우


플랫폼 소개

플랫폼 개발 과정

  1. 제조 현장에서 발생한 양품, 불량품 이미지 데이터 조사 및 수집
  2. 이상탐지를 적용할 알고리즘 선정 및 구현
  3. 클라이언트가 사용 알고리즘을 사용가능하게 API 구현
  4. Streamlit을 활용해 Web GUI 구현
  5. Front와 Backend를 연동해 테스트 진행.
  6. Docker 컨테이너를 활용해 플랫폼 배포하기
  7. 더 나아가야 할점

1. 제조 현장에서 발생한 양품, 불량품 이미지 데이터 조사 및 수집

1.1 제조 현장에서 발생된 이미지 데이터셋 조사

  • MVTec AD
    • 산업 검사에 중점을 둔 이상탐지 방법을 벤치마킹하기 위한 데이터 세트이며[1], 15개 서로 다른 Object와 Texture 범주로 구분되어 있고 각각 10가지, 5가지 종류의 도메인 데이터로 구성되어있다. 그리고 총 3629장의 학습 데이터와 1725장의 테스트 데이터로 존재하며 위 데이터 중 결함 이미지는 실제 산업 현장의 검사 시나리오와 비슷한 결함들을 직접 발생시켜서 취득한 데이터라고 한다.[2]
  • casting product image data for quality inspection [3]
    • 주조는 원하는 모양을 중공 공동이 들어 있는 주형에 액체를 부은 다음 응고 시키는 제조 공정이다. 이 과정에서 주조 결함이 불규칙적으로 발생한다. 이 결함들은 원치 않은 결함이고 결함이 있는 제품을 제거하기 위해 모든 업계에는 품질 검사 부서가 있으며 검사 프로세스는 수동으로 진행하기에 매우 긴 시간이 걸리는 프로세스이며 사람이 육안으로 보기에 100% 정확하지 않을 수 있다. 그렇기에 검사 프로세스를 자동으로 만들기로 결정했고, 이렇게 수집된 데이터 셋은 수중 펌프 임펠러 데이터 셋이다.

1.2 데이터 수집

  • 2021년 8월 당시 Window 환경에서 MVTec AD 수집 방법 [4]

    1. aria2에 접속하여 aria2-1.35.0-win-64bit-build1.zip 파일을 다운로드한다.
    2. 설치 완료 후 압축 파일을 해제한다.
    3. CMD 창을 열어서 aria2 파일을 압축 해제한 파일 경로로 접속한다.
    4. MVTec AD Url에 접속한다.MVTec 링크
    5. MVTec Url에서 Download를 클릭한다.
      • 그러면 ftp url로 제공되는데 해당 url를 복사한다.
      • url : ftp://guest:GU.205dldo@ftp.softronics.ch/mvtec_anomaly_detection/mvtec_anomaly_detection.tar.xz
    6. CMD 창에 접속하여 aria2c.exe ftp://guest:GU.205dldo@ftp.softronics.ch/mvtec_anomaly_detection/mvtec_anomaly_detection.tar.xz 를 입력하고 Enter 키를 누른다.
    7. END
  • 2021년 11월 당시 Window 환경에서 MVTec AD 수집 방법

    1. MVTec AD Url에 접속한다.
    2. MVTec Url에서 Download를 클릭한다.
    3. mvtec_anomaly_detection.tar.xz 해당 파일을 압축 해제를 한다.
    4. END
  • casting product image data for quality inspection 수집 방법

    1. casting product image data for quality inspection 클릭한다.
    2. Kaggle에 로그인을 진행한다.
    3. Download 버튼을 클릭한다.
    4. 다운 받은 파일을 압축한다.
    5. END

참고 문헌

'기타 파일들 > 이미지파일' 카테고리의 다른 글

서버 관련 내용  (0) 2021.10.01
랩 모델 아키텍처  (0) 2021.07.05

 

'기타 파일들 > 이미지파일' 카테고리의 다른 글

과제 3번 사진 자료  (0) 2021.10.20
랩 모델 아키텍처  (0) 2021.07.05

'기타 파일들 > 이미지파일' 카테고리의 다른 글

과제 3번 사진 자료  (0) 2021.10.20
서버 관련 내용  (0) 2021.10.01

< 리눅스 sudo 권한 부여하기 >

※  설정 방법 ※

# vi /etc/sudoers : vi를 이용하여 /etc/sudoers 파일 수정 (vim도 가능)

# visudo : 1. 명령어 visudo를 이용하여 /etc/sudoers 파일 수정

        2. 문법에 맞지 않는 설정을 할 경우 확인해준다.

      ※ visudo는 vim으로는 수정할 수 없다.

 

→ 형식 [계정명][호스트 명]=[옵션][명령어1], [명령어2]....[명령어N]

root 계정은 모든 서버에서 모든 명령어를 사용할 수 있습니다.

neul-carpediem.tistory.com/90

 

< 리눅스 포맷 후 재설치 >

www.youtube.com/watch?v=o9j_9hCRmms

keepdev.tistory.com/69

blog.naver.com/PostView.nhn?blogId=stom13&logNo=221014837238

do-jeon.tistory.com/9

 

<쿠다 인식 >

zereight.tistory.com/533

 

goodtogreate.tistory.com/entry/2004-%EC%9A%B0%EB%B6%84%ED%88%AC%EA%B8%B0%EB%B0%98-NVIDIA-GeForce-RTX-3090%EC%97%90-CUDA-cuDNN-Pytorch-%EC%84%A4%EC%B9%98

 

 

< 사용자 계정 sudo 가능하게 만들기 >

jootc.com/p/20170122128

< 루트 계정이 튕길때>

suzxc2468.tistory.com/150

 

< SSH 관련 사이트>

jhnyang.tistory.com/10

kbs4674.tistory.com/134

 

사용자 ID를 생성하는 명령어는 useradd

패스워드 생성은 passwd 

유닉스 운영체제는 다중 사용자 시스템이다. 리눅스를 설치를 하면 기본적으로 root라는 이름을 가진 슈퍼유저가 있고, 이 관리자는 시스템이 접소할 수 있는 사용자들을 생성하고 관리하는 권한을 가지고 있다. 일개 사용자가 다른 사용자들을 관리할 수는 없다.

즉 root 관리자가 root이외의 사용자를 생성할 때 사용하는 명령어로, useradd라 해도 되지만, adduser라서 쓴다.

# useradd [option] 사용자계정이름

# useradd jong

# passwd cic

>> 사용자를 만들었지만, 비번이 설정되어 있지 않아서, 사용자가 접속할 수가 없다.

로그인하면 바로 비밀번호 입력하라는 커맨드가 뜸. 그래서 계정을 생성한 뒤 에는 그 계정의 초기 비밀번호를 설정해준다.  그리고 제대로 만들어졌는지 확인하기 위해 alt + F2를 눌러서 가상 터미널 tty2로 가서 만들어준 계정으로 로그인을 해준다.

 

 사용자 관리 파일, PASSWD 파일구조

리눅스는 다중 사용자 시스템이라서 등록한 사용자를 관리할수 있다.

일일이 다 외우고 있지 않기때문에 리눅스 운영체제는 사용자 정보를 어디다가 텍스트 파일로 저장해서 관리를 한다.

그럼 우리가 생성한 계정을 확인해볼겸, 사용자 관리 파일에 대해서 알아보자. 

기본적으로 사용자의 목록은 /etc/passwd에 저장되어 있다.

 

사용자의 목록을 저장하고 있는 정보 파일:  /etc/passwd

일단 관리자만 접근할수 있다는걸 보여주기 위해서, 사용자를 관리자가 아닌 jong으로 변경해주고 파일 목록과 정보를 출력해주는 ls-l을 보면 해당 관리자 외 아무도 수정할수 없다고 접근권한이 설정되어 있다.

 

따라서 파일을 삭제하는 명령어를 쳐도 퍼미션권한이 떠서 수행되지 않는다.

그렇기에 반드시 root 권한으로 변경해야한다.

# su

# vi /etc/passwd 또는 cat - 10 /etc passwd

 

useradd 명령어 옵션 및 사용 예시로 사용자들을 혼자서 존재하게 하는게 아니라 팀 으로 하나 이상으 ㅣ그룹에 속속되어 있게 한다.

# man useradd 메뉴얼 알려주기

 

 

< 알파적으로 > 

 

www.hanumoka.net/2019/09/26/ubuntu-20190926-ubuntu-grant-root/

 

< 파일 권한 부여>

jhnyang.tistory.com/11?category=815412

 

 

< 서버에 아나콘다 설치>

dambi-ml.tistory.com/6

datainsider.tistory.com/33

hansworld.co.kr/AII/1038

<pycharm ssh 연동>

하기전에 먼저 ssh 가 설치 되어있는지 확인하기.

smprlab.tistory.com/30

 

Pycharm pro버전으로 서버 PC 환경의 python 인터프리터 사용하여 원격 빌드하기

Pycharm은 대학생 또는 대학원생에게 pro 버전을 사용할 수 있는 1년 라이센스를 무료로 제공한다. https://www.jetbrains.com/student/ 위 링크에서 학교 계정 이메일을 통해 인증을 받아 라이센스를 얻을 수

smprlab.tistory.com

 

hanseokhyeon.tistory.com/entry/Pycharm-Docker%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EA%B0%9C%EB%B0%9C-%EC%A4%80%EB%B9%84?category=854705

 

Mac + Pycharm professional로 딥러닝 서버 Docker로 돌리기!

구글은 모든 애플리케이션을 Docker container 기반으로 실행하고, 무려 매주 20억개 컨테이너를 가동한다고 한다. 그만큼 Docker가 대세가 되어가는 만큼 Docker를 기반으로 개발환경을 세팅해보자. 0. D

hanseokhyeon.tistory.com

naniri.tistory.com/18

 

PYCHARM interpreter 서버와 연결하기

파이참실행 후 File->Settings Project -> Project Interpreter 에서, 빨간색 화살표부분 설정 클릭 -> add SSH Interpreter에서 빨간색 부분에 IP및 서버 계정 입력 빨간부분에 패스워드 입력 1. 빨간 화살..

naniri.tistory.com

 

somjang.tistory.com/entry/Python-Pycharm%EC%97%90-%EC%9B%90%EA%B2%A9-%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0-%EC%B6%94%EA%B0%80%ED%95%98%EA%B3%A0-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0

 

[Python] Pycharm에 원격 인터프리터 추가하고 적용하기!

[AWS] yum을 활용하여 Amazon Linux 2 AMI 에 Python 3.x 설치하기! 1. yum 패키지 업데이트 먼저 yum 패키지를 업데이트 합니다. $ sudo yum update -y 2. Python 3.x / pip3 설치 yum 패키지를 활용하여 python..

somjang.tistory.com

 

< 텐서플로우 설치 >

goodtogreate.tistory.com/entry/TensorFlow-GPU-%EB%B2%84%EC%A0%84-%EC%9A%B0%EB%B6%84%ED%88%AC-1604%EC%97%90-%EC%84%A4%EC%B9%98-%ED%95%98%EA%B8%B0?category=620143

< 멀티 gpu 사용법>

blog.ksc.re.kr/157

 

< 참고 딥러닝 공부 >

www.kaggle.com/youhanlee/code

Applied unsupervised learning with python 책을 기반으로 작성된 글입니다.

 

장바구니 분석의 기본적인 아이디어는 고객의 행동 패턴이나 제품 간의 관계에 대한 통찰을 끌어낼 수 있을 정도로 충분하게 함께 판매되는 제품 또는 제품 그룹 간의 관계와 빈도를 분석하는데 있다.

 

장바구니는 경제 시스템 내에 존재하는 유지되는 상품의 집합이다. 유지 된다는 말은 카탈로그에서 없애기 전까지는 계속 구매가 가능하다는 말로 이해하면 된다. 제품에는 일반적으니 모든 상품이나 서비스가 속할 수 있으며 경제 시스템은 하나의 회사나 행동 주체, 심지어 국가도 이에 해당할수 있다.

7장에 배운 토픽 모델에서는 자주 발생하는 단어 그룹을 찾았다면 이번 장에서는 자주 발생하는 제품 그룹을 찾는 형태이다. 따라서 토픽 모델에서의 단어 클러스터링이 장바구니 분석에 활용될 수 있다. 하지만 가장 큰 차이점은 장바구니에서의 클러스터는 몇개의 제품만 포함하는 작은 단위라는 점이며 클러스터 내 항목의 순서가 확률적 지표를 계산할 때 중요하다는 점이다. 이런 지표가 무엇을 의미하고 어떻게 계산하는지를 살펴 보겠다. 또한 장바구니 분석을 하기전에 요구되는 사항으로는 아이템의 컬렉션으로 구성된 리스트 형태의 데이터를 말한다.

 

 활용 사례

전통적인 소매업에서 적용할 수 있는 3가지 분야로는 1. 가격 개선 2. 쿠폰과 할인 추천 3. 매장의 배치 이다. 

모델을 사용해 제품 간의 관계를 알아내면 이를 전략적으로 활용해 제품을 배치하면 고객들이 더 많은 제품을 구매하도록 유도할 수있다. 둘 이상의 제품 간 관계가 충분히 강하고 단독으로는 잘 구매되지 않는 특성을 가진 제품(예를 들면 고기와 야채)이라면 이를 매장에서 서로 먼곳으로 배치하여 고객들이 두 제품을 구매하러 가면서 다른 제품도 중간에 구매할수 있게 유도할 수 있다. 반대로 관계가 약한 두 제품을 옆에 나란히 배치하면 이를 통해 추가적으로 구매를 유도할 가능성이 있다. 예를 들면 기저귀와 맥주 미국에 아기를 가진 아버지가 매장에 와서 기저귀를 고르고 맥주를 사는 사람이 많은것을 확인하고 바로 옆에 두고 판매를 하니 대부분이 기저귀를 구매하고 맥주를 구매하는 분들이 많았다 라는 것을 예로 들수가 있다. 

가격 개선과 쿠폰 및 할인 추천은 모두 상품의 가격을 다룬다는 측면에서 유사한 전략이다. 다시말해 어떤 제품은 가격을 올리고 어떤 제품은 가격을 내릴 것인가로 설명가능하다. 연관성이 높은 두제품을 생각해보면 이 두 제품은 함께 구매 될 가능성이 높기 떄문에 두 제품 중 하나의 가격을 올리더라도 함께 구매가 이뤄지면서 수익성이 개선 될 수 있다. 하지만 일반적으로 제품의 가격을 올리면 구매 빈도가 감소할 가능성이 있지만 연관성이 높은 상품이라면 risk(위험성)은 줄어든다. 비슷한 방식으로 관련이 별로 없는 제품에 대해서는 한 제품을 구매할 때 나머지 제품의 할인이나 쿠폰을 제공해 구매를 유도 할 수도 있다.

1. 중요한 확률 지표

- 장바구니 분석은 다양한 확률 지표를 기반으로 계산하는데 5가지 지표로는 1. 지지도 2. 신뢰도 3. 향상도 4. 레버리지 5. 확신 로 구성 된다.

1. 지지도 

 - 단순히 아이템 세트가 데이터 내에 나타날 확률로 전체 거래 횟수에 대한 해당 아이템 세트의 거래 횟수 비중으로 간단하게 계산할수 있다. (단 아이템 세트는 단일 또는 묶음 일수 있다.)

- 지지도는 매우 단순하지만 신뢰도 및 연관의 강도를 판단하는데 있어서 중요한 지표이다.

- 지지도는 확률이므로 값의 범위는 [0-1]이다. 

Support(X =>Y) = Support(X,Y) = P(X,Y) = Frequency(X,Y) / N

example) 샘플 데이터가 10개중에 우유와 빵이 함께 나온 데이터를 세어보면 4번 동시에 판매 되었다. 그러면 지지도는 4/10 으로 0.4로 쉽게 계산 가능하다.

2. 신뢰도

- 신뢰도 지표는 기본적으로 제품 A의 구매에 따른 제품 B의 구매 확률이기 때문에 조건부 확률 측면으로 생각해야한다. 신뢰도는 일반적으로 A=>B로 표기하며, A가 포함된 거래에 B가 포함되는 비율을 표현한다. 

- 신뢰도도 확률이므로 값의 범위는 [0-1]이다.

Confidence(X=>Y) = P( Y | X ) = Support(X,Y) / P(X)  = Frequency(X,Y) /N / Frequency(X) / N

즉 , Frequency(X,Y) / Frequency(X) 로 나타낼 수 있다.

example) 맥주 와인 아이템 중 특히 맥주 => 와인의 신뢰도를 계산해보자.

일단 맥주를 포함하는 거래를 식별한다. 거래는 3건이며 거래 2, 6, 7번이 해당하며 이 해당 거래 중에 얼마나 와인이 많이 포함 됐는지를 살펴보면 되는데 결과는 모든 거래에 와인이 포함 돼 있다. 따라서  맥주 => 와인 신뢰도는 1이다. 즉 고객이 맥주를 살 때 항상 와인을 함께 샀다는 의미이다.

3. 항상도(Lfit) 와 레버리지(Leverage)

- 두 지표는 동일한 질문의 답을 찾는다. 신뢰도처럼 향상도와 레버리지는 A=>B로 표현한다. 하지만 답을 찾는 질문은 " 하나의 항목 A가 다른 항목 B와 관련된 항목을 결정하는데 사용할 수 있는가 여부이다." 다시말해 어떤 소비자가 A 제품을 구매하는 경우 제품 B를 구매할지 여부를 어느정도 정도의 확신을 갖고 말할 수 있는 가? 이다. 

- A와 B가 독립적이지 않은 것으로 가정되는 표준 사례에서 A와 B의 지지도두 제품의 독립적으로 가정될 때를 비교함으로써 답을 찾을수 있다.

- 항상도는 두 사례의 비율로 계산되기 때문에 가질 수 있는 값의 범위는 [0, Infinity]이다. 만일 향상도의 값이 1이면 두제품은 서로 독립적이라는 의미이다. 그래서 제품 A의 구매가 제품 B의 구매에 미치는 영향은 없다라는것이다.

Lfit(X=>Y) = Support(X,Y) / (Support(X) * Support(Y)) = P(X,Y) / (P(X) * P(Y))

-레버리지는 두 케이스 간의 차이를 계산하기 때문에 값의 범위는 [-1, 1]이다. 레버리지가 0이면 향상도가 1일때 상황이다.

Leverage(X=>Y) = Support(X,Y) - (Support(X) * Support(Y)) = P(X,Y) - (P(X) * P(Y))

>> 위 지표값은 아이템간의 고나계 강도나 방향을 측정한다.

만일 향상도 값이 0, 1 이라면 두 아이템간의 관계는 부정적인 방향을 강하다고 할수 있다. 한 아이템을 구매하면 나머지는 잘 구매하지 않는다는 의미이다. 양과 음의 관계는 독립성과는 분리된다. 그래서 향상도가 1경우 레버리지가 0인 경우로 부터 멀어질수록 연관성이 강해진다.

 

4. 확신

- 다른 지표에 비해 덜 직관적이다. 확신은 X와 Y가 부정확한 예측 빈도와 무관한 경우, Y의 발생과 무고나하게 X가 발행하는 예상 빈도의 비율이다. 

- 값의 범위는 [0, Inf] 이다

Conviction(X=>Y) = ( 1 - Support(Y)) / (1 - Confidence(X=>Y)) 이다.

example) 반대 관계인 와인 =>맥주를 생각해보자.  Support(Y) 이번 경우라면  Support(맥주)는 3/10 이고 확신 X=>Y는 신뢰도 와인 => 맥주는 3/4dlek. 따라서 확신 :  와인 => 맥주는 [] 이다. 만일 와인과 맥주가 독립적이라면 와인 => 맥주는 2.8배가 더 부적확 할것이라고 할수있다. 하지만 이전에 업급하길 와인과 맥주 사이의 연관성은 성립한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

토픽 모델링은 컴퓨터와 인간 언어의 관계를 탐구하는 컴퓨터 과학 분야인 자연 언어 처리의 한 부분으로, 텍스트 데이터 셋의 가용성이 증가하면서 인기를 끌고 있다.

NLP는 텍스트, 음성 및 이미지를 포함해 거의 모든 형태의 언어를 다룰 수 있다.

토픽 모델

토픽 모델은 거의 대부분 주제를 사전에 알지 못하기 때문에 비지도 학습 영역에 속한다. 비지도 학습 관점에서 토픽 모델은 클러스터링 알고리즘, 특히 k-평균 클러스터링과 가장 유사하고 시작할 때 주제의 수를 선택한 후 모델에서 해당 주제를 구성하는 단어를 추출한다. 

라이브러리 용도
langdetect 언어 종류 감지
matplotlib.pyplot 기본 도표 그리기
nltk 다양한 자연어 처리 작업
numpy 배열과 행렬 작업
pandas 데이터 프레임 작업
pyLDAvis 잠재 디리클레 할당 모델의 결과 시각화
pyLDAvis.sklearn pyLDAvis를 sklearn 모델과 함께 실행
regex 정규표현식 작성 및 실행
sklearn 머신러닝 구축

토픽 모델 개요

잠재적으로 관련이 있는 대량의 텍스트 데이터를 분석할 때 토픽 모델이 좋은 해법이 될 수 있다. 여기에서 연관된 데이터라는 것은 이상적으로 동일한 출처의 문서를 의미한다.

토픽 모델은 문서 모음으로부터 말뭉치(corpus)라는 부르는 단어들을 사용해 추상적인 주제를 식별한다. 즉 문장에 급여나 직원, 회의라는 단어가 포함돼 있다면 그 문장은 일에 관한 것이라고 가정한다고 생각해도 무방하다. 

토픽모델은 동일한 문서에 있는 단어가 연관돼 있다고 가정하고 가정하고 그 가정을 사용해 반복적으로 유사하게 나타나는 단어 그룹을 찾아 추상적인 주제를 정의한다. 이와 같이 이러한 모델은 감지되는 패턴이 단어로 구성돼 있는 고전적인 패턴 인식 알고리즘이다.

토픽 모델링 알고리즘에 4가지 단계

1. 토픽의 수를 정의한다.(모델을 피팅하기 전에 주제의 수를 선택)

2. 문서를 스캔하면서 동시에 등장하는 단어나 구절을 인식한다.

3. 문서의 특성을 나타내는 단어의 클러스터를 스스로 학습한다.

4. 말뭉치를 단어 클러스터로 특성화하는 추상 토픽을 출력한다.

- 일반적인 토픽 모델링 작업 흐름

일반적인 토픽 모델링 작업 흐름

> 가능한 최적의 주제 수를 선택해야 모델이 미리 정의된 주제 수의 제약하에 말뭉치에 가장 적합한 단어 그룹을 찾기 때문이다. 주제 수가 너무 많으면 주제가 부적절하게 좁아지면서 지나치게 세분화된 주제는 오버쿡드 라고 말한다. 마찬가지로 주제의 수가 너무 적으면 주제가 일반적으로 모호해지고, 위 상황을 언더쿡드 라고 말한다.

토픽 모델의 주요 특징

- 특정한 단어 또는 한 구절의 주제를 생성하지 않고 각각 추상 주제를 나타내는 단어 모음을 생성한다

- 직접 내용을 확인하지 않은 문서에 대해서도 주제를 예측해낼 수 있다. (단 문서에 학습 데이터에 없는 단어가 있는 경우 모델은 학습 데이터에서 식별된 주제 중 하나에 연결된 경우에도 해당 단어를 처리할 수 없다.) 그래서 예측보다는 탐색 분석 및 추론에 더 많이 사용되는 경향이 있다.

- 토픽 모델링을 논의할때 주제를 나타내는 단어 그룹이 개념적으로 연관된 것이 아니고 근접성으로만 연관된 것이라는 사실을 지속적으로 강화하는 것이 중요하다. 

* 근접성의 판단

- 동일한 문서에 등장하는 모든 단어는 관련이 있다는 가정에 따르면 자주 근접하는 단어는 주제를 정의하기에 충분하다. 하지만 위 방법의 가정이 일관된 주제를 형성하기에 너무 일반적일 수도 있다. 

* 추상적인 주제를 해석 할려면

- 텍스트 데이터의 고유 특성과 생성된 단어 그룹을 균형 있게 조정해야한다. 

* 추가로 고려할점

- 텍스트 데이터가 갖는 기본적인 노이즈 특성으로 인해 토픽 모델이 주제 중 하나와 관련이 없는 단어를 해당 주제에 지정할 수도 있다.

 

토픽 모델링의 알고리즘 

1. 잠재 디리클레 할당(LDA)

2. 음수 미포함 행렬 분해(NMF)

 

비지니스 활용

- 제약 사항이 있음에도 토픽 모델링은 적당한 곳에 제대로 사용하면 사업적인 가치를 이끌어낼 수 있는 실행 가능한 통찰을 제공하며 예를 들면 개인이 이전에 읽은 글을 토대로 구성된 모음을 사용해 토픽 모델은 독자가 읽기 원하는 글의 유형을 알려준다. 이는 사용자에게 단순성과 사용 편의성을 높여주는 맞춤형 큐레이션이다.

 

연습 1

1. 데이터 로드

//필요한 모듈 임포트

import langdetect
import matplotlib.pyplot
import nltk
import numpy
import pandas
import pyLDAvis
import pyLDAvis.sklearn
import regex
import sklearn

// 전처리 과정에서 사용될 2개의 사전을 로드

nltk.download('wordnet')
nltk.download('stopwords')

// 데이터 로드

path = "News_Final.csv"
df = pandas.read_csv(path, header=0)

// 데이터 모양과 열들을 출력한다.

def dataframe_quick_look(df, nrows):
    print("SHAPE:\n{shape}\n".format(shape=df.shape))
    print("COLUMN NAMES:\n{names}\n".format(names=df.columns))
    print("HEAD:\n{head}\n".format(head=df.head(nrows)))

dataframe_quick_look(df, nrows=2)

// Topic열에는 실제로 토픽 모델이 확인하려는 정보가 포함돼 있다. 그래서 자체적으로 주제를 생성한 후 이를 제공된 주제 데이터와 서로 결과를 비교할수 있게 미리 고유한 주제와 발생 횟수를 출력

print("TOPICS:\n{topics}\n".format(topics=df["Topic"].value_counts()))

 

// 헤드라인 데이터를 추출하고 추출된 데이터를 리스트(list) 오브젝트로 변환한다. 그 후 출력을 해본다.

raw = df["Headline"].tolist()
print("HEADLINES:\n{lines}\n".format(lines=raw[:5]))
print("LENGTH:\n{length}\n".format(length=len(raw)))

2. 텍스트 데이터 정리

// 텍스트가 영어인지 아닌지 식별하는 함수

def do_language_identifying(txt):
try:
 the_language = langdetect.detect(txt)
except: 
the_language = 'none'
return 
the_language

// 표제어를 추출하는 함수

def do_lemmatizing(wrd):
out = nltk.corpus.wordnet.morphy(wrd)
 return 
(wrd if out is None else out)

// 메인 전처리 함수 코드

def do_headline_cleaning(txt):
# 언어를 식별한다.
# 영어가 아니면 return을 null 로 한다. 
    lg = do_language_identifying(txt)
    if lg != 'en': 
        return None
# 공백을 사용해 문자열을 토큰이라고하는 조각으로 나눈다.
    out = txt.split(" ")
# URL(http:s)을 식별해 "URL"이라는 문자열로 교체
    out = ['URL' if bool(regex.search("http[s]?://", i)) else i for i in out]
# 정규 표현식을 사용해 모든 문장 부호와 줄 바꾸기 기호를 빈문자열로 교체
    out = [regex.sub("[^\\w\\s]|\n", "", i) for i in out]
# 정규 표현식을 이용해 숫자를 모두 빈문자열로 교체
    out = [regex.sub("^[0-9]*$", "", i) for i in out]
# 모든 대문자를 소문자로 변경(복잡도를 줄이기 위해서)
    out = [i.lower() if i not in "URL" else i for i in out]
# URL이라는 문자열을 제거하자(왜냐 문자열과 주제 사이에 연결이 발생할 가능성이 있어서)
    out = [i for i in out if i not in "URL"]
# ntlk에서 stopwords을 불러와 stopwords를 제거
    list_stop_words = nltk.corpus.stopwords.words("English")
    list_stop_words = [regex.sub("[^\\w\\s]", "", i) for i in list_stop_words]
    out = [i for i in out if i not in list_stop_words]
# 각 헤드라인에 적용할 수 있는 함수를 정의해 표제어 추출 이때 wordnet사전을 불러서 사용
    out = [do_lemmatizing(i) for i in out]
# 토큰 목록에서 길이가 4 미만인 단어를 제거한다.(이는 대체로 짧은 단어는 일반적인 단어이고 주제와 관련이 적다는 가정을 전제로 한다.) 
    out = [i for i in out if len(i) >= 5]
    return out

clean = list(map(do_headline_cleaning, raw))

clean = list(filter(None.__ne__, clean))
print("HEADLINES:\n{lines}\n".format(lines=clean[:5]))
print("LENGTH:\n{length}\n".format(length=len(clean)))

// 각 헤더라인에 대해 공백을 사용해 토큰들을 연결한다.

clean_sentences = [" ".join(i) for in clean]
print(clean_sentences[0:10])

 

1) 잠재 디리클레 할당(LDA)

- 주어진 문서에 대하여 각 문서에 어떤 주제들이 존재하는지를 서술하는 대한 확률적 토픽 모델 기법 중 하나이며, 미리 알고 있는 주제별 단어수 분포를 바탕으로, 주어진 문서에서 발견된 단어수 분포를 분석함으로써 해당 문서가 어떤 주제들을 함께 다루고 있을지를 예측할 수 있다.

- LDA는 생식 확률 모델이며, 확률로 표현된 데이터를 생성한 프로세스를 알고있다고 가정한 다음 데이터로 부터 이를 생성한 매개변수를 역으로 찾는 작업이다.

LDA에서 중요한 가정

 - 단어의 교환성(exchangeability)이다. 이는 '단어 주머니(bag of words)'라고 표현하며, 교환성은 단어들의 순서는 상관하지 않고 오로지 단어들의 유무만이 중요하다는 가정이다. 예를 들어, 'Apple is red'와 'Red is apple' 간에 차이가 없다고 생각하는 것이다. 단어의 순서를 무시할 경우 문헌은 단순히 그 안에 포함되는 단어들의 빈도수만을 가지고 표현이 가능하게 된다. 이 가정을 기반으로 단어와 문서들의 교환성을 포함하는 혼합 모형을 제시한 것이 바로 LDA이다. 하지만 단순히 단어 하나를 단위로 생각하는 것이 아니라 특정 단어들의 묶음을 한 단위로 생각하는 방식(n-gram)으로 LDA의 교환성 가정을 확장시킬 수도 있다.

LDA 모델의 그래픽 표현

- M개의 문서가 주어져 있고, 모든 문서는 각각 k개의 주제중 하나에 속할때, 문서는 N개의 단어의 연속이며, 전집은 M개의 문서의 집합이며, 생성 프로세스는 말뭉치의 모든 문서에 대해 실행됐으므로 M으로 표시된 가장 바깥쪽 플레이트는 각문서에 대한 반복을 나태낸다. 마찬가지로 단어에 대한 반복은 N으로 표기된 다이어그램의 가장 안쪽 프레이트로 표시된다. 원은 매개변수와 분포, 결과를 나타내고 w로 표시된 음영 처리된 원은 선택된 단어로, 유일하게 알고 있는 데이터 조각이므로 생성 과정을 역으로 엔지니어링 하는 데 사용된다.

- 4가지 변수

* α : 주제 문서 디리클레 배포용 하이퍼파라미터

* β : 각 주제에 대한 단어의 분포

* Z : 주제에 대한 잠재 변수

* θ : 각 문서의 주제 배포를 위한 잠재 변수

>> αβ는 문서 내 주제와 주제 내 단어의 빈도를 제어한다. 만일 α가 증가하면 각 문서의 주제 수가 증가함에 따라 문서가 점점 유사해진다. 반면에 α가 줄어들면 각 문서의 주제 수가 감소함에 따라 문서의 유사성이 낮아진다. β 또한 비슷하게 동작한다.

변분 추론

LDA가 가진 큰 문제는 조건부 확률, 분포의 평가를 관리할 수 없으므로 직접 계산하는 대신 확률을 추정한다는 점이다. 

변수 추론은 더 간단한 근사 알고리즘 중 하나지만 확률에 관한 상당한 지식을 필요로 하는 광범위한 파생이 존재한다.

변수추론은 각 문서의 각 단어를 주제 중 하나에 무작위로 할당해 시작하고 각 문서와 각 문서의 각 단어에 대한 두 비율을 계산하며 이 두 비율 중 하나는 문서에 대한 주제의 비율 P(Topic | Document)이며, 나머지 하나는 주제에 대한 단어의 비율 P(Word | Topic)이다. 이 두 비율을 곱하고 결과 비율을 사용해 단어를 새 주제에 할당하고 주제 할당이 크게 변하지 않는 정상 상태에 도달할 때까지 이 과정을 반복한다. 이후에 문서 내 주제 혼합 및 주제 내 단어 혼합을 추정하는데 사용된다.

변수 추론의 목적

- 실제 분포가 다루기 어려운 형태일 때, 초기 분포와 매우 유사하면서도 다루기 쉬운 간단한 변형 분포를 사용하려는  데 있다.

 

Bag of words

- 텍스트는 머신 러닝으로 전달 할수 없어서 먼저 숫자 형태로 인코딩을 해야한다. 머신러닝에서 텍스트를 사용하는 간단한 방법은 Bag of words 모델을 사용하는 것이다.

- 이 모델은 단어 순서에 관한 모든 정보를 제거하고 각 단어의 존재하는 정도(횟수 또는 빈도)에 중점을 둔다.

Bag of words 데이터 구조로 변환하기 위해 CountVectorizer를 실행 예제

number_words, number_docs, number_features를 정의하며 첫 두개의 변수는 LAD 결과의 시각화를 제어하며 마지막 인자는 특징 공간에 유지할 단어의 수를 제어한다.

number_words = 10
number_docs = 10
number_features = 1000

카운트 벡터라이저를 실행하기 전에 입력값을 세가지 max_df, min_df, max_features이다. 이들 매개변수는 말뭉치의 단어 수를 모델에 영향을 줄 수 있는 수준까지 추가 필터링을 한다. 적은 수의 문서에만 등장하는 단어는 주제에 속하기 너무 드물기 때문에 이를 제거하기 위해 min_df는 지정된 수보다 적은 수의 문서에 등자하는 단어를 버리는데 사용된다. 너무 많은 문서에 나타나는 단어는 특정 주제와 연결될 만큼 구체적이지 않으므로 max_df는 지정된 백분율보다 더 많은 문서에 등장하는 단어를 버리기 위해 사용된다. 마지막으로 너무 과한 모델 피팅을 원치는 않으므로 모델에 맞는 단어의 수는 가장 자주 발생하는 지정된 수(max_features)로 제한한다.

vectorizer1 = sklearn.feature_extraction.text.CountVectorizer(
    analyzer="word",
    max_df=0.5
    min_df=20
    max_features=number_features
)
clean_vec1 = vectorizer1.fit_transform(clean_sentences)
print(clean_vec1[0])

벡터라이저에서 항상 이름과 단어를 추출한다. 모델은 단어를 숫자로 인코딩된 형래로만 제공하므로 형상 이름 벡터를 결과와 병합하면 해석이 쉬워진다.

feature_names_vec1 = vectorizer1.get_feature_names()

퍼블렉서티

- 모델에는 일반적으로 성능을 평가하는 데 활용할 수 있는 지표가 있다. 성능에 대한 정의가 살짝 다르다. 회귀 및 분류에서 예측값은 성과에 대한 명확한 측정값을 계산할 수 있는 실제값과 비교할 수 있다. 토픽 모델을 사용하면 모델이 학습한 단어만 알기 때문에 동일한 주제를 사용하더라도 새 문서에 해당 단어가 포함되지 않을 수 있으므로 예측의 신뢰성이 떨어진다. 이러한 차이로 인해 토픽 모델은 퍼플렉서티라는 언어 모델에 특화된 지표를 사용해 평가한다.

-퍼플렉서티는 PP라고 줄여 부르고, 주어진 단어를 평균적으로 따를 수 있는 가장 가능성이 높은 다른 단어들의 수를 측정한다.

평균적으로 가장 가능성이 높은 소수의 단어들이 뒤따를 수 있는 단어가 더 구체적이고 주제와 더 밀접하게 연관될 수 있다는 생각을 할수 있다. 이와 같이 낮은 퍼플렉서티 점수는 더 나은 언어 모델임을 의미하며, 더 나은 최적의 주제 수를 선택하는데 사용할 수 있다.

n은 단어의 나열에 속한 단어의 수를 의미한다.

연습 : 주제 선택

- LDA는 2개의 입력을 가진다. 첫 번째는 문서 자체이며, 두 번째는 주제의 수이다. 

최적의 수를 찾는 방법

- 여러 개의 주제를 검색하고 가장 퍼플렉서티 값이 작은 주제 수를 선택하는 것이다. 위 방식을 격자 검색이라고 한다.

// 다양한 주제에 LDA 모델을 피팅하는 함수를 정의하고 퍼플렉서티 점수를 계산하고 주제와 퍼플렉서티 점수의 데이터 프레임이고 또다른 하나는 최소 퍼플렉서티 점수를 갖는 주제의 수의 데이터프레임을 반환한다.

def perplexity_by_ntopic(data, ntopics):
    output_dict = {
        "Number Of Topics": [], 
        "Perplexity Score": []
    }
    
    for in ntopics:
        lda = sklearn.decomposition.LatentDirichletAllocation(
            n_components=t,
            learning_method="online",
            random_state=0
        )
        lda.fit(data)
        
        output_dict["Number Of Topics"].append(t)
        output_dict["Perplexity Score"].append(lda.perplexity(data))
        
    output_df = pandas.DataFrame(output_dict)
    
    index_min_perplexity = output_df["Perplexity Score"].idxmin()
    output_num_topics = output_df.loc[
        index_min_perplexity,  # 인덱스
        "Number Of Topics"  # 컬럼 
    ]
        
    return (output_df, output_num_topics)

//퍼플렉서티 함수 실행

df_perplexity, optimal_num_topics = perplexity_by_ntopic(
    clean_vec1, 
    ntopics=[1, 2, 3, 4, 6, 8, 10]
)
print(df_perplexity)

// 시각화

df_perplexity.plot.line("Number Of Topics""Perplexity Score")

그림으로 보았을때, 퍼플렉서티를 통한 최적의 주제 수는 3개이다. 하지만 위에서 Topic에 포함된 주제 수는 4개였다. 그래서 3개가 반환된 이유가 있다 그 이유는 잠시뒤에 다루겠다.

+ Recent posts