선형 모델(Linear Model)

선형 모델(Linear Model)은 입력 변수(feature)와 가중치(weight)들 간의 선형 조합(linear combination)으로 출력 변수(target)를 예측하는 모델을 말합니다. 즉, 입력 변수의 가중합과 편향(bias)을 계산하여 출력 변수를 예측합니다.

선형 모델은 다양한 머신 러닝 작업에 사용됩니다. 예를 들어, 회귀(regression) 문제에서는 입력 변수와 출력 변수 사이의 관계를 선형적으로 모델링하여 출력 변수의 값을 예측합니다. 분류(classification) 문제에서는 입력 변수와 출력 변수 사이의 결정 경계(decision boundary)를 선형으로 모델링하여 데이터를 분류합니다.

선형 모델에는 다양한 종류가 있습니다. 대표적으로는 선형 회귀(Linear Regression), 로지스틱 회귀(Logistic Regression), 서포트 벡터 머신(Support Vector Machine), 선형 판별 분석(Linear Discriminant Analysis) 등이 있습니다.

쉬운 예로, 학생들의 수학 성적을 예측하는 모델을 생각해볼 수 있습니다. 이때 학생들의 공부시간, 출석률, 퀴즈 점수 등의 정보를 입력 변수로 사용하고, 이들의 가중합과 편향을 계산하여 최종 수학 성적을 예측하는 모델을 선형 모델로 구현할 수 있습니다.

코랩에서 실행되는 간단한 코드 예시는 다음과 같습니다.

실행하기 #선형 모델(Linear Model)

import numpy as np
from sklearn.linear_model import LinearRegression

# 입력 변수와 출력 변수 정의
X = np.array([[1], [2], [3], [4], [5]])
y = np.array([[2], [4], [6], [8], [10]])

# 선형 회귀 모델 생성 및 학습
model = LinearRegression()
model.fit(X, y)

# 예측
y_pred = model.predict([[6]])
print(y_pred)

위 코드는 입력 변수 X와 출력 변수 y를 정의하고, 이들을 이용하여 선형 회귀 모델을 생성하고 학습시키는 예시입니다. 최종적으로 입력 변수 [[6]]을 이용하여 예측을 수행하고, 결과를 출력합니다.

가중치(Weight)

머신러닝에서의 가중치는 입력 변수의 영향력을 나타내는 값으로, 선형 모델의 경우 각 입력 변수마다 가중치가 부여되어 해당 변수가 출력에 미치는 영향을 나타내게 됩니다. 이 가중치 값은 모델이 학습하면서 데이터에 적합하게 조정되며, 최적화 과정에서는 가중치를 조정하여 모델의 예측 성능을 향상시킵니다.

간단한 예를 들면, 다음과 같이 입력 변수 x와 출력 변수 y의 관계가 있는 데이터가 있다고 가정해봅시다.

x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]

이 경우, y는 x에 대해 직선의 형태로 관계가 있다고 볼 수 있습니다. 이 관계식은 y = 2x로 나타낼 수 있으며, 여기에서 2는 x의 가중치입니다. 이 가중치는 모델이 학습하면서 최적화 과정에서 조정됩니다.

코드로 예를 들어보면, 다음과 같이 Numpy를 이용하여 간단한 선형 모델을 만들고 학습시킬 수 있습니다.

실행하기 #가중치(Weight)

import numpy as np

# 입력 변수 x와 출력 변수 y 정의
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 6, 8, 10])

# 가중치 w 초기화
w = np.random.rand()

# 학습률과 최대 반복 횟수 설정
learning_rate = 0.01
max_iterations = 1000

# 경사 하강법으로 가중치 학습
for i in range(max_iterations):
    y_pred = w * x
    error = y - y_pred
    w = w + learning_rate * np.dot(x, error) / len(x)

# 학습된 가중치 출력
print(w)

이 코드는 입력 변수 x와 출력 변수 y를 정의하고, 초기 가중치 w를 무작위로 설정한 후 경사 하강법을 이용하여 가중치를 학습합니다. 최종적으로 학습된 가중치를 출력합니다.

수학에서의 기울기(Slope)와의 차이

편의상 수학시간에 많이 본 기울기 처럼 기억하면 되지만, 실제로 가중치(Weight)와 수학에서의 기울기(Slope)는 전혀 다른 개념입니다.

머신러닝에서의 가중치는 모델이 학습하는 과정에서 입력 변수에 대한 상대적인 중요도를 나타내는 값으로, 최적화 알고리즘을 사용하여 학습됩니다.

반면 수학에서의 기울기는 한 점에서의 함수 값의 변화량과 그 위치에서의 독립 변수의 변화량의 비율을 나타내는 값입니다. 함수의 기울기는 해당 점에서의 접선의 기울기를 말하며, 일반적으로 미분으로 구해집니다.

 

최적화 알고리즘

최적화 알고리즘은 모델의 예측값과 실제값의 차이를 최소화하는 가중치를 찾기 위해 사용됩니다. 다양한 최적화 알고리즘이 존재하지만, 대표적인 알고리즘들은 다음과 같습니다.

  1. 경사 하강법(Gradient Descent)
  2. 확률적 경사 하강법(Stochastic Gradient Descent)
  3. 미니 배치 경사 하강법(Mini-Batch Gradient Descent)
  4. 모멘텀(Momentum)
  5. 아다그라드(Adagrad)
  6. 아담(Adam)

