반응형

가끔 드래그하여 복사 붙여넣기를 하려고 할 때 안되는 웹사이트들이 있습니다.

이런 상황에서 사용할 수 있는 유용한 방법을 알려드리도록 하겠습니다.

 

드래그가 막혀있는 사이트에서 드래그 할 수 있는 방법
1. 복사 붙여넣기 하려는 웹사이트 접속

 

2. F12키 누르기

 

3. 우측 상단의 톱니바퀴 모양(설정) 누르기

 

4. Settings의 Preferences 탭에서 아래로 쭉 내려 Debugger로 이동하기

 

5. Disable JavaScript에 체크하기
6. 드래그 하고 싶은 부분 드래그 하기

 

7. 복사 붙여넣기가 끝나면 Disable JavaScript 다시 해제해 주기

이렇게 하면 드래그가 가능합니다.

다 끝나면 다시 해제해 주는거 잊지 마세요!

자바스크립트 사용을 해제해 놓는 거라서

다시 해제하지 않으면 사이트 내 클릭 등 주요 기능이 안될 수 있습니다.

이제 어디서든 코드를 Ctrl+c Ctrl+v 할 수 있습니다.

반응형

'기타' 카테고리의 다른 글

Tistory 블로그에 html 파일을 iframe으로 삽입하기  (1) 2022.03.15
반응형

안녕하세요.

크롤러를 만들다 보면,

내가 가져오고 싶은 부분이 어디에 위치해 있는지 알아야 할 때가 있습니다.

그 때 개발자도구를 사용하면 해당 사이트 html의 어느 부분에 있는지 금방 파악이 가능합니다.

지금부터 그 방법을 같이 알아보도록 하겠습니다.

 

여기에서 사용할 예시 사이트는 네이버 뉴스의 어느 한 기사 입니다.

- 예시 사이트: https://n.news.naver.com/article/666/0000019702

위의 사이트를 클릭해서 들어가 주세요.

위와 같은 기사가 보일 것입니다.

1. F12키를 눌러 개발자 도구 열기

우리가 만약 기사 제목을 수집하고 싶다고 가정해 봅시다.

제목을 가져오려면 html에 어디에 제목이 위치해 있는지 알아야 할 것입니다.

이 때 개발자 도구를 열어줍니다.

개발자 도구는 F12키를 누르면 확인할 수 있습니다.

위와 같이 우측에 창이 생길 것입니다.

하지만 소스 코드 전체를 한눈에 보기엔 어려움이 있습니다.

제목 또한 어디에 있는지 알기 어렵습니다. 

이럴 때는 요소를 클릭하면 바로 알 수 있습니다.

 

2. 요소 선택하기

위의 개발자 도구 창을 보면 좌측 상단에 커서 아이콘이 보입니다.

이 아이콘은 페이지에서 요소를 선택해 검사할 수 있는 기능을 가지고 있습니다.

위의 사진에서 빨간색 박스로 표시된 아이콘을 클릭 후 왼쪽에 기사에 내가 확인하고 싶은 기사에 커서를 가져가면

아래 사진과 같이 파란색으로 표시가 됩니다.

그후 오른쪽 창을 보면 아까는 보이지 않았던 제목 부분이 보입니다.

여기서 원래대로라면 body 밑에 div class name이 end_container인것 밑에 div ct_wrap 밑에 ct_scroll_wrapper 밑에 newsct... 밑에 이런 식으로 쭉쭉 타고 내려가서 h2에 span 에 제목이 위치해 있는 것을 확인할 수 있겠습니다만 귀찮고 복잡합니다.

이렇게 하나하나 눈으로 봐도 되지만 이 대신에  copy selector를 사용하면

더 간단하게 Beautiful Soup의 html selector를 사용해서 바로 가져올 수 있습니다.

3. selector 복사하기

copy selector는 간단합니다.

아까 찾은 개발자 도구에서 제목부분 우클릭을 하고 Copy(복사) 클릭, Copy selector 클릭하면 복사가 됩니다.

이렇게 하고 Ctrl+V를 해서 붙여넣기를 하면 아래와 같이 복사됩니다.

#title_area > span

위의 뜻은 id가 title_area 아래의 span 태그에 제목이 위치해 있다는 것을 뜻합니다.

이것을 만약 Beautiful Soup의 select로 가져오려면 아래처럼 작성하면 제목을 가져오는 것을 확인할 수 있습니다.

#크롤링시 필요한 라이브러리 불러오기
from bs4 import BeautifulSoup
import requests

#테스트 기사
test_url = "https://n.news.naver.com/article/666/0000019702"

# ConnectionError방지
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/98.0.4758.102"}

news = requests.get(test_url,headers=headers)
news_html = BeautifulSoup(news.text,"html.parser")

title = news_html.select("#title_area > span")
title
 

결과: [<span>폭염으로 닭 폐사에 크기까지 줄어든 계란…“왕란이 사라졌다”</span>]

 

이런 식으로 다른 부분들도 개발자 도구를 이용하면 간단하게 가져올 수 있습니다.

반응형
반응형
IPv6

IPv4의 기존 32bit 주소 공간이 인터넷 사용자 증가에 따라 고갈되어 128bit 주소 공간을 제공하는 IPv6가 등장하게 되었다.

IPv6는 네트워크의 물리적 위치에 제한받지 않고 같은 주소를 유지한다.

 

패키지 다이어그램(Package Diagram)

시스템의 서로 다른 패키지들 사이의 의존관계를 표현하기 위한 다이어그램. 패키지와 의존관계로 표현한다.

- 참고자료

https://www.uml-diagrams.org/package-diagrams-overview.html

 

UML package diagrams overview - common types of package diagrams - package diagrams and model diagrams.

UML Package Diagrams Overview Package diagram is UML structure diagram which shows structure of the designed system at the level of packages. The following elements are typically drawn in a package diagram: package, packageable element, dependency, element

www.uml-diagrams.org

 

DB 회복기법

- 로그 기반 회복 기법

  • 지연 갱신 회복 기법: 트랜잭션이 완료되기 전까지 데이터베이스에 기록하지 않는 기법
  • 즉각 갱신 회복 기법: 트랜잭션 수행 중 갱신 결과를 바로 데이터베이스에 반영하는 기법

- 체크포인트 회복 기법: 장애 발생 시 검사점 이후에 처리된 트랜잭션에 대해서만 장애 발생 이전의 상태로 복원시키는 회복 기법

- 그림자 페이징 회복 기법: DB 트랜잭션 수행 시 복제본을 생성하여 데이터베이스 장애 시 이를 이용해 복구하는 기법

 

