[천재교육] 프로젝트 기반 빅데이터 서비스 개발자 양성 과정 9기
학습일 : 2024.09.24
📕 학습 목록
- 정형 데이터 vs 비정형 데이터
- 자연어 처리
- Tokenizer : Okt, Kkma, Hannanum
- 워드 클라우드
- 정규식 처리
📗 기억할 내용
1) 정형 데이터 (Structured Data)
- 정의 : 규격화된 데이터로, 행과 열 형태로 저장되며 관계형 데이터베이스(RDB)에 적합
- 특징
- 숫자나 텍스트를 포함하더라도 고정된 형식에 맞춰 저장됨
- 분석과 처리가 쉽고, 계산이 가능하며, 빠른 검색이 가능
- RDB(Relational Database) 또는 스프레드시트에서 주로 저장 및 관리
- SQL을 사용하여 관리 및 분석이 용이
- 데이터 마이닝 가능
- 예시 : 엑셀 시트, 관계형 데이터베이스의 테이블 데이터, 금융 거래 기록, 학생 성적 데이터
- 한계
- 분석할 수 있는 패턴과 결과가 미리 정의된 틀 안에서만 가능
- 이상치가 존재할 경우, 데이터의 품질이 쉽게 저하될 수 있음
- 이미 많은 분석이 이루어져 새로운 분석 시도에 제한이 있음
- 데이터 생성과 동시에 분석이 끝남 : 예를 들어, 학생 성적 데이터는 점수와 석차 등의 정보를 생성하면 즉시 분석할 수 있으며, 분석의 새로운 의미를 발견하기 어려움
- 이미 분석이 완료된 데이터가 많음 : 많은 정형 데이터는 이미 분석되었기 때문에 새로운 통찰을 도출하기 어려움
- 이상치 문제 : 정형 데이터에서 이상치가 존재하면 데이터 품질이 쉽게 저하될 수 있어, 신뢰성 있는 분석이 어려움
2) 비정형 데이터 (Unstructured Data)
- 정의 : 고정된 구조가 없는 데이터로, RDB에 적합하지 않으며 다양한 형태를 가질 수 있음
- 특징
- 숫자로 표현되지 않거나, 계산이 어려운 데이터를 포함
- 데이터 수집 과정에서 어떤 데이터를 다룰 것인지 명확하게 정의하는 것이 중요
- 전체 데이터의 80%를 차지할 만큼 양이 많음
- 문서, 이미지, 비디오, 오디오 파일, 텍스트 데이터 등 다양한 형식이 존재
- RDB에 저장하기 어려움
- 비정형 데이터를 분석하려면, 데이터 전처리(정형 데이터로 변환하거나 특수한 분석 기법이 필요)가 필수적이며, 제대로 처리하지 못할 경우 분석 결과의 신뢰도가 떨어질 위험이 큼
- 데이터 간 일관성이 부족할 수 있으며, 전처리 과정이 필수적임
- 개인정보 관련 데이터가 포함될 가능성이 높으며, 분리하기 어렵다는 문제가 있음
- 예시 : 이메일, 소셜 미디어 게시물, PDF 문서, 이미지, 동영상 파일, 자유 형식 텍스트 데이터
- 한계
- 비정형 데이터를 분석하려면 추가적인 가공이 필요
- 데이터 품질이 떨어질 수 있고, 일관성을 유지하기 어려움
- 전처리가 제대로 이루어지지 않으면 분석 결과의 신뢰도가 낮아짐
3) 반정형 데이터 (Semi-Structured Data)
- 정의: 데이터가 고정된 스키마를 따르지는 않지만, 데이터 내에 일부 구조적 요소가 존재하는 데이터
- 특징:
- 정형 데이터와 비정형 데이터의 중간 형태로, 특정 구조는 존재하지만 모든 요소가 규칙적으로 저장되지는 않음
- 주로 태그, 키-값 쌍 등의 형식을 따르며, 분석을 위해서 약간의 구조화된 정보를 포함
- 비정형 데이터처럼 특수한 방법으로 분석할 수 있음
- 예시: JSON, XML, 로그 파일, CSV(일부 형태에서)
- 분석:
- 비정형 데이터처럼 처리하지만, 내부에 일부 구조적 정보가 있으므로 처리와 분석이 상대적으로 쉬움
📘 코드 실습
1. 자연어 처리 및 시각화(워드 클라우드)
# 1. 패키지 임포트 import pandas as pd from konlpy.tag import Okt # Okt : 형태소 분석기(tokenizer) # 2. Okt 객체 초기화 # Okt : 클래스 -> 초기화 해줘야 함 # tokenizer : Okt 의 객체(인스턴스) # 텍스트 데이터를 토큰(형태소 단위)으로 분리하는 역할 tokenizer = Okt() # 3. 샘플 텍스트 설정 sample_text = "오, 그녀는 정말 횃불에게 찬란히 타오르는 법을 가르치누나!" # 4. 형태소 분석 수행 (morphs() 사용) # morphs() : 텍스트를 형태소 단위로 분리하는 메서드 tokenizer.morphs(sample_text) # 5. 다양한 형태소 분석기 사용 from konlpy.tag import Okt, Kkma, Hannanum # 여러 형태소 분석기 종류 # 6. 각 형태소 분석기 초기화 및 사용 예시 okt = Okt() kkma = Kkma() han = Hannanum() # 각 형태소 분석기의 분석 결과를 출력 for tokenizer in [okt, kkma, han]: print(tokenizer, "를 사용한 결과") print(tokenizer.morphs(sample_text)) print("-----------------------------------") # 7. 형태소와 품사 태깅 (pos 메서드 사용) # pos : 품사 태깅 okt.pos(sample_text) # Okt의 품사 태그셋 확인 okt.tagset # Okt 토크나이저가 사용하는 품사 목록 확인 # 8. 형태소 분석 결과를 딕셔너리로 정리 # 딕셔너리 형태로 형태소를 저장 tag_dict = {} for k in okt.tagset.keys(): tag_dict[k] = [] for p in okt.pos(sample_text): tag_dict[p[-1]].append(p[0]) # 9. 딕셔너리 데이터를 pandas 데이터프레임으로 변환 및 저장 df = pd.DataFrame.from_dict(tag_dict, orient="index") # key -> 인덱스, value -> 컬럼 df # CSV 파일로 저장 df.to_csv('./token.csv', encoding='cp949') # 명사만 출력 df.loc['Noun'] # 10. 불용어 제거 작업 # 불용어 : 의미 없는 단어들 제거 (stopwords) stopwords = ['오', ',', '!', '가르치', '누나', '은', '는', '를', '에게'] # 불용어 제거 후 형태소 분석 token = okt.morphs(sample_text) [word for word in token if word not in stopwords] # 11. ckonlpy를 이용한 불용어 제거 자동화 from ckonlpy.tag import Twitter, Postprocessor # 클래스 초기화 twitter = Twitter() postprocessor = Postprocessor(twitter, stopwords=stopwords) # pos 메서드에서 불용어 자동 제거 postprocessor.pos(sample_text) # 12. 사용자 정의 품사 태깅 # '타오르는'을 명사로 추가 twitter.add_dictionary('타오르는', 'Noun') twitter.pos(sample_text) # 다른 샘플 텍스트로 테스트 sample_text2 = '미주는 대학 졸업 후 반년 이상 지옥과도 같은 취업난을 몸으로 부딪히며 참 많이도 좌절해야 했었다.' twitter.pos(sample_text2) # 사용자 정의 품사 태깅: '취업난'을 하나의 명사로 처리 twitter.add_dictionary('취업난', 'Noun') twitter.pos(sample_text2) # 13. 2그램 분석법 적용 (n-gram) ngrams = [ (('대학', '졸업'), 'Noun'), (('지옥', '과도'), 'Noun'), (('합격자', '명단'), 'Noun'), ] # Postprocessor로 n-gram 적용 postprocessor = Postprocessor(twitter, ngrams=ngrams) postprocessor.pos(sample_text2) # 14. 품사별 등장 횟수 카운팅 # 품사의 등장 횟수를 저장하는 딕셔너리 생성 tag_dict = {} for k in okt.tagset.keys(): tag_dict[k] = 0 tag_dict['Modifier'] = 0 # 수식어를 수동으로 추가 # 각 품사의 등장 횟수를 딕셔너리에 저장 for p in okt.pos(sample_text2): tag_dict[p[-1]] += 1 # 15. 품사별 등장 횟수를 시각화 import matplotlib.pyplot as plt import koreanize_matplotlib plt.subplots(figsize=(5,2)) plt.bar(tag_dict.keys(), tag_dict.values()) # 막대 그래프 생성 plt.xticks(list(okt.tagset.keys()) + ['Modifier'], list(okt.tagset.values()) + ['수식어'], rotation=90) plt.title('품사 개수') plt.show() # 16. 워드 클라우드 생성 from nltk import Text from wordcloud import WordCloud # 워드 클라우드 생성 font_path = 'C:/Windows/Fonts/malgun.ttf' sample_text3 = "미주는 대학 졸업 후 반년 이상 지옥과도 같은 취업난을 몸으로 부딪히며 참 많이도 좌절해야 했었다." text_count = Text(okt.nouns(sample_text3), name='장미와 찔레') wc = WordCloud(width=640, height=360, background_color='white', font_path=font_path, max_words=100, min_word_length=3) cloud = wc.generate_from_frequencies(text_count.vocab()) plt.imshow(cloud) plt.axis('off') plt.show()
2. 정규식 처리
# 1. 기본 문자열 처리 reg_text = '안녕, 나는 잎싹이야. 너도 잎싹이고, 쟤도 잎싹이야. 우리 모두 잎싹이야.' # replace() 메서드 : '잎싹'이라는 문자열을 '절대잎싹아님'으로 대체 reg_text.replace('잎싹', '절대잎싹아님') # 2. 정규 표현식 (Regular Expression) import re # [정규 표현식을 사용하여 숫자를 제거] # re.sub() : 문자열 내에서 정규 표현식 패턴에 일치하는 부분을 찾아 대체하는 함수 # '[0-9]' : 숫자(0-9) 범위 내에서 검색 reg_text = '안녕, 나는 잎싹이야. 너도 잎1싹이고, 쟤도 잎123싹이야. 우리 모두 잎567싹이야.' # 숫자 포함된 텍스트 # 숫자를 제거한 텍스트로 변환 re.sub('[0-9]', '', reg_text) # 3. 주민등록번호 마스킹 id_text = '안녕하세요, 저는 ABC에요. 제 주민번호는 123456-7894561 이에요. 제 주소는 XX시 OO구 123-45번지예요.' # '0-9' 범위를 의미하는 '\d' 사용. {6}은 숫자 6개, {7}은 숫자 7개를 의미 # 주민등록번호 패턴을 찾아서 '******-*******'로 대체 re.sub('\d{6}-\d{7}', '******-*******', id_text) # 4. 구두점이 있을 때 줄바꿈 처리 eng_text = 'Squire Trelawney, Dr. Livesey, and the rest of these gentlemen having asked me to write down the whole particulars about Treasure Island,' # 쉼표(,)와 마침표(.)를 줄바꿈('\n')으로 대체 result = re.sub(r'[,.]', '\n', eng_text) print(result) # 5. Dr. 에서는 줄바꿈이 되지 않도록 수정 # (?<!Dr) : 부정형 후방탐색 (Dr로 끝나지 않는 경우) result = re.sub(r'(?<!Dr)\. ', '\n', eng_text) # Dr.를 제외하고 마침표 뒤에 줄바꿈 result = re.sub(r',', '\n', result) # 쉼표 뒤에 줄바꿈 print(result) # 6. 주민등록번호 뒷자리 처리 (특정 조건 하에 마스킹) id_text = '안녕하세요, 저는 ABC에요. 제 주민번호는 990101-1234567 이에요. 제 주소는 XX시 OO구 123-45번지예요.' # 주민번호 뒷자리가 1-4로 시작하는 경우에만 뒷부분을 마스킹 re.sub(r'-[1-4]\d{6}', lambda x: x.group(0)[0:2] + '******', id_text)
📙 내일 일정
- 구문 분석 학습
'TIL _Today I Learned > 2024.09' 카테고리의 다른 글
[DAY 51] TF-IDF, Deep Learning 실습 (0) | 2024.09.26 |
---|---|
[DAY 50] 구문 분석 (Syntactic Parsing) (0) | 2024.09.25 |
[DAY 48] Deep Learning 실습 (0) | 2024.09.23 |
[DAY 47] Deep Learning 실습 (0) | 2024.09.20 |
[DAY 46] Deep Learning 실습 (0) | 2024.09.19 |