경사 하강법은 비용 함수를 최소화하기 위해 가중치를 업데이트하는 방법으로, 가장 기본적인 최적화 알고리즘입니다. 확률적 경사 하강법은 경사 하강법의 변형으로, 매번 모든 데이터를 사용하지 않고 랜덤하게 선택된 데이터 하나씩을 사용하여 가중치를 업데이트합니다. 미니 배치 경사 하강법은 확률적 경사 하강법과 비슷하지만, 랜덤하게 선택된 일부 데이터를 미니 배치로 묶어서 사용합니다.

모멘텀은 이전에 업데이트된 가중치를 고려하여 새로운 가중치를 업데이트하는 방법입니다. 아다그라드는 학습률을 자동으로 조절하는 방법으로, 매개변수마다 다른 학습률을 적용하여 효과적인 학습을 도와줍니다. 아담은 모멘텀과 아다그라드를 결합한 알고리즘으로, 모멘텀과 아다그라드의 장점을 모두 가져와서 효과적인 학습을 돕습니다.

가중치 값은 학습 데이터에서 모델의 예측값과 실제값의 차이를 최소화하기 위해 최적화되므로, 학습 데이터와 관련된 가중치 값이며, 새로운 데이터에 대해서는 다시 최적화를 해야합니다. 이를테면, 학습한 모델이나 학습한 가중치를 그대로 사용하여 새로운 데이터에 대한 예측을 수행하는 것은 정확도가 떨어질 수 있습니다. 따라서 새로운 데이터에 대해서는 모델의 재학습이 필요합니다.

 

Logistic Regression

Logistic Regression은 로지스틱 함수를 사용하여 이진 분류(binary classification)를 수행하는 알고리즘입니다. 이 알고리즘은 입력 변수의 가중치 합을 로지스틱 함수에 넣어서 결과를 0과 1사이의 값으로 변환합니다. 이를 이진 분류에서 확률값으로 해석하여 예측하는 방식입니다.

이때 입력 변수의 가중치 합을 로지스틱 함수에 넣어서 확률값으로 변환하는데, 이 가중치는 입력 변수의 영향력을 나타내는 값입니다.

가중치 값은 일반적으로 최적화 알고리즘을 사용하여 계산됩니다. 최적화 알고리즘은 학습 데이터를 사용하여 모델의 예측값과 실제값의 차이를 최소화하는 가중치 값을 찾습니다. 이때 찾은 가중치 값은 모델의 학습 결과를 나타내는 것입니다.

예를 들어, 성별을 예측하는 문제를 생각해보겠습니다. 이 때, 입력 변수로는 나이, 키, 체중 등 여러 요인을 사용할 수 있습니다. 이러한 입력 변수들은 각각 가중치가 부여되어 로지스틱 함수에 적용됩니다. 로지스틱 함수의 출력값은 0과 1사이의 값으로 변환되며, 이를 성별에 대한 확률값으로 해석할 수 있습니다. 예를 들어, 로지스틱 함수의 출력값이 0.7이면, 해당 개체가 여성일 확률이 70%라는 것을 의미합니다. 따라서, 이 알고리즘은 이진 분류에서 예측 결과를 확률값으로 출력하므로, 분류 문제에서 매우 효과적으로 사용됩니다.

좀 더 쉬운 예를 들어보면, 로지스틱 회귀는 예를 들어 누군가의 공부 시간에 따라서 시험 합격 여부를 예측하는 경우를 생각해볼 수 있습니다. 이 때 공부 시간이 입력 변수이고, 합격 여부가 출력 변수입니다. 로지스틱 회귀 모델은 입력 변수(공부 시간)의 가중치 합을 로지스틱 함수에 넣어서 결과를 0~1 사이의 값으로 출력하고, 이를 이진 분류에서 확률값으로 해석하여 예측합니다. 즉, 공부 시간이 많을수록 시험에 합격할 확률이 높아진다고 예측할 수 있습니다.

전처리 작업에서 null 값 처리 (결측치 처리)

null 값은 데이터에서 값이 존재하지 않는 상태를 나타냅니다. 이는 데이터가 제대로 수집되지 않았거나, 처리 과정에서 누락되었을 수 있습니다. null 값이 있는 데이터를 그대로 사용하게 되면 해당 데이터를 이용한 분석 결과가 왜곡되거나 신뢰성이 떨어지는 문제가 발생할 수 있습니다.

따라서, 데이터를 분석하거나 모델을 학습할 때, null 값이 존재하는 데이터는 분석의 대상이 되면 안되며, 해당 데이터를 삭제하거나 다른 값으로 대체해야 합니다.

예를 들어, 다음과 같은 상황에서 null 값이 발생할 수 있습니다.

  • 설문조사에서 일부 응답자가 특정 항목에 대해 답변하지 않은 경우
  • 온라인 쇼핑몰에서 고객이 결제 정보를 입력하지 않은 경우
  • 주식 거래 데이터에서 특정 일자에 거래가 이루어지지 않은 종목이 있는 경우

 

이러한 결측치가 있는 데이터를 그대로 사용하면 분석 결과에 오류가 생기거나 모델의 성능이 저하될 수 있습니다.

따라서 null 값은 처리해 주어야 합니다. 일반적으로는 다음과 같은 방법들이 사용됩니다.

  1. 삭제: 결측치가 포함된 데이터를 삭제하는 방법입니다. 이 방법은 결측치가 일부인 경우에는 유용할 수 있지만, 결측치가 많은 경우에는 분석 결과에 영향을 미칠 수 있으므로 주의해야 합니다.
  2. 대체: 결측치를 다른 값으로 대체하는 방법입니다. 예를 들어, 평균값, 중앙값, 최빈값 등을 사용할 수 있습니다. 이 방법은 결측치가 적은 경우에 유용합니다.
  3. 예측: 결측치를 다른 변수를 이용하여 예측하는 방법입니다. 이 방법은 결측치가 많은 경우에 유용합니다.