네트워크 공격 기법

 

이름 설명
스니핑(Sniffing) 공격 대상에게 직접 공격을 하지 않고 데이터만 몰래 들여다보는 공격 기법(수동적)
네트워크 스캐너, 스니퍼 네트워크 HW,SW 구성의 취약점 파악을 위해 공격자가 취약점을 탐색하는 공격 기법
패스워드 크래킹(Password Cracking) 아래와 같은 공격을 활용함
- 사전(Dictionary) 크래킹: ID와 PW가 될 가능성이 있는 단어를 파일로 만들어 놓고 이 파일의 단어를 대입하여 크랙하는 공격 기법
- 무차별 크래킹: PW로 사용될 수 있는 영문자, 숫자, 특수문자 등을 무작위로 대입하여 비번을 알아내는 공격 기법
- 패스워드 하이브리드 공격: 사전 , 무차별 대입 공격을 결합하여 공격하는 기법
- 레인보우 테이블 공격: 비번별로 해시값을 미리 생성하여 테이블에 모아 두고, 크래킹하고자 하는 해시값을 테이블에서 검색해서 역으로 비번을 찾는 공격 기법
IP 스푸핑(IP Spoofing) 침입자가 인증된 컴퓨팅 시스템인 것처럼 속여서 타깃의 시스템 정보를 빼내기 위해 본인의 패킷 헤더를 인증된 호스트의 IP 주소로 위조해 타깃에 전송하는 공격 기법
ARP 스푸핑 공격자가 특정 호스트의 MAC 주소를 자신의 MAC 주소로 위조한 APR Reply를 만들어 희생자에게 지속적으로 전송하여 희생자의 APR 캐시 테이블에 특정 호스트의 MAC 정보를 공격자의 MAC 정보로 변경, 희생자로부터 특정 호스트로 나가는 패킷을 공격자가 스니핑하는 공격 기법
ICMP Redirect 공격 - 3계층에서 스니핑 시스템을 네트워크에 존재- 하는 또다른 라우터라고 알림으로써 패킷의 흐름을 바꾸는 공격 기법
- 메시지를 공격자가 원하는 형태로 만들어 특정 목적지로 가는 패킷을 공격자가 스니핑하는 공격 기법
트로이 목마 악성 루틴이 숨어 있는 프로그램으로 겉보기에 정상적인 프로그램으로 보이지만 실행하면 악성 코드를 실행하는 프로그램

 

SW 개발 보안의 3요소

 

요소 설명
기밀성(Confidentiality) 인가되지 않은 개인 or 시스템 접근에 따른 정보 공개 및 노출을 차단하는 특성
무결성(Integrity) 정당한 방법을 따르지 않고서 데이터가 변경될 수 없으며, 데이터의 정확성 및 완전성과 고의 또는 악의로 변경되거나 훼손 또는 파괴되지 않음을 보장하는 특성
가용성(Availability) 권한을 가진 사용자나 애플리케이션이 원하는 서비스를 지속해서 사용할 수 있도록 보장하는 특성

 

반응형
반응형

 

디지털 포렌식(Digital Forensics)

: 범죄 행위에 대한 사실을 사법기관에 제출하기 위해 디지털 증거자료를 획득, 분석, 보관, 제출 기록하는 일련의 절차 및 방법을 말함.

디지털 포렌식의 원칙은 정당성, 재현성, 연계성, 신속성, 무결성이 있다.

 

루트킷(Rootkit)

: 해커가 시스템의 민감한 정보를 수집 또는 네트워크상의 다른 시스템을 공격 또는 추적 회피를 위한 중간 지점으로 이용하더라도 로그를 지워버릴 수 있어 탐지하기 어려운 도구를 말한다. 주로 불법적인 해킹에 사용되는 기능을 제공하는 프로그램의 모음.

 

크라임웨어(Crimeware)

: 온라인상에서 범죄와 같은 불법적인 행위를 수행하기 위해 제작된 컴퓨터 프로그램.(공격용 툴킷)

- 악성 코드로 구성된 프로그램이 사용자를 속여 PC에 설치되면 그 안에 있는 정보 수집 또는 자원을 사용하여 다른 대상을 공격하는것에 이용되기도 한다. 
- 키로거, 스파이웨어, 브라우저 하이잭커 등이 크라임웨어에 속한다.

 

개발환경 인프라 구성 방식
방식 설명
온프레미스(On-Premise) 외부 인터넷망이 차단된 상태에서 인트라넷 망만을 활용하여 개발환경을 구축하는 방식
클라우드(Cloud) 아마존, 구글, 마이크로소프트 등 클라우드 공급 서비스를 하는 회사들의 서비스를 임대하여 개발환경을 구축하는 방식.
개발환경 투자비용이 적고 구축 시간이 빠르다.
하이브리드(Hybrid) 온프레미스와 클라우드 방식을 혼용하여 사용.

 

CASE 도구
case 유형 내용
상위 CASE
(Upper CASE)
계획수립, 요구분석, 기본설계 단계를 다이어그램으로 표현
모델들 사이의 모순 검사 및 모델의 오류 검증, 일관성 검증 지원
자료 흐름도 프로토타이핑 작성 지원 및 UI 설계 지원
하위 CASE
(Lower CASE)
구문 중심 편집 및 정적, 동적 테스트를 지원
시스템 명세서 생성 및 소스 코드 생성 지원

 

 

참고자료

수제비 2023 정보처리기사 실기 FINAL 실전 모의고사

반응형
반응형

안녕하세요.

그동안 python으로 여러 프로그램을 만들어 보았는데,

그걸 다른 사람에게도 보여주고 싶을 때는

1. python 설치

2. .py 파일 실행

이렇게 번거로운 과정이 필요할 것입니다.

하지만 그동안 만들었던 .py파일 프로그램을 .exe 파일로 만들 수 있다면

상대방 입장에서도 파일을 다운받아 실행하기만 하면 되니 엄청 간편할 것입니다.

이렇게 python 파일을 exe파일로 만들어주는 라이브러리가 있는데요,

그것은 바로 pyinstaller 라는 라이브러리 입니다.

 

pyinstaller 설치

설치 방법은 간단합니다. 터미널창에 아래와 같이 pip를 사용하여 간단히 설치할 수 있습니다.

pip install pyinstaller

 

pyinstaller 사용 방법

pyinstaller는 터미널에 여러 옵션을 주어 exe파일을 만들 수 있습니다.

그중 유용하게 쓰이는 옵션 몇가지를 알려드리자면,

--noconsole : exe파일 실행 시 콘솔창을 나타나지 않게 하기
--onefile : exe파일을 하나의 파일로 한번에 만들기
--icon: exe파일에 사용할 아이콘을 추가
--add-data: 데이터파일 추가

