인공지능(Artificial Intelligence)/자연어 처리(natural language processing)

[tensorflow] 자연어처리(NLP) 1. 기초다지기(layers)

HAN_PY 2020. 10. 31. 20:36
반응형

0. 들어가면서

 자연어처리, 즉 글자를 컴퓨터가 이해할 수 있게 만드는 것이다. CNN과 RNN의 차이도 모르고, 단 한번도 구현해 본 적이 없다면, 이곳은 오아시스 같은 해결책을 줄 수 있을 것이다. 시작해보자. 

 

 혹시나 텐서플로의 기초가 아닌 자연어 처리에 대한 전반적인 적용 알고리즘에 대해 알고 싶다면, 아래의 링크를 들어가 보자.

han-py.tistory.com/249?category=942088

 

자연어처리 발전흐름(RNN에서 BERT)

1. RNN (Recurrent Neural Network) RNN이 왜나왔을까? 기존 신경망은 연속적인 시퀀스를 처리하기 어렵다. 따라서 입력의 순서가 중요한 분야인 자연어 처리, 음성인식, 주식, 날씨, 음악 같은 부분에서 한

han-py.tistory.com

 

우리가 구현하고 자하는 것은 특정 목적에 맞게 동작하는 AI 모델이 될 것이다. 그 모델을 구성하는 가장 기초부분이 layer라고 할 수 있다. 따라서 tensorflow에서 지원하는 모듈 layer의 종류에 대해 알아보고, 그 layer를 이용해서 model을 만드는 법에 대해 알아 볼 것이다. 그 후에 글자를 천처리 하는 방법에 대해 알아 볼 것이다. 

 

 

1. tensorflow

 여기서는 python을 활용하는 tensorflow를 활용할 예정이다. 특징은 다음과 같다.

  • 함수만 정의하면 자동으로 미분
  • python 기반의 안정적인 라이브러리
  • 유연성과 확장성
  • 구글이 만듦

tensorflow에서 tensor란 N차원 매트릭스를 의미하고 tensor를 flow 한다는 것은 Data flow graph를 이용하여 수치 연산을 하는 과정이다.

 

그래프의 노드(Node, 신경망 그림에서 자주 보이는 동그라미로 바로 아래 곧 나온다)는 수치 연산, 변수, 상수를 나타내고 에지(edge, 노드를 이어 주는 선)는 다차원 데이터 배열(tensor)을 나타낸다.

 

 

 

2. tf.keras.layer

 여기서는 모델을 감싸고 있는 layer의 기초에 대해 알아볼 것 이다. 실질적인 코드는 model 만들 때 layer를 다룰 것이니 여기서는 개념들과 인자들만 이해하고 넘어가면 된다.

 

 tensorflow에서는 딥러닝 모델을 만들 때, 아파트를 짓듯이 모델도 한 층(layer)를 쌓아서 만든다. 즉, layer가 보며 모델이 되고 모델의 layer도 쉽게 바꿀 수 있다는 것이 tensorflow의 큰 장점이다. 이러한 층을 쌓는 것들 중에 가장 많이 쓰이고 있는 tf.keras.layer의 모듈에 대해 알아보자. 순서는

tf.keras.layers.Dense

tf.keras.layers.Dropout

tf.keras.layers.Conv1D

tf.keras.layers,MaxPool1D

순서로 하나씩 알아보자.

 

2.1 tf.keras.layers.Dense

 

 Dense란 신경망 구조의 가장 기본적인 형태로 아래의 수식을 만족하는 기본적인 신경망 형태의 층을 만드는 함수다.

 

y=f(Wx+b)

 

  • x : 입력벡터
  • b : 편향벡터
  • W : 가중치행렬
  • f : 활성화 함수

출력값 = 활성화함수 x (가중치행렬 x 입력벡터 + 편향벡터)

 

위의 수식을 그림으로 보면, 아래와 같은 은닉층(처음 층과 마지막 층의 사이에 있는 층)이 없는 간단한 신경망 형태가 된다. 즉, 은닉층이 없다는 것은 layer가 2개밖에 없는 것이다.

 위에서 말한 노드가 그림에서 동그란 원이 되고, 에지가 노드를 이어주는 선이 된다. 그리고 노드가 W(가중치)를 곱해지는 것이라고 보면 된다.

 

 