null 값은 예를 들어서, 고객 정보 데이터셋에서 나이(age)가 null인 경우, 해당 고객의 나이 정보가 없는 것을 의미합니다. 이 경우에는 대체 방법을 사용하여 결측치를 대체하거나, 예측 방법을 사용하여 해당 고객의 나이를 예측할 수 있습니다.

정규식(regular expression)

정규식(regular expression)은 특정한 패턴의 문자열을 표현하기 위한 문법입니다. 머신러닝에서도 텍스트 데이터를 다룰 때 정규식을 활용하여 데이터를 처리합니다. 텍스트 데이터를 처리할 때, 일관적인 패턴의 문자열을 추출해내는 등의 작업을 수행하기 위해 정규식을 사용합니다. 예를 들어, 이메일 주소를 추출할 때, 이메일의 패턴에 맞는 정규식을 사용하여 이메일 주소를 추출할 수 있습니다.

정규식 패턴을 만들 때는 다양한 메타문자(meta-character)를 사용합니다. 메타문자는 특정한 의미를 가지며, 이를 조합하여 패턴을 만들어냅니다. 예를 들어, ‘\d’는 숫자를 의미하며, ‘\w’는 알파벳 대소문자와 숫자를 의미합니다. 이 외에도 ‘^’는 문자열의 시작을 의미하며, ‘$’는 문자열의 끝을 의미합니다.

머신러닝에서는 CountVectorizer, TfidfVectorizer 등의 벡터화 기법에서도 정규식을 사용합니다. CountVectorizer의 경우, token_pattern 인자에 정규식을 지정하여, 문자열을 추출할 때 사용합니다. 예를 들어, token_pattern=r’\b\w+\b’는 알파벳 또는 숫자가 1개 이상인 문자열만 추출하여 단어로 사용합니다. 이렇게 추출한 단어들을 벡터화하여 머신러닝 모델의 입력으로 사용합니다.

r’\b\w+\b’는 정규식 패턴으로서, 단어를 추출할 때 고려되는 문자열의 패턴을 지정합니다. 이 패턴은 다음과 같이 구성됩니다.

  • \b : 단어 경계를 의미합니다. 즉, 단어의 시작과 끝을 나타냅니다.
  • \w+ : 알파벳 또는 숫자가 1개 이상인 문자열을 나타냅니다. 이 문자열은 단어로서 추출됩니다.
  • r 은 “raw string”의 약자로서, 문자열을 해석할 때 escape 문자(예: \n, \t 등)를 무시하고 그대로 해석하도록 지정하는 파이썬의 문자열 리터럴 접두어입니다. 이를 사용하면 문자열 안에서 역슬래시를 사용할 때 일반적인 문자열 리터럴보다 편리하게 사용할 수 있습니다.예를 들어, 일반적인 문자열 리터럴에서는 역슬래시를 사용하려면 두 번 써야 합니다. 예를 들어, “\n”은 줄바꿈 문자를 나타냅니다. 그러나 r 접두어를 사용하면 “\n” 대신에 r”\n”으로 사용할 수 있습니다. 이렇게 하면 역슬래시를 두 번 쓰는 것보다 코드를 더욱 간결하게 작성할 수 있습니다.

    따라서 r’\b\w+\b’는 “raw string”으로서, 백슬래시 문자를 특수문자로 해석하지 않고 문자열 그대로 해석하도록 하는 것을 의미합니다.

따라서 r’\b\w+\b’ 패턴을 적용하면, 알파벳 또는 숫자가 1개 이상인 문자열을 단어로서 추출할 수 있습니다.

예를 들어, 다음과 같은 문자열이 있다고 가정해보겠습니다.

string = "The quick brown fox jumps over the lazy dog. 12345"

이 문자열에서 CountVectorizer(token_pattern=r’\b\w+\b’)를 사용하면, 다음과 같은 단어들이 추출됩니다.

['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog', '12345']

숫자는 단어로 인식되며, 구두점 등은 단어로 인식되지 않습니다.

NSMC(Naver Sentiment Movie Corpus) 데이터셋 이용 감성 분류(Sentiment Analysis) 문제 해결

실행 해 보기 (Corlab)

NSMC(Naver Sentiment Movie Corpus) 데이터셋은 20만 개의 영화 리뷰 데이터로 구성되어 있으며, 이를 바탕으로 긍정적인지, 부정적인지를 분류하는 감성 분류(Sentiment Analysis) 문제를 해결하는데 활용됩니다.

NSMC 데이터셋은 한글 데이터셋 중에서 가장 많이 사용되는 데이터셋 중 하나이며, 한국어 감성 분류 문제를 다루기 위한 대표적인 데이터셋으로 활용되고 있습니다. 이 데이터셋은 영화 리뷰에 대한 긍정/부정 정보를 레이블로 제공하고 있으며, 이를 학습 데이터로 활용하여 머신러닝 모델을 학습시킬 수 있습니다.

따라서 NSMC 데이터셋을 활용하면 한국어 감성 분류에 대한 다양한 연구나 분석을 수행할 수 있으며, 새로운 머신러닝 모델을 학습시키고 검증하는데에도 활용됩니다.

NSMC 데이터셋에서 train 데이터는 모델을 학습시킬 때 사용하는 원본 데이터이며, test 데이터는 학습된 모델의 성능을 평가하기 위해 사용하는 데이터로, 모델이 예측한 결과물과 실제 정답을 비교하여 모델의 성능을 측정합니다. 일반적으로 모델을 학습할 때 train 데이터와 test 데이터를 나누어서 사용하며, 모델의 성능이 일반화되고 테스트 데이터에 대해서도 잘 동작하는지 확인합니다.