등등이 있습니다.

--icon 옵션을 사용할 때는 .ico, .png 파일 등등을 사용 가능합니다. 실행파일 아이콘이 되는 것이므로 배경은 투명한 배경의 아이콘이 좋습니다.

위의 몇가지 옵션들을 사용하여 exe 파일을 만든다면, 명령어는 아래와 같습니다.

pyinstaller --noconsole --onefile --icon=파일경로\아이콘.png/ico 파일경로\파이썬파일.py

예를 들어, minigame.py라는 파이썬 파일이 있고, star.png라는 아이콘 파일이 있으면 아래와 같이 작성하면 됩니다.

pyinstaller --noconsole --onefile --icon=star.png minigame.py

물론, 파이썬 파일과 png 파일은 해당 터미널 위치에 두 파일이 모두 있어야 합니다.

그러면 dist 파일 안에 exe파일이 만들어집니다.

 

이미지, 소리파일 등등을 .exe파일에 포함하는 방법

저는 전에 제가 pygame으로 만든 미니게임을 exe파일로 만들어 보도록 하겠습니다.

다만, 게임은 보통 이미지 파일과 효과음 등의 소리파일이 포함되어 있습니다.

저는 이 모든 파일을 하나의 exe파일에 포함을 하고 싶기 때문에 추가로 설정을 해주고 .exe파일을 만들어 보도록 하겠습니다.

1. 파이썬 파일(.py)에 설정값 넣어주기

exe파일로 만들려는. py파일 스크립트 맨 위에 아래와 같이 코드를 추가해줍니다.

import sys,os

if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
    os.chdir(sys._MEIPASS)

2. pyinstaller로 --add-data 파일/폴더 옵션 설정하여 exe파일 만들기 

만약 추가할 이미지 등의 파일이 한가지라면 --add-data 파일경로/파일 이렇게 끝에 옵션을 추가해 주면 됩니다.

저의 경우는 resource라는 폴더 안에 이미지, 소리 등의 파일이 다 들어있어서 폴더를 추가해 주도록 하겠습니다.

제 터미널 위치에 있는 파일 예시는 아래와 같습니다.

pygame/
|--- minigame.py
|--- resources/
     |--- enemy.jpg
     |--- player.jpg
     |--- game_over.wav
     |--- background.wav
     |--- babychick.ico

 

터미널이 위치한 pygame 폴더 안에

minigame.py라는 파이썬 게임파일과,

resources라는 게임을 동작하기 위해 필요한 이미지, 소리파일들이 있습니다.

저는 그리고 exe 아이콘으로 resources 폴더 안에 있는 babychick.ico라는 이미지를 사용하도록 하겠습니다.

(※참고: 아이콘 이미지는 여기에서 찾아서 다운받을 수 있습니다.)

이렇게 exe파일을 만들기 위한 명령어는 아래와 같습니다.

pyinstaller --noconsole --onefile --icon=resources\babychick.ico minigame.py --add-data "resources;resources"

--add -data 를 사용하여 resources폴더를 exe에 추가하였습니다.

그러면,

해당 pygame폴더 위치에 build, dist 등의 폴더가 생기며,(build 폴더는 삭제하셔도 exe 실행하는 데 문제가 없습니다.)

우리가 원하는 exe파일은 dist 폴더에 위치해 있습니다.

이 .exe파일만 따로 빼서 다른 사람들에게 보내면

추가로 파이썬을 설치하거나 할 필요 없이 바로 파일실행으로 게임이 실행됩니다:)

결과물

 

참고자료

https://pyinstaller.org/en/stable/index.html

 

PyInstaller Manual — PyInstaller 5.8.0 documentation

PyInstaller bundles a Python application and all its dependencies into a single package. The user can run the packaged app without installing a Python interpreter or any modules. PyInstaller supports Python 3.7 and newer, and correctly bundles many major P

pyinstaller.org

https://api.arcade.academy/en/latest/tutorials/bundling_with_pyinstaller/index.html

 

Bundling a Game with PyInstaller - Python Arcade 2.6.17

Previous GPU Particle Burst

api.arcade.academy

 

마무리

제가 만든 .exe파일은 소리, 이미지 파일을 추가하다보니 용량이 커져서 실행 시작때 조금 느리지만(259MB 정도 됩니다...)

게임은 실행이 잘 되니 좋습니다:)

여러분들도 한번 그동안 만들었던 파이썬 파일로 실행파일 만들어서

친구,가족분들께 보여주면 좋을 것 같습니다.

반응형
반응형

안녕하세요.

이번에는 저번 pygame포스팅에 이어서 인트로와 아웃트로를 추가해 주도록 하겠습니다.

- 인트로: 게임 설명 및 시작, 종료 버튼 추가

- 아웃트로: 게임 스코어 안내 및 다시시작, 종료 버튼 추가

저번에는 따로 함수를 만들지 않았는데 이번에는

intro, game, outro 함수를 각각 만들어 연결해 보도록 하겠습니다.

이번 게시물의 결과물을 아래에서 미리 확인해 보세요:)

Preview

 

게임 기본 설정
import pygame, sys
from pygame.locals import *
import random, time

pygame.init()

# 초당 프레임 설정
FPS = 60
FramePerSec = pygame.time.Clock()

# 색상 세팅(RGB코드)
RED = (255, 0, 0)
ORANGE = (255, 153, 51)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
SEAGREEN = (60, 179, 113)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
VIOLET = (204, 153, 255)
PINK = (255, 153, 153)

GREY = (213,213,213)
LIGHT_GREY = (246,246,246)
LIGHT_BLACK = (76,76,76)
# 게임 진행에 필요한 변수들 설정
SPEED = 5  # 게임 진행 속도
SCORE = 0  # 플레이어 점수

# 폰트 설정
font = pygame.font.SysFont('Tahoma', 60)  # 기본 폰트 및 사이즈 설정(폰트1)
small_font = pygame.font.SysFont('Malgun Gothic', 20,bold=True)  # 작은 사이즈 폰트(폰트2)
middle_font = pygame.font.SysFont('Malgun Gothic', 40) # 중간 사이즈 폰트(폰트3)
game_over = font.render("GG", True, BLACK)  # 게임 종료시 문구

# 게임 배경화면
background = pygame.image.load('resources/background1.jpg')  # 배경화면 사진 로드

# 게임 화면 생성 및 설정
display_width = 640
display_height = 440
GameDisplay = pygame.display.set_mode((display_width,display_height))
GameDisplay.fill(PINK)
pygame.display.set_caption("Mini Game")