2.1.1 기본 코드

위의 내용을 코드로 구현하려면, 아래와 같이 가중치 변수를 모두 정의해 줘야한다.(tensorflow에서는 코드 한 줄로 작성 가능)

# y = f(Wx+b) 구현
# import tensorflow as tf

W = tf.Variable(tf.random_uniform([5, 10], -1.0, 1.0))
b = tf.Variable(tf.zeros([10]))
y = tf.matmul(W, x) + b

 

  • tf.random_uniform 함수는 정규분포 난수를 생성하는 함수로, 배열의 shape, 최소값, 최대값을 파라미터로 사용한다. 즉, 최소값과 최대값 사이의 난수를 생성해서 배열에 넣어준다.
  • tf.zeros는 적혀진 배열의 shape에 맞게 모든 원소의 값이 0인 텐서를 생성한다.

 옛날에는 위와 같이 모든 변수들을 선언 후에 하나하나씩 연산을 해줘야했다. 그러나 tensorflow에서는 자동으로 만들어준다. 그리고 tensorflow에서는 인자 설정에 따라 활성화 함수 설정, 초기화 방법, 정규화 방법 등 다양한 기능을 쉽게 사용 가능하다.

 

 

 

2.1.2 tensorflow로 Dense 구현하기

 

 케라스 Dense를 사용하기 위해서는 먼저 객체를 생성해 주자

dense = tf.keras.layers.Dense(...)

 

 

그리고 생성한 Dense 객체에 입력값을 넣어줘야한다. 입력값을 넣는 방법에는 2가지가 있다.

# 1. 객체 생성 이 후에 입력값 설정
dense = tf.keras.layers.Dense( ... )
output = dense(input)

# 2. 객체 생성 시 입력값 설정
output = tf.keras.layers.Dense( ... )(input)

 

 

Dense 객체 생성 시 위의 코드에서 ( ... )부분에 여러 인자를 추가여여 가중치, 초기화 방법, 활성화 함수 같은 여러 옵션을 지정할 수 있다. 그 종류에 대해 알아보자. 객체 생성 시 지정할 수 있는 인자는 아래와 같다.

  def __init__(unit,
               activation=None,
               use_bias=True,
               kernel_initializer='glorot_uniform',
               bias_initializer='zeros',
               kernel_regularizer=None,
               bias_regularizer=None,
               activity_regularizer=None,
               kernel_constraint=None,
               bias_constraint=None,
               **kwargs):
  • unit : 출력 값의 크기로 Integer이나 Long 형태다.
  • activation : 활성화 함수를 나타낸다.
  • use_bias : 편향(b)를 사용할지 여부를 나타내고 Boolean 값 형태다.
  • kernel_initializer : 가중치(W) 초기화 함수
  • bias_initializer : 편향 초기화 함수
  • kernel_regularizer : 가중치 정규화 방법
  • bias_regularizer : 편향 정규화 방법
  • activity_regularizer :출력 값 정규화 방법
  • kernel_constraint : Optimizer에 의해 업데이트 된 이후에 가중치에 적용되는 부가적인 제약 함수
  • bias_constraint : Optimizer에 의해 업데이트된 이후에 편향에 적용되는 부가적인 제약 함수

위의 인자 중에 사용할 인자만 적어주면 된다.

 

 

 

2.1.3 사용법

우리는 입력값에 대해 활성화 함수인 시그모이드 함수를 사용할 것이고, 출력값은 10개의 값을 출력하는 Fully Connected Layer(완전 연결 계층)를 구현해 보자.

inputs = tf.keras.layers.Input(shape = (20, 1))  # input size를 넣어주면 된다.
output = tf.keras.layers.Dense(units = 10, activation = tf.nn.sigmoid)(inputs)

 

10개의 노드를 가지는 은닉층과 마지막 출력 값으로 2개의 노드가 있는 신경망의 예는 아래와 같을 것이다.

inputs = tf.keras.layers.Input(shape = (20, 1))  # input size를 넣어주면 된다.
hidden = tf.keras.layers.Dense(units = 10, activation = tf.nn.sigmoid)(inputs)
output = tf.keras.layers.Dense(units = 2, activation = tf.nn.sigmoid)(hidden)

 