https://raw.githubusercontent.com/e9t/nsmc/master/ratings_train.txt
NSMC 데이터셋의 경우, 각 영화 리뷰가 긍정(1)인지 부정(0)인지를 나타내는 레이블 데이터를 포함하고 있습니다. 이 레이블 데이터는 실제로 영화 리뷰를 작성한 사용자들이 부여한 점수를 기반으로 생성되었습니다. 예를 들어, 10점 만점에 8점 이상을 부여한 리뷰는 긍정(1)으로 분류되었고, 4점 이하를 부여한 리뷰는 부정(0)으로 분류되었습니다. 따라서 이 레이블 데이터는 사람이 임의로 만든 것이 아니라 실제 사용자들의 평가를 기반으로 생성된 것입니다.

https://raw.githubusercontent.com/e9t/nsmc/master/ratings_test.txt

ratings_test.txt 파일은 NSMC 데이터셋에서 제공하는 영화 리뷰 데이터 중에서 학습에 사용되지 않은 새로운 데이터로, 학습된 모델의 일반화 성능을 평가하기 위한 목적으로 제공됩니다. 따라서 해당 파일에 포함된 리뷰 데이터는 모두 실제로 존재하는 데이터이며, 해당 데이터에 대한 레이블(긍정/부정)을 예측하여 모델의 성능을 평가합니다.
예를 들어 데이터의 6270596 굳 ㅋ 1도 가상으로 만든 데이터가 아니며, 해당 리뷰는 실제로 존재하는 리뷰입니다. 이 리뷰에서는 “굳”이라는 축약어와 “ㅋ”이라는 이모티콘을 사용하여 긍정적인 평가를 전달하고 있으며, 해당 리뷰에 대한 레이블은 1(긍정)입니다.

NSMC 데이터셋을 이용하여 입력된 문장이 긍정인지 부정인지 판단하는 간단한 파이썬 코드는 다음과 같습니다. 이 코드는 train 데이터를 이용하여 CountVectorizer를 이용하여 단어장을 생성하고, 이를 이용하여 입력된 문장을 벡터화하여 Logistic Regression 모델을 이용하여 긍정/부정을 판단합니다.

 

import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression

# 데이터 불러오기
train_data = pd.read_csv('ratings_train.txt', sep='\t', na_values='NaN')
test_data = pd.read_csv('ratings_test.txt', sep='\t', na_values='NaN')

# null 값 제거
train_data.dropna(inplace=True)
test_data.dropna(inplace=True)

# CountVectorizer를 이용하여 단어장 생성
vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
vectorizer.fit(train_data['document'])

# train 데이터를 이용하여 Logistic Regression 모델 생성
lr = LogisticRegression(max_iter=5000)
train_X = vectorizer.transform(train_data['document'])
train_y = train_data['label']
lr.fit(train_X, train_y)

# test 데이터를 이용하여 예측 수행
test_X = vectorizer.transform(test_data['document'])
pred_y = lr.predict(test_X)

# 사용자로부터 입력 받은 문장 예측 수행
user_input = input("영화 리뷰를 입력하세요: ")
input_X = vectorizer.transform([user_input])
result = lr.predict(input_X)

# 예측 결과 출력
if result[0] == 1:
    print("긍정적인 리뷰입니다.")
else:
    print("부정적인 리뷰입니다.")

코드 설명을 좀더 상세히 하겠습니다.

#CountVectorizer를 이용하여 단어장 생성 부분

vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
vectorizer.fit(train_data['document'])

CountVectorizer는 입력된 텍스트 데이터를 분석하여 단어장을 생성하는 역할을 합니다. 단어장이란, 분석된 텍스트 데이터에서 중복되지 않는 단어들의 집합을 의미합니다.  이때, 기본적으로는 공백을 기준으로 단어를 분리합니다.

ratings_train.txt 의 “3819312 흠…포스터보고 초딩영화줄….오버연기조차 가볍지 않구나 1 “를 이용해 설명해 보겠습니다.

위 코드에서는 train_data['document']의 텍스트 데이터를 이용하여 CountVectorizer를 통해 단어장을 생성하는 부분입니다.

이를 ratings_train.txt 파일의 텍스트 데이터인 ‘흠…포스터보고 초딩영화줄….오버연기조차 가볍지 않구나’로 대체해보면 다음과 같습니다.이를 실행하면 ‘흠’, ‘포스터보고’, ‘초딩영화줄’, ‘오버연기조차’, ‘가볍지’, ‘않구나’ 등의 단어가 단어장으로 생성됩니다. 이 단어장은 이후에 다른 텍스트 데이터에 대해서도 적용되어 해당 데이터를 벡터화하는 데 사용됩니다.

위에서 주어진 코드에서는 token_pattern=r'\b\w+\b' 옵션을 통해 정규식 패턴을 설정하여, 단어를 추출할 때는 알파벳 또는 숫자가 1개 이상인 문자열만 고려하도록 설정하였습니다. 따라서, “흠”, “포스터보고”, “초딩영화줄”, “오버연기조차”, “가볍지”, “않구나” 등의 단어가 추출됩니다.
이부분만 해 보겠습니다.
실행하기 (NSMC-1)

from sklearn.feature_extraction.text import CountVectorizer

# ratings_train.txt 파일에서 한 줄을 가져옴
text = '흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나'

# CountVectorizer를 이용하여 단어장 생성
vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
vectorizer.fit([text])