#점수 reset함수
def reset():
    global SCORE
    SCORE = 0
    return SCORE

 

Button 함수 만들기

Intro,outro에 사용할 버튼을 간단하게 만들기 위해 버튼을 만드는 함수를 하나 추가해 줍니다.

이 버튼 함수는 버튼 영역 안에 마우스 포인터가 들어가면 색이 바뀌고 클릭 시 True값을 return 합니다.

더 자세히 설명하자면 아래와 같습니다.

button(버튼안에 들어갈 메세지, x좌표,y좌표, 도형의가로길이,도형의세로길이,도형색, 포인터가 도형위에 위치시 변하는 색, action=True(클릭했을 때 이벤트 활성화), 버튼글씨색 설정 )

#버튼 생성 함수
def button(msg,x,y,w,h,ic,ac,action=None,fcolor=BLACK):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    #print(click)
    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.ellipse(GameDisplay, ac,(x,y,w,h))

        if click[0] == 1 and action != None:
            return True
    else:
        pygame.draw.ellipse(GameDisplay, ic,(x,y,w,h))

    textSurf = middle_font.render(msg,True,fcolor)
    textRect = textSurf.get_rect()
    textRect.center = ( (x+(w/2)), (y+(h/2)) )
    GameDisplay.blit(textSurf, textRect)

 

Intro 만들기

게임 설명 텍스트를 위치시켜주고,

start, quit 버튼을 만들어서

start를 누를 시 게임을 시작하고, quit을 누르면 창이 닫히도록 game_intro 함수를 만들어 주었습니다.

# 시작(intro) 화면
def game_intro():
    intro = True

    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        # 배경화면 사진 게임창에 불러오기(사진, 위치)
        GameDisplay.blit(background, (0, 0)) #TODO
        # 텍스트 생성 및 배치하기
        large_Text = pygame.font.SysFont('Tahoma', 100)
        Text1,Text1Rect = text_objects("How to Play",large_Text)
        Text2,Text2Rect = text_objects("Use ← , → to avoid bombs!",middle_font)
        Text3,Text3Rect = text_objects("방향키 ← , →를 사용하여 폭탄을 피하세요!",small_font)
        Text1Rect.center = ((display_width/2),(display_height/4.5))
        Text2Rect.center = ((display_width/2),(display_height/2.5))
        Text3Rect.center = ((display_width/2),(display_height/2))
        GameDisplay.blit(Text1, Text1Rect)
        GameDisplay.blit(Text2,Text2Rect)
        GameDisplay.blit(Text3,Text3Rect)
        #start,quit버튼
        introBtn1 = button("START",display_width/6,display_height/1.7,200,100,BLACK,BLUE,action=True,fcolor=YELLOW)
        introBtn2 = button("QUIT",display_width/2,display_height/1.7,200,100,BLACK,RED,action=True,fcolor=YELLOW) 
        #버튼을 눌렀을 때
        if introBtn1 == True:
            return game()
        if introBtn2 ==True:
            pygame.quit()
            quit()
        pygame.display.update()
        FramePerSec.tick(FPS)

 

게임에서 동작할 class 만들기

게임에서 사용할 플레이어 및 적 개체 class를 저번 처럼만들어 줍니다.

## 게임 내에서 동작할 클래스 설정 ##

## 플레이어에게 적용할 클래스
class Player(pygame.sprite.Sprite):
    # 플레이어 이미지 로딩 및 설정 함수
    def __init__(self):
        super().__init__()
        # 플레이어 사진 불러오기
        self.image = pygame.image.load('resources/chick.png')
        # 이미지 크기의 직사각형 모양 불러오기
        self.rect = self.image.get_rect()
        # rec 크기 축소(충돌판정 이미지에 맞추기 위함)
        self.rect = self.rect.inflate(-20,-20)
        # 이미지 시작 위치 설정
        self.rect.center = (540, 390)

    # 플레이어 키보드움직임 설정 함수
    def move(self):
        prssdKeys = pygame.key.get_pressed()
        # 왼쪽 방향키를 누르면 5만큼 왼쪽 이동
        if self.rect.left > 0:
            if prssdKeys[K_LEFT]:
                self.rect.move_ip(-5, 0)
                position_p = self.rect.center
                return position_p
        # 오른쪽을 누르면 5만큼 오른쪽으로 이동
        if self.rect.right < 640:
            if prssdKeys[K_RIGHT]:
                self.rect.move_ip(5, 0)
                position_p = self.rect.center
                return position_p


## 적에게 적용할 클래스
class Enemy(pygame.sprite.Sprite):

    # 적의 이미지 로딩 및 설정 함수
    def __init__(self):
        super().__init__()
        # 적 사진 불러오기
        self.image = pygame.image.load('resources/boom2.png')
        # 이미지 크기의 직사각형 모양 불러오기
        self.rect = self.image.get_rect()
        # rec 크기 축소(충돌판정 이미지에 맞추기 위함)
        self.rect = self.rect.inflate(-20,-20)
        # 이미지 시작 위치 설정
        self.rect.center = (random.randint(40, 600), 0)

    # 적의 움직임 설정 함수+ 플레이어 점수 측정
    def move(self):
        global SCORE

        # 적을 10픽셀크기만큼 위에서 아래로 떨어지도록 설정
        self.rect.move_ip(0, SPEED)  # x,y좌표 설정
        # 이미지 가 화면 끝에 있으면(플레이어가 물체를 피하면) 다시 이미지 위치 세팅 + 1점 추가
        if (self.rect.bottom > 440):
            SCORE += 1
            self.rect.top = 0
            self.rect.center = (random.randint(30, 610), 0)
        return self.rect.center
게임 만들기

이제 위의 클래스를 사용하여 폭탄 피하기 게임을 만들어 줍니다.

게임 종료 시 outro화면으로 넘어갈 수 있도록 설정하는 것도 잊지 말고 넣어 줍니다.