사용법은 이렇게 굉장히 간단하기 때문에 꼭 익혀두자.

 

 

 

 

2.2 tf.keras.layers.Dropout

2.2.1 기본개념

 

 신경망 모델을 만들 때 생기는 문제점 중에 대표적인 것이 과적합(Overfitting)이다. 보통 과적합 문제는 정규화(Regularization) 방법으로 많이 해결하고 정규화 방법 중 대표적인 것인 Dropout이다. Dropout도 역시 tensorflow에서 모델에 쉽게 적용할 수 있게 간단한 모듈을 제공해 준다.

 

풀어서 이야기를 하면 학습 데이터에 과정합되는 상황을 방지하기 위해 학습 시 특정 확률로 노드들의 값을 0으로 든들게 된다. 이러한 과정은 학습할 때만 적용되고 예측 혹은 테스트할 때는 적용되지 않아야 한다. 물론 keras에는 이러한 부분들이 자동으로 적용된다.

 

 

이것도 아래와 같이 먼저 객체를 생성해서 사용한다.

 tf.keras.layers.Dropout( ... )

 

그리고 Dense와 같은 방법으로 입력 같을 넣어주면된다.

# 1. 객체 생성 이 후에 입력값 설정
dropout = tf.keras.layers.Dropout( ... )
output = dropout(input)

# 2. 객체 생성 시 입력값 설정
output = tf.keras.layers.Dropout( ... )(input)

 

이제 Dropout에 들어갈 수 있는 인자에 대해 알아보자.

__init__(
    rate,
    noise_shape=None,
    seed=None,
    **kwargs
)
  • rate : 드롭아웃을 적용할 확룰을 0~1 사이의 값으로 적는다. ex) dropout=0.2로 지정하면 전체 입력값 중에서 20%를 0으로 만든다.
  • noise_shape : 받는 값은 shape을 뜻하는데 여기서는 정수형의 1D-tensor 값을 받는다. 이 값을 지정하면 특정 값만 드롭아웃을 적용 가능하다. ex) 입력값이 이미지라면 noise_shape을 지정하면 특정 채널에만 드롭아웃을 적용할 수 있다.
  • seed : 드롭아웃 진행 시 지정된 확률값을 바탕으로 무작위로 드롭아웃이 적용 할 때, 임의의 선택을 위한 시드 값을 의미한다. seed 값은 정수형이며, 같은 seed를 넣으면 동일한 드롭아웃 결과가 나온다.

 

 

2.2.2 사용법

 

 아래와 같이 단순하게 적용할 부분을 입력값으로 넣어주면된다.

inputs = tf.keras.layers.Input(shape = (20, 1))
output = tf.keras.layers.Dropout(rate = 0.5)(inputs)

 

위의 Dense 예인 신경망에서 처음 input에 Dropout을 적용해 보면 아래와 같다.

inputs = tf.keras.layers.Input(shape = (20, 1))
dropout = tf.keras.layers.Dropout(rate = 0.2)(inputs)
hidden = tf.keras.layers.Dense(units = 10, activation = tf.nn.sigmoid)(dropout)
output = tf.keras.layers.Dense(units = 2, activation = tf.nn.sigmoid)(hidden)

 이러한 방식으로 적용하려는 츼의 노드에 넣어주기만 하면 된다. 이렇게 어느 layer든 넣어주어 과적합을 방지 할 수 있기 때문에 모델 구현 시 자주 사용된다.

 

 

 

 

 

2.3 tf.keras.layers.Conv1D

2.3.1 들어가기전

 

 들어가기 전에 기본적인 이미지에 적용하는 합성곱 방식인 Conv2D에 대한 것과 CNN에 대해 알고 싶다면 아래의 링크를 타고 들어가 보면, 대략적인 CNN 작동 원리를 알 수 있을 것이다. 여기서는 Conv1D에 대해 알아 볼 것이다.

han-py.tistory.com/230?category=942087

 

Convolutional Neural Network(CNN) _기초개념

0. CNN 특징 image classification에서 가장 많이 사용하고 있다. 일반적으로 convolution layer, pooling layer, fully-connected layer로 구성되어 있다. feature extraction 역할(특징을 뽑아낸다) - Convolut..