# 단어장에 생성된 단어 출력
print(vectorizer.get_feature_names())

CountVectorizer는 텍스트 데이터를 입력 받아 각 단어가 몇 번 나타나는지를 세어서 단어장(vocabulary)을 생성하는 도구입니다. 예를 들어, “흠”, “포스터보고”, “초딩영화줄”, “오버연기조차”, “가볍지”, “않구나” 등의 단어가 추출되면, 이 단어들을 단어장에 등록하고 각 단어에 인덱스를 부여합니다. 이후, 각 문장을 벡터화할 때는 각 단어가 해당 문장에서 몇 번 나타나는지를 세어서 각 단어의 인덱스에 해당하는 원소에 그 횟수를 넣어줍니다. 이렇게 벡터화하면, 각 문장은 단어의 빈도수로 이루어진 벡터로 표현됩니다.

벡터 정보의 해당 단어의 횟수 정보와 단어 내용 자체는 CountVectorizer에서 생성된 단어장(vocabulary)에 저장됩니다. CountVectorizer는 입력된 텍스트 데이터에서 단어를 추출하고, 추출한 단어들을 기반으로 단어장을 생성합니다. 이때, 각 단어는 고유한 인덱스 번호를 부여받습니다.

예를 들어, “초딩영화줄”과 “오버연기조차”가 추출되었고, 이들이 단어장에서 각각 0번과 1번의 인덱스를 부여받았다면, “초딩영화줄”이 3번, “오버연기조차”가 5번 등장한다면, 벡터 정보에서는 0번 인덱스에 해당하는 값이 3이 되고, 1번 인덱스에 해당하는 값이 5가 됩니다. 이렇게 벡터 정보와 단어 내용이 인덱스를 활용하여 연결되는 것입니다.

# train 데이터를 이용하여 Logistic Regression 모델 생성

lr = LogisticRegression(max_iter=5000)
train_X = vectorizer.transform(train_data['document'])
train_y = train_data['label']
lr.fit(train_X, train_y)

Logistic Regression은 통계학에서 개발된 분류 모델 중 하나로, 데이터를 분석하여 해당 데이터가 어떤 범주(class)에 속하는지를 예측하는 모델입니다. 이 모델은 입력 변수의 가중치 합을 로지스틱 함수(sigmoid function)에 넣어서 결과를 0~1사이의 값으로 출력하고, 이를 이진 분류(binary classification)에서 확률값으로 해석하여 예측합니다.

위의 코드에서는 sklearn 라이브러리의 LogisticRegression 클래스를 이용하여 Logistic Regression 모델을 생성합니다. 이를 위해 max_iter 매개변수를 5000으로 설정하여 최적화를 위한 최대 반복 횟수를 설정합니다. 이후, CountVectorizer 클래스로부터 생성된 단어장에서 transform 메소드를 이용하여 train 데이터의 문서들을 벡터 형태로 변환한 후, 이를 train_X 변수에 저장합니다. train_y 변수에는 train 데이터의 레이블을 저장합니다. 마지막으로, LogisticRegression 모델의 fit 메소드를 이용하여 train_X와 train_y를 이용하여 모델을 학습시킵니다.

한국어 말뭉치를 이용한 Chat GPT API 이용 서비스 구축

한국어로는 ‘말뭉치’ 혹은 ‘말모둠’으로 번역하는, 코퍼스(corpus)는 글 또는 말 텍스트를 모아 놓은 것입니다. 말뭉치는 주로 기계 학습 알고리즘을 훈련시키기 위해 사용되며, 텍스트 분류, 정보 검색, 기계 번역, 감성 분석 등에 사용됩니다. 대규모 말뭉치는 자연어 처리 모델의 성능을 크게 향상시킬 수 있으며, 그 중에서도 한국어 말뭉치 데이터는 한국어 자연어 처리 분야에서 매우 중요한 자원입니다.

ChatGPT API를 이용해 한국어 말뭉치를 사용해 서비스를 고도화 할 때 주의해야 할 점은 다음과 같습니다.

  1. 데이터의 출처와 사용에 대한 법적 문제 : 머신러닝을 위해서는 충분한 데이터가 필요합니다. 그러나 데이터의 출처나 사용에 대해서는 법적 문제가 발생할 수 있습니다. 따라서 데이터의 출처와 사용에 대한 법적인 제약사항을 확인하고, 이에 따라 데이터를 사용해야 합니다.
  2. 데이터의 품질과 양질의 데이터 확보: 데이터의 품질과 양질의 데이터 확보는 머신러닝 알고리즘의 성능과 결과에 영향을 미칩니다. 따라서 적절한 크기와 품질의 데이터를 사용하여 머신러닝 모델을 학습시켜야 합니다.
  3. 사용자의 프라이버시 보호: 서비스 이용 중 사용자의 프라이버시 보호는 매우 중요합니다. 머신러닝 모델을 학습시키기 위해서는 사용자의 데이터를 수집할 수 있습니다. 이 때, 사용자의 데이터를 보호하고 적절한 보안 조치를 취해야 합니다.
  4. 데이터 전처리와 모델 학습에 대한 기술적인 이해: 한국어 말뭉치를 이용해 머신러닝 모델을 학습시키기 위해서는 데이터 전처리와 모델 학습에 대한 기술적인 이해가 필요합니다. 이를 위해서는 머신러닝과 자연어 처리 기술에 대한 이해가 필요하며, 이를 충분히 습득해야 합니다. 기본적인 머신러닝에 대해서 배우고자 하시는 분은
    샵투스쿨의  왕초보! 텐서플로우 2.0 머신러닝 기초 강좌 를 보세요(무료).