###### 게임 설정 ########
# 플레이어 및 적 개체 생성
def game(speed = SPEED):

    P1 = Player()

    E1 = Enemy()

    # Sprites Groups 생성하기
    # 게임 물체들을 그룹화 하여 그룹별로 접근하여 설정 시 용이하게 만들기
    # 적(enemy) 객체 그룹화하기
    Enemies = pygame.sprite.Group()
    Enemies.add(E1)
    # 전체 그룹을 묶기
    All_groups = pygame.sprite.Group()
    All_groups.add(P1)
    All_groups.add(E1)

    # 적 개체 1초(1000ms)마다 새로 생기는 이벤트 생성
    increaseSpeed = pygame.USEREVENT + 1
    pygame.time.set_timer(increaseSpeed, 1000)

    # 게임 BGM 설정
    bgm = pygame.mixer.Sound('resources/backgroundMusic.mp3')
    bgm.play()
    ## 게임 루프 설정 ##
    # 게임 종료되기 전까지 실행되는 루프(이벤트) 설정
    while True:
        for event in pygame.event.get():
            # type increaseSpeed이면 속도 증가하여 어렵게 만듬(적 물체 이벤트)
            if event.type == increaseSpeed:
                speed += 0.5
            # 이벤트가 종료되면 게임도 종료시킴
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

        # 배경화면 사진 게임창에 불러오기(사진, 위치)
        GameDisplay.blit(background, (0, 0))
        # 하단부에 위치할 스코어 점수(적을 피할때마다 +1점 증가)
        scores = small_font.render("Score: " + str(SCORE), True, BLACK)
        GameDisplay.blit(scores, (10, 400))

        # group1 = '<Player Sprite(in 1 groups)>'
        # group2 = '<Enemy Sprite(in 2 groups)>'

        # 게임 내 물체 움직임 생성
        for i in All_groups:
            GameDisplay.blit(i.image, i.rect)
            i.move()
            if str(i) == '<Player Sprite(in 1 groups)>':
                player_pos = i
            else:
                enemy_pos = i

        # <Player Sprite(in 1 groups)>
        # 플레이어 충돌 판정(게임종료)시
        if pygame.sprite.spritecollideany(P1, Enemies):
            for i in All_groups:
                i.kill()
            # 물체 이미지 변경(충돌후 변경되는 이미지)
            # 플레이어
            GameDisplay.blit(background, (0, 0))
            image0 = pygame.image.load('resources/chickbommed.png')
            image0.get_rect()
            GameDisplay.blit(image0, player_pos)

            # 폭탄
            image1 = pygame.image.load('resources/boomm.png')
            image1.get_rect()
            GameDisplay.blit(image1, enemy_pos)
            pygame.display.update()

            # 배경음악 멈춤
            bgm.stop()
            # 적과 충돌시 효과음 추가
            pygame.mixer.Sound('resources/BOOM.WAV').play()
            time.sleep(0.5)
            # 게임오버화면 설정
            pygame.mixer.Sound('resources/gameover.mp3').play()
            pygame.display.update()
            game_outro()

        pygame.display.update()
        # 초당 프레임 설정
        FramePerSec.tick(FPS)

 

Outro 만들기

게임 종료 화면을 만들어 줍니다.

게임 점수를 배치하고 버튼을 배치하여,

다시 플레이하고 싶은 사람은 score 리셋 후 retry를, 종료하고 싶은 사람은 quit을 눌러 창을 닫을 수 있도록 설정합니다.

## 게임오버 페이지
def game_outro():
    outro = True

    while outro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        GameDisplay.blit(background, (0, 0))
        final_scores = font.render("Your Score: " + str(SCORE), True, BLACK)
        Music = small_font.render("Music: www.bensound.com",True,BLACK)
        Photos = small_font.render("Photos: pixabay, pngwing",True,BLACK)
        Madeby = small_font.render("Made by wonhwa.tistory.com",True,BLACK)
        GameDisplay.blit(final_scores, (150, 100))
        GameDisplay.blit(game_over, (280, 200))
        GameDisplay.blit(Music,(10,400))
        GameDisplay.blit(Photos,(10,380))
        GameDisplay.blit(Madeby,(350,400))
        #retry,quit버튼
        outroBtn1 = button("RETRY",display_width/6,display_height/1.7,200,100,BLACK,BLUE,action=True,fcolor=YELLOW)
        outroBtn2 = button("QUIT",display_width/2,display_height/1.7,200,100,BLACK,RED,action=True,fcolor=YELLOW)
        #time.sleep(1)
        #pygame.display.update()
        #time.sleep(5) 
        #TODO: 버튼 누르면 동작
        if outroBtn1 == True:
            reset()
            game()
        if outroBtn2 ==True:
            pygame.quit()
            sys.exit()
        pygame.display.update()
        FramePerSec.tick(FPS)

 

게임 시작!

이제 만들어둔 함수를 호출하여 게임을 시작할 수 있습니다.

#####게임 시작#####
game_intro()

 

게임 파일

게임 파이썬 파일을 .exe파일로 만들어 보았습니다.(용량이 259MB로 꽤 큽니다..)

해보고 싶은 분들은 다운받아 실행해보시길 바랍니다 :)

https://drive.google.com/file/d/1fZGR-vbcTgAvsYqhsIh5lmnWSORJ0I0a/view?usp=sharing 

 

minigame.exe

 

drive.google.com

.py를 .exe로 만드는 방법은 아래의 링크를 참고해 주세요.

https://wonhwa.tistory.com/66

 

[python] pyinstaller로 이미지,소리파일이 포함된 .exe파일 만들기(feat.pygame)

안녕하세요. 그동안 python으로 여러 프로그램을 만들어 보았는데, 그걸 다른 사람에게도 보여주고 싶을 때는 1. python 설치 2. .py 파일 실행 이렇게 번거로운 과정이 필요할 것입니다. 하지만 그동

wonhwa.tistory.com

 

전체 코드

https://github.com/ElenaLim/Pygame/blob/main/minigame_ver1.1.py

 

GitHub - ElenaLim/Pygame: Minigame using Pygame

Minigame using Pygame. Contribute to ElenaLim/Pygame development by creating an account on GitHub.

github.com

참고자료

https://wonhwa.tistory.com/45

 

[python/Game] 파이썬으로 게임만들기(2) - 미니게임

이번 포스팅에서는 미니 게임을 pygame을 사용하여 만들어 보도록 하겠습니다. preview 이 게임은 병아리가 폭탄을 피하고 부딪히면 게임이 종료되는 미니게임 입니다. 게임 구성 1. 게임 화면 설정

wonhwa.tistory.com

https://pythonprogramming.net/pygame-button-function/

 

Python Programming Tutorials

PyGame Progress: 0% --> PyGame Buttons, part 4, creating a general PyGame button function Now that we've got some fancy code coming along, it's time to move all of this to a function, so that we can use this dynamically to create other buttons, rather than

pythonprogramming.net

 

마무리

그동안 저번에 만든 미니게임에 인트로,아웃트로를 넣고 싶었는데 드디어 완성할 수 있었네요.

exe파일도 올려두었으니 한번 씩 심심할 때 해보시면 좋을 것 같습니다 ㅎㅎ

반응형
반응형

안녕하세요.