han-py.tistory.com

 

2.3.2 Conv1D, Conv2D, Conv3D

 Convolution(합성곱)의 연산의 일부로 tensorflow에서는 Conv1D, Conv2D, Conv3D가 사용된다. 그리고 Conv1D, Conv2D, Conv3D 이렇게 나눠지는 기준은 바로 합성곱이 진행되는 방향과 합성곱의 결과로 나오는 출력값이다. 

  합성곱의 방향 출력값
Conv1D 한 방향(가로) 1-D Array(vector)
Conv2D 두 방향(가로, 세로) 2-D Array(matrix)
Conv3D 세 방향(가로, 세로, 높이) 3-D Array(tensor)

사실 위 표의 출력값은 합성공의 출력 값과 동일하지 않다. 왜냐하면 배치 크기와 합성곱이 적용되는 필터의 개수를 고려하면 다르게 표현 될 것이다. 위의 경우는 배치를 고려하지 않고 합성곱 필터를 하나만 적용했을 떄라고 생각하면 된다.

 

자연어 처리 분야에서 사용하는 합성곱의 경우 각 단어 벡터의 차원 전체에 대해 필터를 적용시키기 위해 주로 conv1D를 사용한다.

 

 

2.3.3 구현

# 1. 객체 생성 이 후에 입력값 설정
conv1d = tf.keras.layers.Conv1D( ... )
output = conv1d(input)

# 2. 객체 생성 시 입력값 설정
output = tf.keras.layers.Conv1D( ... )(input)

 

 

설정 변경을 위해 객체에 들어갈  수 있는 인자는 다음와 같다.

  def __init__(self,
               filters,
               kernel_size,
               strides=1,
               padding='valid',
               data_format=None,
               dilation_rate=1,
               activation=None,
               use_bias=True,
               kernel_initializer='glorot_uniform',
               bias_initializer='zeros',
               kernel_regularizer=None,
               bias_regularizer=None,
               activity_regularizer=None,
               kernel_constraint=None,
               bias_constraint=None,
               **kwargs):

 위에서 배운 Dense와 비슷해보이지만, 합성곱 연산을 수행할 필터와 관련된 부분은 다르다. 즉, 합성곱에서는필터의 크기가 필요한데, Conv1D의 경우는 필터의 입력값의 차원 수와 높이가 동일하게 연산되기 때문에 가로 길이만 설정해 주면 된다. 쉽게 말하면 높이는 안적어도 되고 필터의 가로에 적용되는 kernel_size만 설정해 주면 된다.

 

  • filters : 필터의 개수로서, 정수형을 지정한다. 출력 차원의 수이다.
  • kerner_size : 필터의 크기로서, 정수 혹은 정수의 리스트, 튜플 형태로 지정한다. 합성곱이 적용되는 가로 길이를 나타낸다.
  • strides : 정수 혹은 정수의 리스트, 튜플 형태로 지정한다. 1이 아닌 값을 지정할 경우 dilation_rate는 1 이외의 값을 지정하지 못한다.
  • padding : 패딩 방법을 정한다. "VALID" 또는 "SAME"을 지정할 수 있다.
  • data_format : 데이터의 표현 방법을 선택하는 것이다. channel_last의 경우 (batch, length, channels) 형태여야하고 channel_first의 경우는 (batch, channels, length) 형태여야 한다.
  • dilation_rate : dilation 합성곱 사용 시 적용할 dilation 값으로서 정수 혹은 정수의 리스트, 튜플 형태로 지정한다. 1이 아닌 값을 지정하면 strides 값으로 1 이외의 값을 지정하지 못한다.
  • activation : 활성화 함수
  • use_bias : 편향(b)를 사용할지 여부를 나타내고 Boolean 값 형태다.
  • kernel_initializer : 가중치(W) 초기화 함수
  • bias_initializer : 편향 초기화 함수
  • kernel_regularizer : 가중치 정규화 방법
  • bias_regularizer : 편향 정규화 방법
  • activity_regularizer :출력 값 정규화 방법
  • kernel_constraint : Optimizer에 의해 업데이트 된 이후에 가중치에 적용되는 부가적인 제약 함수
  • bias_constraint : Optimizer에 의해 업데이트된 이후에 편향에 적용되는 부가적인 제약 함수