그럼 아래의 한국어 말뭉치 데이터를 이용해 보겠습니다. (하나는 train, 하나는 test)

https://raw.githubusercontent.com/e9t/nsmc/master/ratings_train.txt

https://raw.githubusercontent.com/e9t/nsmc/master/ratings_test.txt

Chat GPT API는 미리 학습된 GPT 모델을 이용하여 자연어 생성을 수행하는 API입니다. 따라서, 한국어 말뭉치 데이터를 이용하여 Chat GPT API를 이용하려면, 다음과 같은 절차를 따르면 됩니다.

  1. 한국어 말뭉치 데이터 다운로드: 위에서 제공한 링크에서 다운로드할 수 있습니다.  “ratings_train.txt”와 “ratings_test.txt” 두 개의 파일이 있습니다.
  2. 데이터 전처리: 말뭉치 데이터를 Chat GPT 모델이 이해할 수 있는 형태로 변환해야 합니다. 이를 위해서는 데이터를 텍스트 파일로 저장하고, 각 줄은 하나의 문장이어야 합니다. 또한, 줄 바꿈 문자를 이용하여 문장 구분을 해야 합니다.예시 코드
    import os
    
    input_file = 'ratings_train.txt'
    output_file = 'korean_corpus.txt'
    
    with open(input_file, 'r', encoding='utf-8') as f:
        with open(output_file, 'w', encoding='utf-8') as out:
            next(f)  # 첫 번째 줄은 건너뜀
            for line in f:
                _, sentence, _ = line.strip().split('\t')
                out.write(sentence + '\n')
    

    또 전처리 작업에는 형태소 분석, 품사 태깅 등이 포함될 수 있습니다.

  3. Chat GPT API 사용: 전처리된 말뭉치 데이터를 이용하여 Chat GPT API를 사용할 수 있습니다. API는 OpenAI에서 제공하는 GPT 모델을 이용하며, API 사용에는 인증키가 필요합니다. 아래는 한국어 말뭉치 데이터를 전처리하여 ChatGPT API를 이용하는 간단한 예시 코드입니다. 이 코드는 KoNLPy 패키지를 사용하여 한국어 형태소 분석을 수행하고, ChatGPT API를 이용하여 대화를 생성합니다.
    import openai
    from konlpy.tag import Komoran
    
    # OpenAI API key 설정
    openai.api_key = "YOUR_API_KEY"
    
    # 한국어 형태소 분석기 설정
    komoran = Komoran()
    
    # 대화 생성 함수
    def generate_text(prompt):
        response = openai.Completion.create(
            engine="davinci",
            prompt=prompt,
            max_tokens=60,
            n=1,
            stop=None,
            temperature=0.5,
        )
    
        message = response.choices[0].text.strip()
        return message
    
    # 입력 문장
    input_text = "안녕하세요. 오늘 날씨가 참 좋네요."
    
    # 형태소 분석
    tokens = komoran.pos(input_text)
    
    # 분석 결과를 ChatGPT API 입력 형식에 맞게 가공
    prompt = "The following is a conversation between a human and an AI. The human says, '{}'\n\nThe AI responds:".format(
        " ".join(["{}|{}".format(token[0], token[1]) for token in tokens])
    )
    
    # 대화 생성
    response = generate_text(prompt)
    
    print("입력 문장:", input_text)
    print("대화 생성 결과:", response)
    
    
    

    이 코드는 입력 문장을 한국어 형태소 분석기를 이용해 형태소 단위로 분석한 후, ChatGPT API 입력 형식에 맞게 가공한 다음, API를 이용하여 대화를 생성합니다. 최종적으로 생성된 대화를 출력합니다.

 

GPT-J-6B 모델 corlab 에서 사용해 보기 (corlab pro 필요)

GPT-J-6B 모델을 무료로 사용하기 위해서는 Hugging Face의 Transformers 라이브러리를 사용하면 됩니다. 아래는 Transformers 라이브러리를 사용하여 GPT-J-6B 모델을 로드하고 예측하는 예제 코드입니다.

from transformers import GPTJForCausalLM, GPT2Tokenizer

# GPT-J-6B 모델과 토크나이저 로드
tokenizer = GPT2Tokenizer.from_pretrained("EleutherAI/gpt-j-6B")
model = GPTJForCausalLM.from_pretrained("EleutherAI/gpt-j-6B")

# 입력 문장
input_text = "Hello, how are you?"

# 토큰화
input_ids = tokenizer.encode(input_text, return_tensors="pt")

# GPT-J-6B 모델에 입력하여 예측
output = model.generate(input_ids, max_length=50, do_sample=True)

# 디코딩하여 출력
generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
print(generated_text)

위 코드에서 GPTJForCausalLM은 GPT-J-6B 모델 클래스를, GPT2Tokenizer는 GPT-J-6B 모델에 맞는 토크나이저를 의미합니다. 이 코드를 실행하면 “Hello, how are you? I’m doing well, thank you for asking.”와 같은 문장이 출력됩니다.

이 코드를 사용하기 위해서는 transformers 라이브러리가 설치되어 있어야 합니다. pip install transformers 명령어를 사용하여 라이브러리를 설치할 수 있습니다.

corlab에서는 다음과 같이 하시면 됩니다.

 

!pip install transformers

 

앞서 말씀드린것 처럼 자원을 많이 사용하므로 Colab Pro 를 사용하셔야 합니다.

git

 

고성능 딥러닝 프레임워크 JAX (Corlab)