저번 sklearn LDA 토픽 모델링 게시물에 이어서 이번에는 선정한 토픽에 대해

기간별로 어떻게 변화하는지를 확인해 보도록 하겠습니다.

 

데이터 준비

데이터는 저번 게시물에서 사용한 데이터를 사용하겠습니다.

- 데이터: 공공데이터 포탈의 '공정거래위원회_소비자 민원학습데이터 처리기관별 소비자 상담내역' 

링크 들어가셔서

'공정거래위원회_소비자 민원학습데이터 처리기관별 소비자 상담내역_20211227.csv' 

파일을 다운받아 주세요.

import pandas as pd
df = pd.read_csv('공정거래위원회_소비자 민원학습데이터 처리기관별 소비자 상담내역_20211227.csv',encoding='cp949')
print(df.head())
print(df.shape)

약 5만개의 행으로 이루어져 있습니다.

이 데이터에서 날짜 데이터도 있고 기타 데이터도 많지만,

토픽 모델링은 사건 제목을 가지고 해보도록 하겠습니다.

#토픽 토크나이저를 위해 필요한 부분 (사건제목) 추출
contents= df['사건제목(ACCIDENT_TITLE)']
contents

텍스트 토크나이징 및 카운트 벡터화

이제 이 텍스트를 가지고 sklearn을 사용하여 텍스트 토큰화 및 카운트 벡터화를 하겠습니다.

카운트 벡터는 sklearn.feature_extraction.text.CountVectorizer를 사용하여 생성할 수 있습니다.

저번 게시글과 마찬가지로, max_df=0.5로, min_df를 5로 지정하고 max_features 최대 2000개까지만 카운트벡터를 생성해 보겠습니다.

from konlpy.tag import Okt
from sklearn.feature_extraction.text import CountVectorizer
###형태소 분석###
okt = Okt()
def tokenizer(text):
    #명사 추출, 2글자 이상 단어 추출
    return [ word for word in okt.nouns(text) if len(word)>1]
Count_vector = CountVectorizer(tokenizer=tokenizer,
                              max_df = 0.5,
                              min_df = 5,
                              max_features = 2000)

%time minwon_cv = Count_vector.fit_transform(contents) 
print(minwon_cv[:5])
print(minwon_cv.shape)

이렇게 minwon_cv라는 민원 제목과 관련된 카운트벡터를 만들었습니다.

최적 토픽 수 선정하기

이번에는 토픽 수를 선정해 보겠습니다.

sklearn를 사용하는 경우, 혼란도만 제공하고 있는데, tmtoolkit을 사용하면 응집도도 구할 수 있습니다.

토픽에 따른 혼란도, 응집도 및 토픽 내용을 print해주는 함수를 하나 만들어 실행해 보도록 하겠습니다.토픽 수는 3에서 10까지 늘려 값을 확인해 보겠습니다.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import LatentDirichletAllocation
from tmtoolkit.topicmod.evaluate import metric_coherence_gensim

# 토픽별 단어를 보여주는 함수
def print_top_words(model, feature_names, n_top_words):
    for topic_idx, topic in enumerate(model.components_):
        print("토픽 #%d: " % topic_idx, end='')
        print(", ".join([feature_names[i]
                        for i in topic.argsort()[:-n_top_words -1:-1]]))
                        
# 혼란도 및 응집도 구하는 함수
def calc_pv_coherence(countVector,vocab, start=5, end=30, max_iter=10,topic_wp=0.1, doc_tp=1.0):
    num = []
    per_value = []
    cor_value = []
    for i in range(start,end+1):
        lda = LatentDirichletAllocation(n_components=i,max_iter=max_iter,
                                       topic_word_prior=topic_wp,
                                       doc_topic_prior=doc_tp,
                                       learning_method='batch', n_jobs=-1,
                                       random_state=0)
        lda.fit(countVector)
        num.append(i)
        pv = lda.perplexity(countVector)
        per_value.append(pv)
        coherence_score = metric_coherence_gensim(measure='u_mass',
                                                  top_n=10,
                                                  topic_word_distrib=lda.components_,
                                                 dtm=countVector,
                                                 vocab=vocab,
                                                 texts=None)
        cor_value.append(np.mean(coherence_score))
        
        print(f'토픽 수: {i}, 혼란도: {pv:0.4f}, 응집도:{np.mean(coherence_score):0.4f}')
        print_top_words(lda, vocab,10)
    
    plt.plot(num,per_value,'g-')
    plt.xlabel("topic_num")
    plt.ylabel("perplexity")
    plt.show()
    
    plt.plot(num,cor_value,'r--')
    plt.xlabel("topic_num")
    plt.ylabel("coherence_score")
    plt.show()
    return per_value,cor_value
per_values, cor_values = calc_pv_coherence(minwon_cv,names,start=3,end=10)

이렇게 토픽 갯수별 토픽 단어들이 나오고,

토픽별 혼란도, 응집도를 확인했을 때 최적의 토픽 수는 4 로 보입니다.

선정된 토픽 갯수로 LDA 토픽 모델링 하기

sklearn LDA를 사용해서 4개의 토픽을 가지고 있는 모델을 만들어 보겠습니다.

from sklearn.decomposition import LatentDirichletAllocation
lda = LatentDirichletAllocation(n_components=4,
                               n_jobs= -1,
                               random_state=0,
                               max_iter=10,
                                topic_word_prior=0.1,
                               doc_topic_prior=1.0,
                               learning_method='batch',
                               )
minwon_topics = lda.fit_transform(minwon_cv)

토픽 모델링 한 결과는 아래와 같습니다. 각 토픽별로 상위 20개 단어를 보도록 하겠습니다.

print_top_words(lda, Count_vector.get_feature_names_out(),20)

 

트렌드 확인하기

이제 이 민원 토픽들을 가지고 시간별로 어떤 종류의 토픽이 많이 나왔는지 확인하기 위한 트렌드 분석을 진행해 보겠습니다.

날짜 데이터는 '등록일자(RCPT_YMD)' 컬럼에 있습니다. 

행이 5만개가 되기 때문에 날짜를 월단위까지만 자른 데이터를 토픽 분포 데이터와 합치도록 하겠습니다.

from sklearn.feature_extraction.text import CountVectorizer
trend_data = pd.DataFrame(minwon_topics,columns=['토픽'+str(i) for i in range(1,5)])
trend_data = pd.concat([trend_data,df['등록일자(RCPT_YMD)'].map(lambda x:x[:7])], axis=1)
trend_data.head()

이후 groupby를 사용하여 월 단위로 토픽의 평균을 구해보겠습니다.

