ASAC-SK플래닛 T아카데미 데이터 엔지니어

25.12.15 48일차 [딥러닝_NLP_워크플로우_챗봇구성, 활성화 함수]

Datadesigner 2025. 12. 15. 17:41

오늘은 딥러닝 NLP모델의 이해를 위한 실습과

 

딥러닝의 활성화 함수에 대한 수업을 진행했다.

 

내일쯤이면 딥러닝 파트가 끝난다고 한다.

 

넘나어려운것

 


목표

 

  • NLP(자연어 처리 과정 이해)
    • LLM의 기반
      • 백터디비, RAG, 유사도 등등 연관성
    • 토큰화 작업
      • 말뭉치 -> ....... -> 토큰화
  • 전이학습 (누군가 만든 모델을 사용->시간절약, 빠르게 높은 성능 보장받을수 있음)
  • 제로샷, 파인튜닝등 학습법 확인
  • 성능 무시(고려 사항 아님)
 

연구목표

 

  • AI기반 챗봇 구성
    • 사용자 질문 -> 해당 질문 토큰화 -> 기존의 챗봇시트(백터(1차원, 1배열) 데이터를 가진 자료구조)에서 유사도 검사 -> 유사도 값이 가장 작은 값(질문과 가장 가까운 질문지) 선택 -> 이에 대응하는 답변 응답
    • 챗봇시트 (ChatbotData.csv)
      • 개인 작업자 작성후 공유한 데이터(출처 추후 표시)
    • 시뮬레이션 - gradio 진행
 

 

데이터 획득

 

 


이렇게 수많은 말뭉치들이 있다. 그 중 nsmc를 선택했다.

# 리뷰데이터 획득
corpus = Korpora.load('nsmc')


    Korpora 는 다른 분들이 연구 목적으로 공유해주신 말뭉치들을
    손쉽게 다운로드, 사용할 수 있는 기능만을 제공합니다.

    말뭉치들을 공유해 주신 분들에게 감사드리며, 각 말뭉치 별 설명과 라이센스를 공유 드립니다.
    해당 말뭉치에 대해 자세히 알고 싶으신 분은 아래의 description 을 참고,
    해당 말뭉치를 연구/상용의 목적으로 이용하실 때에는 아래의 라이센스를 참고해 주시기 바랍니다.

    # Description
    Author : e9t@github
    Repository : https://github.com/e9t/nsmc
    References : www.lucypark.kr/docs/2015-pyconkr/#39

    Naver sentiment movie corpus v1.0
    This is a movie review dataset in the Korean language.
    Reviews were scraped from Naver Movies.

    The dataset construction is based on the method noted in
    [Large movie review dataset][^1] from Maas et al., 2011.

    [^1]: http://ai.stanford.edu/~amaas/data/sentiment/

    # License
    CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
    Details in https://creativecommons.org/publicdomain/zero/1.0/

[Korpora] Corpus `nsmc` is already installed at /root/Korpora/nsmc/ratings_train.txt
[Korpora] Corpus `nsmc` is already installed at /root/Korpora/nsmc/ratings_test.txt
# 정답 확인
# 리뷰의 감정분석(긍정/부정) 대한 데이터임
set( corpus.get_all_labels() )  # {0:부정 1:긍정}

{0, 1}
len(corpus.train), len(corpus.test) # 데이터 20만개

(150000, 50000)
corpus.train.get_all_texts()[100], corpus.train.get_all_labels()[100]

('신카이 마코토의 작화와,미유와 하나카나가 연기를 잘해줘서 더대박이였다.', 1)

 

type(corpus.train.get_all_texts())

tuple

데이터 준비 + 분석(EDA)

 

 

훈련데이터를 준비해준다.

 

데이터 전처리 과정을 진행한다. 전처리할 내용은 따로 없다.
정답 비율

모델 구축

 