JAX (Just After eXecution;실행직후)
JAX 라이브러리는 TensorFlow와 유사한 기능을 가지고 있으며, 특히 자동 미분과 XLA(accelerated linear algebra) 및 JIT(just-in-time) 컴파일 기능을 강조합니다. 이러한 기능은 머신러닝 알고리즘을 더욱 효율적으로 구현하고 최적화하는 데 도움이 됩니다.

JAX 라이브러리가 “Just After eXecution”의 약자로 실행직후 라는 이름을 가지게 된것은,  NumPy, SciPy, PyTorch 등과 같은 수치 연산 라이브러리와 같이 계산 그래프를 구성하고 실행하기 직전까지 모든 것이 동적으로 결정되는 동적 계산 그래프 (dynamic computation graph) 라이브러리이기 때문입니다. 이러한 동적 계산 그래프 방식은 머신러닝 프레임워크에서 일반적으로 사용되는 정적 계산 그래프와 대조적입니다. JAX는 JIT(Just-In-Time) 컴파일러와 함께 사용되어 동적 계산 그래프를 효율적으로 컴파일하여 실행 시간을 최적화합니다. 따라서 “Just After eXecution”이라는 이름이 지어진 것입니다.

JAX는 pip로 설치할 수 있으며, 아래 명령어를 사용하여 설치할 수 있습니다.

pip install jax jaxlib

다만, JAX는 GPU를 사용하기 때문에 GPU가 없는 경우 CPU 버전으로 설치해야 합니다. GPU가 없는 경우 아래 명령어를 사용하여 설치할 수 있습니다.

pip install jax jaxlib==0.1.70+cpu -f https://storage.googleapis.com/jax-releases/jax_releases.html

 

아래는 JAX를 사용하여 간단한 선형 회귀 모델을 구현하는 예시입니다.GPU 가 없는 컴퓨터를 사용하시는 분을 위해 구글 colab에서 실행 가능하도록 작성되었습니다.

실행하기

 import jax.numpy as jnp
from jax import grad

# 선형회귀 모델 함수
def linear_regression(X, w):
    return jnp.dot(X, w.T)

# 평균제곱오차 손실 함수
def mse_loss(y_true, y_pred):
    return jnp.mean((y_true - y_pred) ** 2)

# 경사하강법 함수
def gradient_descent(w, X, y, learning_rate):
    grad_func = grad(mse_loss)
    grad_w = grad_func(y, linear_regression(X, w))
    return w - learning_rate * grad_w

# 입력과 출력 정의
X = jnp.array([[1., 1.], [2., 2.], [3., 3.], [4., 4.]])
y = jnp.array([[2.], [4.], [6.], [8.]])

# 가중치 초기값 설정
w = jnp.array([[1., 1.]])

# 학습
for epoch in range(10):
    # 예측 계산
    y_pred = linear_regression(X, w)

    # 손실 계산
    loss = mse_loss(y, y_pred)
    print(f"에포크 {epoch}\n가중치: {w}\n손실: {loss}\n예측결과: {y_pred}")

    # 경사하강법을 사용하여 가중치 갱신
    w = gradient_descent(w, X, y, 0.1)

git

JAX가 tensorflow 보다  쌘놈인가?

 

JAX (Just After eXecution) 는 기계 학습 라이브러리로, Google에서 개발했습니다. TensorFlow와 마찬가지로 JAX도 딥 러닝 모델을 만들고 훈련시키는 데 사용됩니다. 그러나 TensorFlow와 JAX 사이에는 몇 가지 차이점이 있습니다.

첫째, JAX는 미분 가능한 함수만 허용합니다. 이는 딥 러닝 모델을 구축하는 데 도움이 됩니다. 미분 가능한 함수는 모든 미분 가능한 지점에서 기울기를 가지기 때문입니다. JAX는 이러한 함수만 지원하므로 모델에서 발생할 수 있는 다양한 오류를 방지할 수 있습니다.

둘째, JAX는 함수를 컴파일하고 JIT(Just-in-time) 컴파일러로 컴파일합니다. 이는 계산 속도를 빠르게 만들어줍니다. TensorFlow와 같은 라이브러리는 모델을 그래프로 변환한 다음 실행합니다. 반면 JAX는 모델을 즉시 컴파일하고 실행합니다.

셋째, JAX는 TensorFlow와 비교해 더 깔끔한 구문을 제공합니다. TensorFlow는 상태 변수와 그래프를 별도로 추적해야 하지만 JAX는 함수형 프로그래밍을 사용하여 코드를 작성하므로 보다 간결합니다.

JAX와 TensorFlow는 모두 딥러닝 라이브러리이지만, 각각의 장단점이 있습니다. 따라서 뛰어난 것은 사용하는 목적과 상황에 따라 다릅니다.

JAX는 JAX를 이용한 코드는 다른 프레임워크와 달리 일부 또는 전체가 컴파일됩니다. 이는 빠른 속도와 함께 간소화된 코드를 제공합니다. 또한 JAX는 XLA 컴파일러를 사용하므로, TPU에서 더 빠르게 실행할 수 있습니다.

반면, TensorFlow는 이미 매우 널리 사용되고 있으며, TensorFlow 기반의 라이브러리 및 프레임워크가 많이 개발되어 있습니다. TensorFlow는 또한 다양한 하드웨어를 지원하며, 자체적으로 GPU를 활용하여 연산을 가속화할 수 있습니다.

따라서 뛰어난 것은 사용하는 목적과 상황에 따라 다르므로, 적절한 상황에서 적합한 도구를 선택하는 것이 중요합니다.