#월별 평균 구하기
trend = trend_data.groupby(['등록일자(RCPT_YMD)']).mean()
trend.head()

이제 월별로 토픽 비중이 어떻게 변했는지 확인하기 위해 matplotlib을 사용하여 그래프를 그려 보도록 하겠습니다.

matplotlib의 AutoDateLocator를 사용하여 x축은 6개월 단위로 눈금 및 값을 표시해서 보여주도록 하겠습니다.

import matplotlib
import matplotlib.pyplot as plt
from matplotlib import font_manager,rc
from matplotlib.dates import AutoDateLocator,MonthLocator
# 한글 폰트 설정
font_location = 'C:/Windows/Fonts/MALGUNSL.TTF' #맑은고딕
font_name = font_manager.FontProperties(fname=font_location).get_name()
rc('font',family=font_name)
#날짜설정
locator = AutoDateLocator()
locator.intervald['MONTHLY'] = [6]

print_top_words(lda, Count_vector.get_feature_names_out(),20)

fig,axes = plt.subplots(2,2,figsize=(10,10))
for col,ax in zip(trend.columns.tolist(),axes.ravel()):
    ax.set_title(col)
    ax.xaxis.set_major_locator(locator)
    ax.axes.xaxis.set_visible(True)
    
    ax.plot(trend[col])

plt.show()

4개의 토픽에서 토픽별로 시간에 따라 분포가 어떻게 변화했는지 확인할 수 있습니다.

각 토픽 주제는 대략적으로

토픽 1: 피해 상담 문의

토픽2: 환불 및 반품 문의

토픽3: 수리 및 보상 문의

토픽4: 계약 해지 문의 

이렇게 볼 수 있을 것 같습니다.

토픽1 은 최근에 급격히 비중이 늘어났고, 토픽 3번은 시간에 따라 비중이 줄어들고 있고, 토픽 4번은 후반부에 비중이 늘어남을 확인할 수 있습니다.

 

 참고자료

1. 도서 - 파이썬 텍스트 마이닝 완벽 가이드(위키북스)

2.  https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.LatentDirichletAllocation.html

 

sklearn.decomposition.LatentDirichletAllocation

Examples using sklearn.decomposition.LatentDirichletAllocation: Topic extraction with Non-negative Matrix Factorization and Latent Dirichlet Allocation Topic extraction with Non-negative Matrix Fac...

scikit-learn.org

3. https://matplotlib.org/stable/api/dates_api.html

 

matplotlib.dates — Matplotlib 3.6.3 documentation

matplotlib.dates Matplotlib provides sophisticated date plotting capabilities, standing on the shoulders of python datetime and the add-on module dateutil. By default, Matplotlib uses the units machinery described in units to convert datetime.datetime, and

matplotlib.org

 

반응형
반응형

안녕하세요. 저번시간에는 토픽 모델링을 할 때 gensim으로 하는 방법을 알아보았는데,

이번에는 sklearn을 활용하여 LDA를 하는 방법을 알아보도록 하겠습니다.

 

​데이터 준비

공공데이터 포탈의 '공정거래위원회_소비자 민원학습데이터 처리기관별 소비자 상담내역' 을 활용하여

LDA를 해보도록 하겠습니다.

아래의 링크에서 csv파일을 다운받아 주세요.

https://www.data.go.kr/data/15098351/fileData.do#tab-layer-file

 

공정거래위원회_소비자 민원학습데이터 처리기관별 소비자 상담내역_20211227

공정거래위원회의 소비자 민원학습 데이터로, 소비자들의 민원상담을 처리한 기관별 상담데이터를 보여주는 데이터입니다. 이 데이터는 기관명 상위기관을 포함하고 있습니다.

www.data.go.kr

import pandas as pd
df = pd.read_csv('공정거래위원회_소비자 민원학습데이터 처리기관별 소비자 상담내역_20211227.csv',encoding='cp949')
print(df.head())
print(df.shape)

약 5만개의 행으로 이루어져 있습니다.

여기서 사용할 컬럼은 사건 제목을 사용하여 토픽 모델링을 진행해 보도록 하겠습니다.

#토픽 토크나이저를 위해 필요한 부분 (사건제목) 추출
contents= df['사건제목(ACCIDENT_TITLE)']
contents

행별로 처리결과라는 카테고리가 있는데 그것이 몇개 있는지 확인해보도록 하겠습니다.

#카테고리 확인
df.groupby('처리결과명(PRCS_RESULT_NAME)').count()
print(len(df.groupby('처리결과명(PRCS_RESULT_NAME)').count()))

27

총 27개의 카테고리가 있습니다.

 

텍스트 토크나이징 및 카운트 벡터화

이제 이 텍스트를 가지고 sklearn을 사용하여 텍스트 토큰화 및 카운트 벡터화를 하겠습니다.

카운트 벡터는 sklearn.feature_extraction.text.CountVectorizer를 사용하여 생성할 수 있습니다.

tokenizer 함수를 하나 만들어 주고,

CountVectorizer의 tokenizer에 해당 토큰화함수를 입력하고,

max_df는 gensim에서 사용했던 no_above처럼 일정 %이상 빈도가 너무 자주 등장하는 것을 제외하고,

min_df는 no_below처럼 몇 회 미만으로 나온 단어를 제외합니다.

이번에는 max_df=0.5로, min_df를 5로 지정하고 max_features 최대 2000개까지만 카운트벡터를 생성해 보겠습니다.

from konlpy.tag import Okt
from sklearn.feature_extraction.text import CountVectorizer
###형태소 분석###
okt = Okt()
def tokenizer(text):
    #명사 추출, 2글자 이상 단어 추출
    return [ word for word in okt.nouns(text) if len(word)>1]
Count_vector = CountVectorizer(tokenizer=tokenizer,
                              max_df = 0.5,
                              min_df = 5,
                              max_features = 2000)

%time minwon_cv = Count_vector.fit_transform(contents) 
print(minwon_cv[:5])
print(minwon_cv.shape)

이렇게 minwon_cv라는 민원 제목과 관련된 카운트벡터를 만들었습니다.

 

최적 토픽 수 선정을 위해 혼란도, 응집도 구하기

이번에는 토픽 수를 선정해 보겠습니다.

sklearn의 경우, 혼란도만 제공하고 있는데, tmtoolkit을 사용하면 응집도도 구할 수 있습니다.

tmtoolkit 설치는 아래의 명령어를 입력하여 터미널에서 설치해 주시면 됩니다.

pip install --user tmtoolkit

sklearn에서 LDA는 sklearn.decomposition.LatentDirichletAllocation 을 사용하여 구할 수 있습니다.