토크나이저를 이용한 토큰화

 

  • 문장 -> 분절 -> 사전화 -> 백터화 -> 패딩 -> 임베딩
    • '오늘 날씨는 너무 ...' -> .... -> [0, 312, 23, 1, 56, .... , 9]
    • 텍스트 => 수치화 (규칙, 크기, 등등 정보필요) => 토큰화!!
    • 토크나이저는 토큰화 처리 도구(위의 공정을 한번데 다 수행할수 있음)
  • LLM이나 트랜스포머 계열 제품은 함수 호출로 전과정이 완료됨
 

분절화

 

  • 방법
    • 공백 기반 분절(분리, 분해)
      • 알파벳, LLM쪽에서 사용하는 도구에서는 주로 공백기반임
    • 형태소 분석기 통해 분절(한국어등 교착어 대상)
# 1. 한국어 대상 형태소 분석기(교착어 중심) 설치
#    교착어 -> 자연어처리( 한국어 초기모델 )-> 성과 잘 안나옴
#    LLM 이후 -> 한국어 처리 -> 공백 기반으로 명사 + 조사 통으로 학습 
#    -> 물량으로 처리 (GPT, 구글) -> 성과 잘 나옴
!pip install -q konlpy

# 2. 형태소 분석기 모듈 가져오기
from konlpy.tag import Okt

# 3. 분절만 담당하는 도구 => 실제 NLP에서는 백터화까지 모두 진행함
tokenizer = Okt()

# 4. 분절 확인

# 원 문장
train_df.sentence[99]
---------------------
 '설정이 재밌고 새로운 에피소드 내에서 메인 스토리도 차차 나오는게 재밌음'
---------------------
# 분절
tokenizer.morphs( train_df.sentence[99] )
# 형태소 분석기 => "설정", "이"
# LLM기반 토큰 => "설정이"
---------------------
['설정',
 '이',
 '재밌고',
 '새로운',
 '에피소드',
 '내',
 '에서',
 '메인',
 '스토리',
 '도',
 '차차',
 '나오는게',
 '재밌음']
 ---------------------
 # 형태소 분석기 기반으로 문장을 구성한다면 => 분절된 토큰 사이에 공백 개입 문장 완성
# 설정 이 재밌고 새로운 에피소드 내 에서 ... => LLM 은 이렇게 처리 하지 않음!!

# 형태소 분리해서 문장을 이해하는 것은 쉽이 않음
# => 대체 필요 (공백 기반 토큰화, 물량으로 해결(설정이, 설정을, ....):학습량으로 해결)

분절화(공백단위 진행)

from tensorflow.keras.preprocessing.text import Tokenizer

nlp_tokenizer = Tokenizer()

%%time

# 문장 => 분절(공백기반) => 사전화 구축 (토큰별로 숫자를 부여)
nlp_tokenizer.fit_on_texts( train_df.sentence )

 

사전화

 

  • 분절 후 토큰(분절한 단어의 단위, 분절단위)으로 쪼개짐
  • 토큰이 발견되면 순차적으로 라베링 수행함
  • 영화 -> 1, 너무 -> 2, ...
  • 토큰에 라벨을 부여하여 데이터를 준비 -> 사전화

백터화

 

 

 

  • 문장 1개에 대해서 백터(1차원) 구성

백터화 이후 전처리의 개념으로 패딩 공정을 거쳐 보정해주어야한다.

 

패딩

 

  • 모든 문장의 길이를 통일 -> 학습 가능한 형태가 됨
  • 길이
    • 설정한 최대 길이값?
      • 특정 모델의 성능에 대한 성능제한을 둘 수 있음, 버전이 올라가면 더 많은 길이 제공 (업그레이드된 효과)
      • 데이터 길이가 더 긴 경우 정보손실 나올수 있음
      • 자르기를 통해서 (청크)단위 구성을 할 수 있음
    • 데이터의 최대 길이? -> 데이터가 추가되거나 등등 하면 변경되수 있음
      • 장점 : 정보 손실 없음
# 주어진 데이터의 최대 길이 획득
# 문장 전체 => 벡터화
# 
x = nlp_tokenizer.texts_to_sequences(train_df.iloc[: , 0 ])
x

모든 말뭉치를 백터화했다.

가장 많은 토큰으로 구성된 문자의 길이값을 구하는 내용이다. 이것을 알아야 데이터 손실없이 패딩 공정이 가능하다.