다음은 위에 JAX로 작성된 선형 회귀 모델 코드를 TensorFlow로 변환한 예시입니다.
JAX는 TensorFlow와 비슷한 API를 가지고 있기 때문에 코드 변환이 그리 어렵지 않습니다. 그러나 두 라이브러리의 내부 구현 방식이 다르기 때문에 성능 차이가 있을 수 있습니다. 또한 TensorFlow는 GPU를 이용한 병렬 처리에 대한 지원이 더욱 뛰어나기 때문에 대규모 데이터에 대한 학습 속도에서 우위를 보입니다.

import tensorflow as tf
import numpy as np

# 입력과 출력 정의
X = np.array([[1., 1.], [2., 2.], [3., 3.], [4., 4.]])
y = np.array([[2.], [4.], [6.], [8.]])

# 가중치 초기값 설정
w = tf.Variable(np.array([[1., 1.]]))

# 선형 회귀 모델 함수
def linear_regression(X, w):
    return tf.matmul(X, tf.transpose(w))

# 평균제곱오차 손실 함수
def mse_loss(y_true, y_pred):
    return tf.reduce_mean(tf.square(y_true - y_pred))

# 경사하강법 함수
def gradient_descent(w, X, y, learning_rate):
    with tf.GradientTape() as tape:
        y_pred = linear_regression(X, w)
        loss = mse_loss(y, y_pred)
    grads = tape.gradient(loss, w)
    w.assign_sub(learning_rate * grads)
    return w

# 학습
for epoch in range(10):
    # 예측 계산
    y_pred = linear_regression(X, w)

    # 손실 계산
    loss = mse_loss(y, y_pred)
    print(f"에포크 {epoch}\n가중치: {w}\n손실: {loss}\n예측결과: {y_pred.numpy()}")

    # 경사하강법을 사용하여 가중치 갱신
    w = gradient_descent(w, X, y, 0.1)

 

아래는 jax로 작성된 코드를 tensorflow도 사용하지 말고, python으로 코딩한 예시입니다. 속도 측면에서는 jax나 tensorflow보다 느릴 수 있습니다.

 

import numpy as np

# 선형회귀 모델 함수
def linear_regression(X, w):
    return np.dot(X, w.T)

# 평균제곱오차 손실 함수
def mse_loss(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 경사하강법 함수
def gradient_descent(w, X, y, learning_rate):
    def mse_grad(y, y_pred):
        return -2 * np.mean((y - y_pred) * X, axis=0)
    
    grad_w = mse_grad(y, linear_regression(X, w))
    return w - learning_rate * grad_w

# 입력과 출력 정의
X = np.array([[1., 1.], [2., 2.], [3., 3.], [4., 4.]])
y = np.array([[2.], [4.], [6.], [8.]])

# 가중치 초기값 설정
w = np.array([[1., 1.]])

# 학습
for epoch in range(10):
    # 예측 계산
    y_pred = linear_regression(X, w)

    # 손실 계산
    loss = mse_loss(y, y_pred)
    print(f"에포크 {epoch}\n가중치: {w}\n손실: {loss}\n예측결과: {y_pred}")

    # 경사하강법을 사용하여 가중치 갱신
    w = gradient_descent(w, X, y, 0.1)

JAX의 자동 미분 기능

JAX는 자동 미분 기능을 내장하고 있기 때문에 딥러닝 모델의 학습에 필요한 그래디언트 계산을 자동으로 수행할 수 있습니다.딥러닝에서 모델 학습은 주로 그래디언트 기반 최적화 알고리즘을 사용하여 이루어집니다. 그래디언트 기반 최적화 알고리즘은 손실 함수의 그래디언트를 계산하여 모델 파라미터를 업데이트하는 방식으로 작동합니다. 따라서 자동 미분 기능이 없으면 그래디언트를 직접 계산해야 하는 번거로움이 있습니다.

JAX는 그래디언트 자동 계산 기능을 제공함으로써 이러한 번거로움을 줄여줍니다. 이를 통해 개발자는 모델 학습에 집중할 수 있습니다.

예를 들어, 다음과 같은 간단한 신경망 모델이 있다고 가정해봅시다.

실행#JAX의 자동 미분 기능

import jax.numpy as jnp
from jax import grad

def loss_fn(params, x, y_true):
    y_pred = jnp.dot(x, params)
    loss = jnp.mean((y_pred - y_true) ** 2)
    return loss

params = jnp.array([0.5, -0.2, 1.0])
x = jnp.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
y_true = jnp.array([10, 20, 30])

grad_loss_fn = grad(loss_fn)

grad_params = grad_loss_fn(params, x, y_true)

print(grad_params)

위 코드에서는 간단한 3개의 입력값과 1개의 출력값을 가지는 선형 회귀 모델을 정의하였습니다. 이 모델의 손실 함수(loss function)는 평균 제곱 오차(Mean Squared Error)를 사용하였습니다. 그리고 이 손실 함수의 그래디언트(gradient)를 자동으로 계산하기 위해 JAX의 grad 함수를 이용하였습니다.

grad 함수는 함수의 인수로 전달된 함수의 그래디언트를 계산하여 반환하는 함수입니다. grad 함수가 반환한 그래디언트 값은 params에 대한 손실 함수의 편미분값이므로, 이 값은 params를 어떻게 업데이트해야 하는지 알려주는 방향성을 가집니다. 따라서 이 값을 이용하여 모델의 가중치(weight)를 업데이트하면 됩니다.

위 코드를 실행하면, grad_params의 값으로[-128.40001, -154.40001, -180.40001] 이 출력됩니다. 이 값은 입력값 x가 [1.0, 2.0, 3.0]일 때, 손실 함수를 x의 각 요소에 대해서 미분한 그래디언트 벡터를 의미합니다.