디테일한 이해를 하기 위해서는 위의 CNN 주소를 들어가서 읽어 보면좋다.

 

 

 

2.3.4 사용법

inputs = tf.keras.Input(shape = (1, 28, 28))
conv = tf.keras.layers.Conv1D(
		filters=10,
        kernel_size=3,
        padding='same',
        activation=tf.nn.relu)(input)

위의 코드에 Dropout을 적용해 보자.

inputs = tf.keras.Input(shape = (1, 28, 28))
dropout = tf.keras.layers.Dropout(rate=0.2)(input)
conv = tf.keras.layers.Conv1D(
		filters=10,
        kernel_size=3,
        padding='same',
        activation=tf.nn.relu)(input)

합성곱은 자주 사용하므로 알아두면 좋을 것이다. 그리고 conv2d와 conv3d도 비슷하기 때문에 텐서플로 공식문서에서 필요시 확인해 주면 된다.

 

 

 

2.4 tf.keras.layers.MaxPool1D

 합성곱 신경망 사용 시 풀링 기법도 많이 사용된다. Pooling이란 feature map의 크기를 줄이거나 주요한 특징을 뽑아내기 위해서 합성곱 신경망 이후에 적용되는 기법이다. 종류는 MaxPool1D, MaxPool2D, MaxPool3D으로 나눠진다.

 

풀링에는 두 가지 풀링 기법이 있다. 바로 맥스 풀링(max-pooling)과 평균 풀링(average-pooling)이다. 맥스풀링은 패처 맵에 대해 최대값만을 뽑아내는 방식이고, 평균 풀링은 피처 맵에 대해 전체 값들의 평균한 값을 뽑는 방식이다. 우리는 지금은 맥스 풀링 기법을 사용하여 MaxPool1D에 대해 알아보자.

 

2.4.1 구현

# 1. 객체 생성 이 후에 apply함수를 이용해 입력값 설정
max_pool = tf.keras.layers.MaxPool1D( ... )
max_pool.apply(input)

# 2. 객체 생성 시 입력값 설정
max_pool = tf.keras.layers.MaxPool1D( ... )(input)

 

2.4.2 인자

__init__(
    pool_size=2,
    strides=None,
    padding='valid',
    data_format=None,
    )
  • pool_size : 풀링을 적용할 필터의 크기를 뜻한다. 정수값을 가진다.
  • strides : 적용할 스트라이드의 값. 정수 혹은 None 값을 받는다
  • padding : 패팅 방법을 지정한다. "valid" 또는 "same"을 지정할 수 있다.
  • data_format: 데이터의 표현 방법을 선택한다. "channel_last" 혹은 "channel_first"를 지정할 수 있다. channel_last의 경우 데이터는 (batch, length, channels) 형태여야 하고, channel_first의 경우는 (batch, channels, length) 형태여야 한다.

 

2.4.3 적용

 이제 텐서플로 모듈을 사용하여 간한히 하나의 네트워크를 만들어 보자. 입력값이 합성곱과 맥스 풀링을 사용한 후 완전 연결 계층을 통해 최종 출력 값이 나오는 구조를 만들고 맥스 풀링을 하용하여 완전 연결 계층을 통해 최종 출력 값이 나오는 구조를 만들자. 입력값에는 dropout을 적용하고, 맥스풀링의 결과값을 별다른 인자값 없이도 사용할 수 있는 Flatten layers를 이용하여 행렬을 벡터로 바꿔준다.

 

inputs = tf.keras.Input(shape = (1, 28, 28))
dropout = tf.keras.layers.Dropout(rate=0.2)(input)
conv = tf.keras.layers.Conv1D(
		filters=10,
        kernel_size=3,
        padding='same',
        activation=tf.nn.relu)(input)
max_pool = tf.keras.layers.MaxPool1D(pool_size = 3, padding = 'same')(conv)
flatten = tf.keras.layers.Flatten()(max_pool)

 

 

 

 

3. 정리

 우리는 지금까지 layers에 대해 알아보았다. 그리고 이제 우리는 그 layer를 이용하여 모델을 만드는 방법에 대해 알아 볼 것이다. 다음 링크로 가보자.

han-py.tistory.com/270

 

 

반응형