패딩 공정 코드, 기본값들에 옵션들을 채워주고 아까 구한 59개의 토큰에서 안정적으로 +1 해준다, 안해도 되긴 한다.

이렇게 리스트를 패딩을 통해서 배열로 바꿔주어야 한다.

x_padding. nparray의 형태

임베딩

 

  • 인공신경망에 데이터를 주입할 때 (학습 시) 임베딩 수행함 (압축 행위 수행, 필요시 원핫인코딩까지 진행함)
  • 본 노트에서는 백터화된 데이터만 사용 (모델 사용 x) => 생략
 

인공신경망 구축 -> 학습 -> 평가, ... 생략

 

시스템 구축, 통합, 모델 덤프 및 서빙

 

벡터의 유사도 검사

 

 


  • 문장(자연어) -> 백터화 (수치화됨)
  • 원리
    • 문장과 문장의 유사도는 벡터대 벡터간 거리를 기반 계산 -> 거리(양)추출됨
    • 거리가 가장 작은 벡터간의 가장 유사한 내용임 -> 챗봇 시트내에 준비된 질문과 동일한 내용으로 간주
      • 코사인 유사도 사용
        • 방향성을 중시 => 내용의 유사성 중시
 

  • 참고
    • 벡터 유사도 검사는 텍스트, 이미지 등 데이터를 숫자 벡터로 변환한 뒤, 이 벡터들 간의 거리나 방향을 측정하여 얼마나 비슷한지 평가하는 기술입니다. 주로 코사인 유사도를 사용해 두 벡터의 각도를 기반으로 유사도를 1 (완전 동일) ~ -1 (완전 반대) 사이의 값으로 측정하며, 추천 시스템, 검색 엔진, 자연어 처리 등에서 핵심적인 역할을 합니다.
  • 벡터 유사도 검사의 주요 방식
    • 코사인 유사도 (Cosine Similarity): 가장 흔히 사용되며, 벡터의 크기(길이)를 무시하고 방향만으로 유사도를 측정합니다.
      • 원리: 두 벡터의 내적(dot product)을 각 벡터의 크기로 나눈 값으로, 1에 가까울수록 비슷하고, 0에 가까우면 직각(무관), -1에 가까우면 정반대입니다.
      • 장점: 데이터의 절대적인 크기(예: 문서의 길이)보다는 내용의 유사성을 파악하는 데 효과적입니다.
    • 유클리드 유사도 (Euclidean Similarity): 두 벡터의 좌표값 차이를 제곱하여 더한 후 제곱근을 씌운 '거리'를 기반으로 유사도를 측정합니다.
      • 원리: 거리가 가까울수록 유사도가 높다고 판단합니다
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

# 참고로 scipy, sklearn 등등 다양하게 제공됨
def cos_sim(AVec, BVec):
  return np.dot(AVec, BVec) / ( np.linalg.norm(AVec) * np.linalg.norm(BVec) )

벡터의 유사도를 검사하는 코드이다,.

사용자 입력 => 백터화 함수

 

  • 시나리오
    • 사용자 입력 -> 벡터화 -> 패딩(최대길이 60) -> 챗봇 시트의 질문지와 유사도 검사 -> 값이 가장 작은 데이터 찾음 -. 답변 획득 -> 응답

 

사용자가 입력한 내용을 벡터화 해준다, 

그 이후 패딩까지 처리해주는 인코더 함수를 정의해준다. 

함수를 호출해보면 바로 배열까지 인코딩해주는 모습을 볼 수 있따.

 

다른 csv파일을 불러온다,

 

apply() 와 lambda 함수를 사용해서 모든 11823개의 데이터의 q 내용이 vec라는 파생 변수에 추가되도록 해준다.

 