sklearn LDA의 n_components는 추출할 토픽의 수를 의미하고,

max_iter는 알고리즘의 최대 반복 횟수(gensim의 passes라고 생각하면 됩니다.),

topic_word_prior은 베타값(토픽의 사전 단어분포),

doc_topic_prior은 알파값(문서의 사전 토픽분포),

learning_method는 학습방법으로 online과 batch가 있습니다.

n_jobs는 모델 사용시 사용하는 프로세서의 수를 의미하며 -1로 설정하면 모든 프로세서를 사용할 수 있습니다.

이번에는 max_iter를 10으로 설정하고,

topic_word_prior와 doc_topic_prior은 아래의 논문

https://www.ncbi.nlm.nih.gov/pmc/articles/PMC387300/

 

Colloquium Paper: Mapping Knowledge Domains: Finding scientific topics

A first step in identifying the content of a document is determining which topics that document addresses. We describe a generative model for documents, introduced by Blei, Ng, and Jordan [Blei, D. M., Ng, A. Y. & Jordan, M. I. (2003) J. Machine ...

www.ncbi.nlm.nih.gov

을 참고하여 각각 0.1, 1.0으로 설정해 보도록 하겠습니다.

random_state는 0으로 설정해준 뒤,

n_components는 5부터 30까지의 값을 넣어 실행한 뒤,

혼란도, 응집도 값을 각각 구해 matplotlib으로 시각화 해보도록 하겠습니다.

혼란도는 sklearn LDA 모형의 .perplexity로 값을 구하고,

응집도는 tmtoolkit.topicmod.evaluate.metric.coherence_gensim을 사용하여 구하도록 하겠습니다.

coherence score에서 measure은 'u_mass'를 사용하였습니다.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import LatentDirichletAllocation
from tmtoolkit.topicmod.evaluate import metric_coherence_gensim
def calc_pv_coherence(countVector,vocab, start=5, end=30, max_iter=10,topic_wp=0.1, doc_tp=1.0):
    num = []
    per_value = []
    cor_value = []
    for i in range(start,end+1):
        lda = LatentDirichletAllocation(n_components=i,max_iter=max_iter,
                                       topic_word_prior=topic_wp,
                                       doc_topic_prior=doc_tp,
                                       learning_method='batch', n_jobs=-1,
                                       random_state=0)
        lda.fit(countVector)
        num.append(i)
        pv = lda.perplexity(countVector)
        per_value.append(pv)
        coherence_score = metric_coherence_gensim(measure='u_mass',
                                                  top_n=10,
                                                  topic_word_distrib=lda.components_,
                                                 dtm=countVector,
                                                 vocab=vocab,
                                                 texts=None)
        cor_value.append(np.mean(coherence_score))
        
        print(f'토픽 수: {i}, 혼란도: {pv:0.4f}, 응집도:{np.mean(coherence_score):0.4f}')
    
    plt.plot(num,per_value,'g-')
    plt.xlabel("토픽 수:")
    plt.ylabel("혼란도: ")
    plt.show()
    
    plt.plot(num,cor_value,'r--')
    plt.xlabel("토픽 수:")
    plt.ylabel("응집도: ")
    plt.show()
    return per_value,cor_value

함수를 이렇게 만들고 아래와 같이 호출해 줍니다.

per_values, cor_values = calc_pv_coherence(minwon_cv,Count_vector.get_feature_names_out(),start=5,end=30)

시작 토픽은 5, 끝나는 토픽 수는 30으로 설정한 뒤 실행해 줍니다.

여기서 시간이 2~3시간정도 걸릴 수 있습니다.

 

이렇게 각 토픽에 대한 혼란도, 응집도가 나오고,

위의 그래프는 토픽 수에 따른 혼란도를,

이 그래프는 토픽 수에 따른 응집도(u_mass)를 보여 줍니다.

여기서 적절한 토픽 수 찾기가 좀 어려웠는데요,

혼란도는 적을수록 좋은데 이 그래프에서는 토픽수가 늘어날수록 혼란도도 늘어나고,

응집도는 0에 가까울수롤 좋은데 응집도 그래프에서는 토픽이 29개일 때 응집도가 가장 0에 가깝기 때문입니다.

저는 여기서 응집도를 기준으로 가장 높았던 토픽 수 29로 설정해 보았습니다.

만약 다른 갯수로 설정하고 싶다면 n_components를 해당 토픽 갯수로 바꿔서 진행하면 됩니다.

 

결정된 토픽 수로 토픽 모델링 하기
lda = LatentDirichletAllocation(n_components=29,
                               n_jobs= -1,
                               random_state=0,
                               max_iter=10,
                                topic_word_prior=0.1,
                               doc_topic_prior=1.0,
                               learning_method='batch')
%time minwon_topics = lda.fit_transform(minwon_cv)

토픽 수 29로 LDA모델을 만들고 fit한 후 토픽을 뽑아보면,

for topic_idx, topic in enumerate(lda.components_):
    print("토픽 #%d: " % topic_idx, end='')
    print(", ".join([Count_vector.get_feature_names_out()[i] for i in topic.argsort()[:10]]))

이렇게 결과가 나옵니다. 하지만 이는 비중이 작은 순서라서 다시 가장 비중이 큰 10개만 다시 뽑아보면,

for topic_idx, topic in enumerate(lda.components_):
    print("토픽 #%d: " % topic_idx, end='')
    print(", ".join([Count_vector.get_feature_names_out()[i] for i in topic.argsort()[:-11:-1]]))

비슷한 단어가 많이 겹치는 것을 확인할 수 있습니다.

단순히 응집도 점수만 봤을 때 이런 결과가 나오니 다른 토픽 수도 확인하여 결정하는 것이 좋을 것 같습니다.

 

참고자료

1. 도서 - 파이썬 텍스트 마이닝 완벽 가이드(위키북스)

2. https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.LatentDirichletAllocation.html

 

sklearn.decomposition.LatentDirichletAllocation

Examples using sklearn.decomposition.LatentDirichletAllocation: Topic extraction with Non-negative Matrix Factorization and Latent Dirichlet Allocation Topic extraction with Non-negative Matrix Fac...

scikit-learn.org

3. https://alvinntnu.github.io/NTNU_ENC2045_LECTURES/nlp/topic-modeling-naive.html#additional-notes

 

2. Topic Modeling: A Naive Example — ENC2045 Computational Linguistics

Simple Text Pre-processing Depending on the nature of the raw corpus data, we may need to implement more specific steps in text preprocessing. In our current naive example, we consider: removing symbols and punctuations normalizing the letter case strippin

alvinntnu.github.io

 

반응형

+ Recent posts