# 유사도 검사 함수
def ckeck_answer_similar(question=''):
  if not question:
    return '정확하게 입력 후 질문하시기 바랍니다.'
    # 1. 질문 -> 벡터화
  q_vec = custom_encode(question)
  # 2. 챗봇 시트 df에서 질문 -> x_padding 을 통해서 벡터화 구성되어있음
  #    x_padding 과 q_vec의 같은 코사인 유사도를 계싼하여서
  #    train_df의 파생변수(추가 컬럼)으로 'score'에 담으시오
  chatbot_df['score'] = chatbot_df.vec.apply(lambda x : cos_sim(x, q_vec))
  #    cos_sim( 챗봇시트1개 질문벡터, q_vec)
  # 3. 가장 유사한 질문 -> 코사인 유사도는 방향성 -> 가장 큰 값 취하면 됨
  #    만약, 유클리드 -> 거리가 큰 값
  #    idxmax()해당 컬럼의 값이 가장 큰 데이터의 인덱스값 반환
  #    사용자 질문에 가장 가까운 질문을 찾아서 거기에 대응하는 답변을 응답
  return chatbot_df.loc[chatbot_df['score'].idxmax()]['A'] 
  pass


# 사용자 질문을 입력받음
ckeck_answer_similar('아 진짜 돈까스')
-------------------------
'송장 번호를 확인해보세요.'
-------------------------
# 동문 서답의 이유 => 사전 구축(14만개의 리뷰), 응답(챗봇시트) => 상호 어휘량 다름
# 말뭉치의 양(장르,분야,등등 다양 대량), 토크나이저가 전문화될 필요

사전 학습된 모델(pre-trained model) 사용

 

# 트랜스포머 계열 모델이 가장 많이 등록된 커뮤니티 => 허깅페이스
!pip show sentence-transformers

from sentence_transformers import SentenceTransformer

# 허깅펭스 기반에 등록된 사전학습된 모델의 이름 or 경로
model_name = 'sentence-transformers/xlm-r-100langs-bert-base-nli-stsb-mean-tokens'

model = SentenceTransformer(model_name)

%%time
# 얘는 통합형 모델이기때문에 토크나이저랑 모델이 결합된 형태임(케이스 바이 케이스긴 함)
res = model.encode(['오늘 저녁은 물 한잔 드링킹'])
# (1, 768) 문장 1개에 대한 최대 토큰수 => 768
res.shape

# 기존 챗봇시트 => 인코드 함수를 통해서 벡터화 처리
chatbot_df.head(1)

# 사전 준비된 df 파일
# 파이썬에 했던 pickle로 저장한거임
import pickle

pre_data = '/content/drive/MyDrive/GoodNotes/t아카데미/7. data_analysis_ml_dl_llm/nlp/chatbot_df.dat'

# 로드처리 실습
with open(pre_data, 'rb') as f:
  df = pickle.load(f)
df.head(2)

전체 문장 11823개를 모두 처리하기는 너무 오래걸려서 사전 준비된 데이터로 로드했다.

하면서 나름 pickle도 복습

# 유사도 계산하여 답변처리
def ckeck_answer_similar(question=''):
  if not question:
    return '정확하게 입력 후 질문하시기 바랍니다.'
  q_vec = model.encode(question) # 토크나이저 변경 (768 토큰길이를 가진 토크나이저)
  # df의 이름 변경됨, 벡터값을 가진 컬럼명 변경 'em'
  df['score'] = df.em.apply(lambda x : cos_sim(x, q_vec))
  return df.loc[df['score'].idxmax()]['A'] 
  pass

ckeck_answer_similar('다시 돌아가고 싶어요?')
------------------------
돌아오길 바란다면 연락해보세요.
------------------------

좀 똑똑해졌다.

결론

 

 
  • 자연어 처리, LLM 등등 자연어를 데이터로, 기반으로 추론/생성 등 행위를 하는 모델들은 반드시 자연어를 수치화하는 토크나이저가 필요하다
    • 많은 언어를 커버할수로그 버전이 올라갈수록 토큰에 사용되는 사전의 수가 기하급수적으로 올라감 => 모델이 사용자의 질의를 더 잘 이해하게 되는 기반
    • LLM 모델이 새로 나오면 표현 가능한 토큰수 체크
    • 말뭉치 -> ... -> 임베딩된 백터 표현 : 과정이해
      • 실제
        • 스페셜 토큰 존재함
          • 문장의 시작과 끝 표시
          • 없는 토큰에 대한 표시
          • 문장 구분들 표시
          • ... => 통상 등 태그 형태로 표기함

개요

 

  • Activation function
  • 포지션
    • 절차
      • 데이터
      • 모델
          1. 인공신경망구성(CNN,RNN등 신경망 구조 속에 활성화함수 활용)
          • 직접 신경망 구성에 관여하지 않으면 접하지 못함.
          1. [학습회수(epoch),데이터크기(batch_size), 최적화도구(gd->..adam/nadam), 평가도구 세팅(정확도,손실)]
          1. 데이터주입 후 학습
 

  • 사용이유
    • 인공신경망의 성능 향상(정확도 향상) 위해 사용.
      • 최적화 도구
        • GD->SGD -> ... -> ADAM -> ..
        • 미세 조정을 통해 최적의 파라미터 W,b값 찾는 도구
      • 활성화 함수 사용
        • 은닉층 사용시
          • 데이터를 전반적으로 조정
            • 데이터를 선형(예측 정확도 높음)에서 비선형(예측 정확도 낮음)으로 변경등 분포 조정
          • 이로 인해 층을 더 깊게 구성하는 이유가 됨
            • 활성화를 미사용 -> 대부분 데이터가 조기에 선형 수준으로 조정 -> 과적합, 얕은 깊이의 구조가 됨
          • 단점
            • 정보 손실 발생
        • 출력측 사용시
          • (이진|다중)분류 처리등에 활용
            • 이진 : 시그모이드
            • 다중 : 소프트맥스
 

sigmoid

 

 
  • 머신러닝에서 개발, 초기 딥러닝 사용
  • 입력 : 실수( -무한대 ~ +무한대)
  • 출력 : 0 ~ 1 => 음수값 X
  • 용도 : 이진 분류
    • 출력층 사용
  • 문제점
    • 입력값이 커지거나 작아지면 거의 1.0, 0.0에 수렴
      • 기울기 0이 됨 -> 학습 효과 X -> 학습을 통해 만들어진 신경망내의 가중치값 미반영 -> 죽은 뉴런 문제 발생
  •  

sigmode 1
sigmoid 2

이진분류법에 사용되는 함수이다.

 

tanh

 

 
  • sigmoid 개선
  • 변동폭을 2배로 확장
  • 출력 : -1 ~ 1
    • 범위를 넓혀서 발생 빈도르 줄임 (죽은 뉴런)
    • LSTM-GRU 에서 내부적으로 사용됨
    • 해결 못함
  •  

tanh 조건식, 함수

 

relu

 

  • 최근 많이 사용 (20여년)
  • 장점
    • 가장 빠르게 처리(연산 비용 적음)
  • 단점
    • 죽은 뉴런 미해결(x값이 음수일때) -> 음수일때 미응답 발생 가능성 있음

 

relu 조건식, 함수

relu는 자주 사용되고 디벨롭도 relu 기준으로 많이 되었따.

leaky relu

 

 
  • 음수대역에서 기울기를 0.01로 부여 -> 완만하게 죽은 뉴런이 발생하도록 조정

 

leaky relu 조건식., 함수

PRelu

 

 
  • 0.01로 고정값이 아닌 파라미터를 받아서 처리
  • 자유도 부여(음수대역 기울기) -> 유연성 부여

 

prelu 조건식

ELU

 

 
  • 음수대역 -> 기울기 -> 미분적용
  • 직선 x -> 커브 도입
    • 단점 : 연산 비용 비싸짐
  •  

elu 조건식. 함수

Maxout

 

 


 
  • Relu의 장점 + 죽은 뉴런 문제 해결(학습이 안됨)
  • 파라미터 많다 -> 연산비용이 상승 -> 학습 속도 저하

 

maxout 조건식, 함수

Softmax

 

 

 
  • 전체에 대한 개별 비율 -> 다중(다항) 분류
  • 확률의 총합 => 1.0
  • 출력층 사용

 

softmax 조건식

사용자 정의 활성화함수 -> 발표?


 
  • 사내용으로 비공개 용도로 존재할 수 있음

오늘의 수업은 여기까지