이번 포스팅에서는 PyTorch 에서 인덱싱(indexing)과 슬라이싱(slicing)을 이용해서 텐서 내 원하는 위치의 원소 부분집합을 가져오는 방법을 소개하겠습니다. PyTorch 로 딥러닝을 할 때 인풋으로 사용하는 데이테셋이 다차원의 행렬인 텐서인데요, 인덱싱과 슬라이싱을 자주 사용하기도 하고, 또 차원이 많아질 수록 헷갈리기도 하므로 정확하게 익혀놓을 필요가 있습니다. NumPy의 인덱싱, 슬라이싱을 이미 알고 있으면 그리 어렵지 않습니다. 

 

(1) 파이토치 텐서 인덱싱 (indexing of PyTorch tensor) 

(2) 파이토치 텐서 슬라이싱 (slicing of PyTorch tensor)

(3) 1개 값만 가지는 파이토치 텐서에서 숫자 가져오기 : tensor.item() 

(4) 파이토치 텐서 재구조화 (reshape)

 

 

PyTorch tensor indexing

 

 

(1) 파이토치 텐서 인덱싱 (indexing of PyTorch tensor)

 

먼저, 예제로 사용할 PyTorch tensor를 NumPy ndarray를 변환해서 만들어보겠습니다.

torch.Size([3, 5]) 의 형태를 가진 텐서를 만들었습니다. 

 

import torch
import numpy as np

## -- creating a tensor object
x = torch.tensor(
    np.arange(15).reshape(3, 5))

print(x)
# tensor([[ 0,  1,  2,  3,  4],
#         [ 5,  6,  7,  8,  9],
#         [10, 11, 12, 13, 14]])


## -- shape, size of a tensor

x.shape
# torch.Size([3, 5])

x.size(0)
# 3

x.size(1)
# 5

 

 

다양한 인덱싱 시나리오별로 예를 들어서 설명을 해보겠습니다. 

 

 

(1-1) 1번 행 전체를 인덱싱 해오기 

 

## indexing using position number
x[1]  # or equivalently x[1, :]
# tensor([5, 6, 7, 8, 9])

 

 

(1-2) 1번 행, 2번 열 원소 인덱싱 해오기

 

x[1, 2]
# tensor(7)

 

 

(1-3) 1번 열 전체를 인덱싱 해오기

 

x[:, 1]
# tensor([ 1,  6, 11])

 

 

(1-4) 1번 열, 블리언(Boolean) True 인 행만 인덱싱 해오기

 

## indexing using Boolean
x[1][[True, False, False, False, True]]
# tensor([5, 9])

 

 

(1-5) 1번 열, 텐서(tensor)의 값의 행만 인덱싱 해오기

 

## indexing using a tensor
x[1][torch.tensor([1, 3])]
# tensor([6,8])

 

 

(1-6) 1번 열을 가져오되, 행은 리스트의 위치 값 순서대로 바꾸어서 가져오기

 

## changing the position using indexing
x[1, [4,3,0,1,2]]
# tensor([9, 8, 5, 6, 7])

 

 

(1-7) 행 별로 열의 위치를 달리해서 값 가져오기

(예) 0번 행의 4번 열, 1번 행은 3번 열, 2번 행은 2번 열의 값 가져오기

 

## 행별로 인덱싱할 위치를 바뀌가면서 인덱싱하기
x[torch.arange(x.size(0)), [4,3,2]]
# tensor([ 4,  8, 12])

 

 

(1-8) 전체 행의 마지막 열(-1) 값 가져오기

 

## -1 : last elements
x[:, -1]
# tensor([ 4,  9, 14])

 

 

(1-9) 인덱싱한 위치에 특정 값을 재할당 하기

(예) 1번 행에 값 '0'을 재할당하기

 

## asinging new value using indexing
x[1] = 0


print(x)
# tensor([[ 0,  1,  2,  3,  4],
#         [ 0,  0,  0,  0,  0],   <----- '0' 으로 재할당 됨
#         [10, 11, 12, 13, 14]])

 

 

(2) 파이토치 텐서 슬라이싱 (slicing of PyTorch tensor)

 

 

(2-1) 1번 행 이후의 행의 모든 값 가져오기

 

x = torch.tensor(
    np.arange(15).reshape(3, 5))

print(x)
# tensor([[ 0,  1,  2,  3,  4],
#         [ 5,  6,  7,  8,  9],
#         [10, 11, 12, 13, 14]])


## -- slicing
x[1:]
# tensor([[ 5,  6,  7,  8,  9],
#         [10, 11, 12, 13, 14]])

 

 

(2-2) 1번 행 이후의 행 & 3번 열 이후의 열의 모든 값 가져오기

 

x[1:, 3:]
# tensor([[ 8,  9],
#         [13, 14]])

 

 

(2-3) 전체 행, 1번 열의 값 가져오기

 

x[:, 1]
# tensor([ 1,  6, 11])

 

 

(2-4) 1번 행, 전체 열의 값 가져오기

 

x[1, :]  # or equivalently x[1]
# tensor([5, 6, 7, 8, 9])

 

 

(2-5) 1번 행의, 1번과 4번 행의 값 가져오기

(생소한 코드예요. ^^;)

 

## tensor[1::3] ==> (1, None, None, 4)
x[1][1::3]
# tensor([6, 9])

 

 

 

(3) 1개 값만 가지는 파이토치 텐서에서 숫자 가져오기 : tensor.item()

 

## torch.tensor.item()
## : get a Python number from a tensor containing a single vlaue
y = torch.tensor([[5]])
print(y)
# tensor([[5]])

y.item()
# 5

 

 

만약 PyTorch tensor가 1개의 값(즉, 스칼라) 만을 가지는 것이 아니라 여러개의 값을 가지는 경우, tensor.item() 메소드를 사용하면 ValueError: only one element tensors can be converted to Python scalars 가 발생합니다. 

 

## ValueError
x.item()

# ValueError Traceback (most recent call last)
# <ipython-input-74-3396a1b2b617> in <module>
# ----> 1 x.item()

# ValueError: only one element tensors can be converted to Python scalars

 

 

 

(4) 파이토치 텐서 재구조화 (reshape)

 

NumPy의 reshape() 메소드와 동일하게 PyTorch tensor 도 reshape() 메소드를 이용해서 형태(shape)를 재구조화할 수 있습니다. 

 

torch.tensor([[0, 1, 2, 3, 4, 5]])
# tensor([[0, 1, 2, 3, 4, 5]])


## -- reshape
torch.tensor([[0, 1, 2, 3, 4, 5]]).reshape(2, 3)
# tensor([[0, 1, 2],
#         [3, 4, 5]])

 

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 PyTorch tensor 와 NumPy ndarrays 의 행렬 곱셈(matrix multiplication) 성능을 비교해보겠습니다. GPU 는 Google Colab 을 사용해서 성능을 테스트했습니다. 

 

(1) PyTorch tensor & GPU 로 행렬 곱셈 (matrix multiplication) 

(2) PyTorch tensor & CPU 로 행렬 곱셈

(3) NumPy ndarrays & CPU 로 행렬 곱셈

 

 

PyTorch tensors & GPU vs. PyTorch tensors & CPU vs. NumPy ndarrays & CPU

 

 

 

m * n 행렬 A 와 n * p 행렬 B 가 있다고 했을 때, 행렬 곱셈(matrix multiplication) C = AB 는 아래와 같이 정의할 수 있습니다.  행렬 곱셈 연산은 A 의 i번째 행과 B의 j번째 열의 성분들을 각각 곱한 후 더한 것이며, 서로 독립적으로 병렬 연산 (calculation in parallel) 이 가능합니다. GPU 는 수 천 개의 cores 를 가지고 있으므로 단지 수 개의 cores를 가지는 CPU 보다 병렬로 행렬 곱셈을 매우 빠르게 수행할 수 있습니다. 

 

행렬 곱셈 (matrix multiplication)

 

 

 

(1) PyTorch tensor & GPU 로 행렬 곱셈 (matrix multiplication)

 

PyTorch를 불러오고, torch.manual_seed() 로 초기값을 설정해서 매번 동일한 난수가 발생하게 설정을 해준 다음, torch.rand() 함수로 난수를 생성해서 torch 객체를 만들어보겠습니다. 

 

import torch
print(torch.__version__)
#1.13.1+cu116

## generate the torch objects with random numbers
torch.manual_seed(1004)
x = torch.rand(1, 25600)
y = torch.rand(25600, 100)

 

 

다음으로, torch tensor 객체를 저장할 디바이스를 정의하겠습니다. 아래 코드는 GPU 를 사용할 수 있으면 (torch.cuda.is_available() == True) 'cuda' 로 디바이스를 정의하고, 그렇지 않으면 'cpu'로 디바이스를 정의합니다. 

 

## define the device
device = 'cuda' if torch.cuda.is_available() else 'cpu'

 

 

이제 x, y의 두 개 tensor 객체를 위에서 정의한 디바이스에 등록(register)해서 정보를 저장하겠습니다. 

 

## register and save the tensor objects with the device
x, y = x.to(device), y.to(device)

 

 

마지막으로, PyTorch tensor 객체인 행렬 x와 y 의 행렬 곱셉(matrix multiplication, z = (x@y))을 GPU 를 사용해서 해보겠습니다. 이때 실행 성능을 확인하기 위해 %timeit 으로 실행 시간을 측정해보겠습니다. 

 

행렬 곱셉에 25.4 µs ± 26.9 µs per loop 의 시간이 걸렸네요.  

 

## (1) run matrix multiplication of the Torch objects on GPU
%timeit z = (x@y)

# The slowest run took 6.94 times longer than the fastest. 
# This could mean that an intermediate result is being cached.
# 25.4 µs ± 26.9 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

 

 

 

(2) PyTorch tensor & CPU 로 행렬 곱셈 (matrix multiplication)

 

이번에는 PyTorch tensor 에 대해 CPU 를 사용(x.cpu(), y.cpu())해서 행렬 곱셉을 해보겠습니다. 

PyTorch tensor에 대해 CPU 로는 932 µs ± 292 µs per loop 의 시간이 소요되었으며, 이는 위의 PyTorch tensor & GPU 대비 약 37배 더 시간이 소요되었습니다. 

 

## (2) run matrix multiplication of the same tensors on CPU
x, y = x.cpu(), y.cpu()

%timeit z = (x@y)

# 932 µs ± 292 µs per loop 
# (mean ± std. dev. of 7 runs, 1000 loops each)

 

 

 

(3) NumPy ndarrays & CPU 로 행렬 곱셈

 

마지막으로 NumPy의 ndarrays 로 위의 PyTorch로 했던 행렬 곱셉을 똑같이 실행해서, 소요시간을 측정(%timeit)해 보겠습니다.

 

NumPy의 ndarrays 로 행렬 곱셉은 1.17 ms ± 46.4 µs per loop 이 걸려서, 위의 PyTorch tensor & GPU 는 NumPy ndarrays 보다 46배 빠르고, 위의 PyTorch tensor & CPU 는 NumPy ndarrays 보다 1.25 배 빠르걸로 나왔습니다

역시 GPU 가 행렬 곱셉 성능에 지대한 영향을 끼치고 있음을 확인할 수 있습니다! 

 

## (3) run matrix multiplication on NumPy arrays
import numpy as np

x = np.random.random((1, 25600))
y = np.random.random((25600, 100))

%timeit z = np.matmul(x, y)

# 1.17 ms ± 46.4 µs per loop 
# (mean ± std. dev. of 7 runs, 1000 loops each)

 

 

PyTorch tensor & GPU 의 강력한 성능을 이용해서 멋진 딥러닝 모델 학습하세요. 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 PyTorch 모듈을 사용해서 난수를 생성하여 텐서 객체를 만드는 여러가지 방법을 소개하겠습니다. (numpy 유사하네요)

 

 

1. 난수를 생성해서 PyTorch tensor를 만들기

  (1-1) torch.rand(size) : 0과 1 사이의 실수[0, 1) 로 난수를 생성해서 텐서 만들기

  (1-2) torch.randn(size) : 표준정규분포 X~N(0, 1)로 부터 난수를 생성해서 텐서 만들기

  (1-3) torch.randint(low, high, size) : low~high 사이의 정수로 난수를 생성해서 텐서 만들기

  (1-4) torch.randperm(the upper bound, n) : 0~n 사이의 정수를 무작위로 섞어서 텐서 만들기 

 

2. 인풋과 동일한 형태(same shape as input tensor)로 난수를 생성해서 PyTorch tensor 만들기

  (2-1) torch.rand_like(input) : 인풋과 동일한 형태(shape)로 0~1 사이의 실수로 난수를 생성해서 텐서 만들기

  (2-2) torch.randn_like(input) : 인풋과 동일한 형태로 표준정규분포 X~N(0,1)에서 난수를 생성해서 텐서 만들기

  (2-3) torch.randint_like(input, low, high) : 인풋과 동일한 형태로 low~high 사이의 정수로 난수를 생성해서 텐서 만들기

 

 

 

 

1. 난수를 생성해서 PyTorch tensor를 만들기

 

  (1-1) torch.rand(size) : 0과 1 사이의 실수[0, 1) 로 난수를 생성해서 텐서 만들기

 

이때 0은 포함되고 1은 포함되지 않습니다. 난수를 생성하는 것이기 때문에 실행할 때마다 매번 텐서 안의 원소 값이 달라집니다. 

 

import torch

## generating a tensor object with random numbers b/w 0 and 1
torch.rand(2, 4)

# tensor([[0.6653, 0.6714, 0.4876, 0.2055],
#         [0.9733, 0.5680, 0.9754, 0.1981]])

 

 

만약, 난수 생성 값을 매번 동일하게 나오게 하고 싶다면 torch.manual_seed() 메소드로 난수 초기값을 설정해주면 됩니다. (아래 코드를 실행하면 저와 동일한 난수 값으로 구성된 텐서를 반환할 것입니다.)

 

## setting a seed number for reproducibility
torch.manual_seed(1004) 
torch.rand(2, 4)

# tensor([[0.9716, 0.3893, 0.2629, 0.9071],
#         [0.1041, 0.0360, 0.1655, 0.7124]])

 

 

 

(1-2) torch.randn(size) : 표준정규분포 X~N(0, 1)로 부터 난수를 생성해서 텐서 만들기

 

평균이 0, 표준편차가 1인 표준정규분포 X~N(0, 1) 로 부터 실수 난수를 생성해서 텐서를 만들어줍니다. 

 

# generating a tensor from a standard normal distribution, X~N(0, 1)
torch.randn(2, 4)

# tensor([[ 1.0868, -1.5346, -0.4525,  0.3689],
#         [-0.9079, -0.2578, -0.3581,  0.4072]])

 

 

 

(1-3) torch.randint(low, high, size) : low~high 사이의 정수로 난수를 생성해서 텐서 만들기

 

이때 low 값은 포함되고, high 값은 포함되지 않습니다. 

 

## generating a tensor with random integers
## (including the low value, but not including the high value)
torch.randint(low=0, high=10, size=(2, 4))

# tensor([[9, 2, 7, 8],
#         [5, 3, 0, 8]])

 

 

 

(1-4) torch.randperm(the upper bound, n) : 0~n 사이의 정수를 무작위로 섞어서 텐서 만들기

 

아래의 예처럼 upper bound 'n' 이 '10' 이면 0~9 까지의 정수 (10은 미포함) 를 모두 사용해서 무작위로 섞어서 텐서를 만들어줍니다. 

 

## returns a random permutation of integers from 0 to n
torch.randperm(10)

# tensor([5, 3, 2, 7, 6, 9, 4, 1, 8, 0])

 

 

 

 

2. 인풋과 동일한 형태(same shape as input tensor)로 난수를 생성해서 PyTorch tensor 만들기

 

(2-1) torch.rand_like(input)

           : 인풋과 동일한 형태(shape)로 0~1 사이의 실수로 난수를 생성해서 텐서 만들기

 

예제로 numpy ndarray 로 (2, 3) 형태의 PyTorch tensor 를 만들어보았습니다. 

 

## creating a tensor object with numpy array
import numpy as np

y = np.array([[1., 2., 3.], [4., 5., 6.]])
z = torch.tensor(y)

print(z)
# tensor([[1., 2., 3.],
#         [4., 5., 6.]], dtype=torch.float64)


z.shape
# torch.Size([2, 3])

 

 

torch.rand() 가 0~1 사이의 실수에서 난수를 생성해서 텐서를 만들었는데요, torch.rand_like(input) 은 인풋과 같은 형태(shape)로 0~1 사이의 실수에서 난수를 생성해서 텐서를 만들어줍니다. 

 

## Returns a tensor with the same size as input 
## that is filled with random numbers 
## from a uniform distribution on the interval [0,1)
torch.rand_like(z)

# tensor([[0.6764, 0.6955, 0.1822],
#         [0.4265, 0.8873, 0.2876]], dtype=torch.float64)

 

 

 

(2-2) torch.randn_like(input)
           : 인풋과 동일한 형태로 표준정규분포 X~N(0,1)에서 난수를 생성해서 텐서 만들기

 

## Returns a tensor with the same size as input 
## that is filled with random numbers from 
## a normal distribution with mean 0 and variance 1.
torch.randn_like(z)

# tensor([[-1.2964, -0.0624,  1.2123],
#         [ 2.2158,  0.2930, -0.2537]], dtype=torch.float64)

 

 

 

(2-3) torch.randint_like(input, low, high)

           : 인풋과 동일한 형태로 low~high 사이의 정수로 난수를 생성해서 텐서 만들기

 

## Returns a tensor with the same shape as Tensor input 
## filled with random integers generated uniformly 
## between low (inclusive) and high (exclusive)
torch.randint_like(input=z, low=0, high=10)

# tensor([[7., 6., 8.],
#         [2., 9., 1.]], dtype=torch.float64)

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 PyTorch 의 자료구조인 tensor가 무엇이고, tensor 객체를 만드는 방법(how to create a PyTorch tensor objects)을 소개하겠습니다. 

 

(1) 텐서(tensor)는 무엇인가? 

(2) PyTorch 텐서 만들고 속성정보 조회하기

(3) 0(zeros), 1(ones)로 채워진 텐서, 빈 텐서(empty tensor) 만들기

 

 

(1) 텐서(tensor)는 무엇인가? 

 

텐서(tensor) 는 PyTorch의 가장 기본적인 데이터 유형으로서, NumPy의 다차원 배열인 ndarray 와 유사합니다. 

스칼라(Scalar)는 0 차원의 텐서, 벡터(Vector)는 1 차원의 텐서, 행렬(Matrix)은 2 차원의 텐서, 그리고 3차원 이상의 다차원 행렬은 다차원 텐서입니다. PyTorch의 텐서는 스칼라, 벡터, 행렬 및 다차원 텐서를 모두 아우르는 일반화된 데이터 구조를 말합니다. 

 

PyTorch tensor objects: scalar, vector, matrix, tensor

 

PyTorch 로 GPU를 사용해서 다차원 행렬을 가지고 병렬처리를 하려면 텐서 객체로 데이터를 변환해야 합니다. 

텐서 내의 데이터 원소는 모두 같은 데이터 유형이어야 합니다. (가령, 모두 float 이거나, int 이거나 동일해야 함.)

 

 

 

(2) PyTorch 텐서 만들고 속성정보 조회하기

 

(2-1) 리스트(List)에 대해 torch.tensor(a list) 로 텐서 만들기

 

import torch

## creating a tensor object with a list of lists
x = torch.tensor([[1., 2., 3.]])

print(x)
# tensor([[1., 2., 3.]])

 

 

(2-2) NumPy의 다차원 array 를 torch.tensor(np.array) 로 텐서로 변환하기

 

## creating a tensor object with numpy array
import numpy as np

y = np.array([[1., 2., 3.], [4., 5., 6.]])
z = torch.tensor(y)

print(z)
# tensor([[1., 2., 3.],
#         [4., 5., 6.]], dtype=torch.float64)

 

 

(2-3) 텐서의 형태(shape)와 데이터 유형(dtype) 속성정보 조회하기

 

## accessing the Shape and DataType of a tensor

print(x.shape)
# torch.Size([1, 3])

print(x.dtype)
# torch.float32

 

 

 

(3) 0(zeros), 1(ones)로 채워진 텐서, 빈 텐서(empty tensor) 만들기

 

(3-1) 0 으로 채워진 텐서 만들기 : torch.zeros(size)

 

## generating a tensor object with zeros
torch.zeros((2, 4))

# tensor([[0., 0., 0., 0.],
#         [0., 0., 0., 0.]])

 

 

(3-2) 1 로 채워진 텐서 만들기 : torch.ones(size)

 

## generating a tensor object with ones
torch.ones((2, 4))

# tensor([[1., 1., 1., 1.],
#         [1., 1., 1., 1.]])

 

 

(3-3) 빈 텐서 만들기 : torch.empty(size)

 

## generating a tensor filled with uninitialized data.
torch.empty((2, 4))

# tensor([[0., 0., 0., 0.],
#         [0., 0., 0., 0.]])

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python을 사용해서 

 

(1) 텍스트 데이터 전처리 (text data pre-processing)

(2) 토큰화 (tokenization)

 

하는 방법을 소개하겠습니다. 

 

 

(1) 텍스트 데이터 전처리 (text data pre-processing)

 

텍스트 데이터 전처리를 하는데는 (a) Python의 텍스트 처리 내장 메소드 (Python built-in methods)와 (b) 정규 표현식 매칭 연산(regular expression matching operations)을 제공하는 Python re 패키지를 사용하겠습니다. re 패키지는 Python을 설치할 때 디폴트로 같이 설치가 되므로 별도로 설치할 필요는 없습니다. 

 

예제로 사용할 Input 텍스트는 인터넷쇼핑몰의 고객별 거래내역에 있는 구매 품목 텍스트 데이터이며, Output 은 텍스트 전처리 후의 고객별 구매 품목의 리스트입니다. 

 

예) Input: '**[세일]** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건'

예) Output: [말티즈, 강아지사료, 습식, 소프트]

 

[ 텍스트 데이터 전처리 절차 ]

    (1-1) [], (), {}, <> 괄호와 괄호 안 문자 제거하기

    (1-2) '...외', '...총' 제거하기

    (1-3) 특수문자, 숫자 제거

    (1-4) 단위 제거: cm, km, etc.

    (1-5) 공백 기준으로 분할하기

    (1-6) 글자 1개만 있으면 제외하기

    (1-7) 텍스트 데이터 전처리 사용자 정의함수(User Defined Function) 정의 

    (1-8) pandas DataFrame의 텍스트 칼럼에 데이터 전처리 사용자 정의함수 적용

 

 

(1-1) [], (), {}, <> 괄호와 괄호 안 문자 제거하기

 

Python의 정규 표현식(regular expression)을 다루는 re 패키지를 사용해서 다양한 형태의 괄호와 괄호안의 문자를 매칭한 후에 '' 로 대체함으로써 결과적으로 제거하였습니다. re.sub() 는 pattern 과 매치되는 문자열을 repl 의 문자열로 대체를 시켜줍니다. 

 

정규표현식에서 문자 클래스를 만드는 메타 문자인 [ ] 로 만들어지는 정규표현식은 [ ]사이에 들어가는 문자 중 어느 한개라도 매치가 되면 매치를 시켜줍니다. 가령, [abc] 의 경우 'a', 'b', 'c' 중에서 어느 하나의 문자라도 매치가 되면 매치가 되는 것으로 간주합니다. 

 

## Python Regular expression operations
import re

## sample text
s = '**[세일]** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건'


## (1-1) [], (), {}, <> 괄호와 괄호 안 문자 제거하기
pattern = r'\([^)]*\)'  # ()
s = re.sub(pattern=pattern, repl='', string=s)

pattern = r'\[[^)]*\]'  # []
s = re.sub(pattern=pattern, repl='', string=s)

pattern = r'\<[^)]*\>'  # <>
s = re.sub(pattern=pattern, repl='', string=s)

pattern = r'\{[^)]*\}'  # {}
s = re.sub(pattern=pattern, repl='', string=s)

print(s)
[Out] 
# **** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건

 

 

 

(1-2) '...외', '...총' 제거하기

 

Python의 내장 문자열 메소드인 replace() 를 사용해서 '...외', '...총' 을 ' ' 로 대체함으로써 제거하였습니다. 

 

## (1-2) '...외', '...총' 제거하기
s = s.replace('...외', ' ')
s = s.replace('...총', ' ')

print(s)
[Out]
# **** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!! 5건

 

 

 

(1-3) 특수문자, 숫자 제거

 

정규표현식에서 하이픈(-)은 from ~ to 의 범위를 나타냅니다. [a-zA-Z] 는 소문자와 대문자 영어 모두를 의미하며, [가-힣] 은 한글 전체를 의미합니다. 

 

정규표현식에서 [^] 는 not 의 의미이며, 아래의 [^a-zA-Z가-힣] 은 앞에 '^' 가 붙었으므로 영어와 한글이 아닌(not, ^) 문자, 즉 특수문자와 숫자와 매칭이 됩니다. 

 

## (1-3) 특수문자, 숫자 제거
pattern = r'[^a-zA-Z가-힣]'
s = re.sub(pattern=pattern, repl=' ', string=s)

print(s)
[Out] 
# 말티즈 강아지사료 습식 소프트 신  종   Kg       원    건

 

 

 

(1-4) 단위 제거: cm, km, etc.

 

## (1-4) 단위 제거: cm, km, etc.
units = ['mm', 'cm', 'km', 'ml', 'kg', 'g']
for unit in units:
    s = s.lower() # 대문자를 소문자로 변환
    s = s.replace(unit, '')
    
print(s)
[Out] 
# 말티즈 강아지사료 습식 소프트 신  종          원    건

 

 

 

(1-5) 공백 기준으로 분할하기

 

Python 내장형 문자열 메소드인 split() 을 사용해서 공백(space)을 기준으로 문자열을 분할하였습니다. 

 

## (1-5) 공백 기준으로 분할하기
s_split = s.split()

print(s_split)
[Out] 
# ['말티즈', '강아지사료', '습식', '소프트', '신', '종', '원', '건']

 

 

 

(1-6) 글자 1개만 있으면 제외하기

 

글자 길이가 1 보다 큰 (len(word) != 1) 글자만 s_list 의 리스트에 계속 추가(append) 하였습니다. 

 

## (1-6) 글자 1개만 있으면 제외하기
s_list = []
for word in s_split:
    if len(word) !=1:
        s_list.append(word)
        
print(s_list)
[Out] 
# ['말티즈', '강아지사료', '습식', '소프트']

 

 

 

(1-7) 텍스트 데이터 전처리 사용자 정의함수(User Defined Function) 정의 

 

위의 (1-1) ~ (1-6) 까지의 텍스트 전처리 과정을 아래에 사용자 정의함수로 정의하였습니다. 문자열 s 를 input으로 받아서 텍스트 전처리 후에 s_list 의 단어들을 분할해서 모아놓은 리스트를 반환합니다. 

 

## 텍스트 전처리 사용자 정의함수(UDF of text pre-processing)
def text_preprocessor(s):
    import re
    
    ## (1) [], (), {}, <> 괄호와 괄호 안 문자 제거하기
    pattern = r'\([^)]*\)'  # ()
    s = re.sub(pattern=pattern, repl='', string=s)
    
    pattern = r'\[[^)]*\]'  # []
    s = re.sub(pattern=pattern, repl='', string=s)
    
    pattern = r'\<[^)]*\>'  # <>
    s = re.sub(pattern=pattern, repl='', string=s)
    
    pattern = r'\{[^)]*\}'  # {}
    s = re.sub(pattern=pattern, repl='', string=s)
    
    ## (2) '...외', '...총' 제거하기
    s = s.replace('...외', ' ')
    s = s.replace('...총', ' ')
    
    ## (3) 특수문자 제거
    pattern = r'[^a-zA-Z가-힣]'
    s = re.sub(pattern=pattern, repl=' ', string=s)
    
    ## (4) 단위 제거: cm, km, etc.
    units = ['mm', 'cm', 'km', 'ml', 'kg', 'g']
    for unit in units:
        s = s.lower() # 대문자를 소문자로 변환
        s = s.replace(unit, '')
        
    # (5) 공백 기준으로 분할하기
    s_split = s.split()
    
    # (6) 글자 1개만 있으면 제외하기
    s_list = []
    for word in s_split:
        if len(word) !=1:
            s_list.append(word)
            
    return s_list
    

## sample text
s = '**[세일]** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건'

## apply the UDF above
s_list = text_preprocessor(s)
print(s_list)
[Out] 
# ['말티즈', '강아지사료', '습식', '소프트']

 

 

 

(1-8) pandas DataFrame의 텍스트 칼럼에 데이터 전처리 사용자정의함수 적용

 

pandas DataFrame에 위의 (1-7) 텍스트 전처리 사용자 정의함수를 적용하기 위해서는 apply() 와 lambda function 을 사용합니다. 

 

## pandas DataFrame
import pandas as pd

s1 = '**[세일] 몰티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건'
s2 = '[시크루즈] 50%+추가20%/여름신상 루즈핏 롱원피스/상하세트/점프슈트...외3건'
s3 = '올챌린지 KF94 마스크 100매 국내생산 여름용 황사 화이트...총2건'
s4 = '[최대혜택가] ##하림 용가리치킨 300gX3봉 외 닭가슴살/튀김 골라담기...외12건'
s5 = '[20%+15%] 종아리알 타파! 무로 요가링/마사지릴/압박스타킹/마사지볼...외4종'

df = pd.DataFrame({
    'id': [1, 2, 3, 4, 5], 
    'items': [s1, s2, s3, s4, s5]
})

print(df)
[Out]
#    id                                              items
# 0   1  **[세일] 몰티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건
# 1   2     [시크루즈] 50%+추가20%/여름신상 루즈핏 롱원피스/상하세트/점프슈트...외3건
# 2   3           올챌린지 KF94 마스크 100매 국내생산 여름용 황사 화이트...총2건
# 3   4   [최대혜택가] ##하림 용가리치킨 300gX3봉 외 닭가슴살/튀김 골라담기...외12건
# 4   5    [20%+15%] 종아리알 타파! 무로 요가링/마사지릴/압박스타킹/마사지볼...외4종


## Apply the text preprocessing UDF using apply() and lambda function
df['items_list'] = df['items'].apply(lambda s: text_preprocessor(s))


print(df['items'])
print('-------------'*5)
print(df['items_list'])
[Out]
# 0    **[세일] 몰티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건
# 1       [시크루즈] 50%+추가20%/여름신상 루즈핏 롱원피스/상하세트/점프슈트...외3건
# 2             올챌린지 KF94 마스크 100매 국내생산 여름용 황사 화이트...총2건
# 3     [최대혜택가] ##하림 용가리치킨 300gX3봉 외 닭가슴살/튀김 골라담기...외12건
# 4      [20%+15%] 종아리알 타파! 무로 요가링/마사지릴/압박스타킹/마사지볼...외4종
# Name: items, dtype: object
# -----------------------------------------------------------------
# 0                     [몰티즈, 강아지사료, 습식, 소프트]
# 1         [추가, 여름신상, 루즈핏, 롱원피스, 상하세트, 점프슈트]
# 2       [올챌린지, kf, 마스크, 국내생산, 여름용, 황사, 화이트]
# 3               [하림, 용가리치킨, 닭가슴살, 튀김, 골라담기]
# 4    [종아리알, 타파, 무로, 요가링, 마사지릴, 압박스타킹, 마사지볼]
# Name: items_list, dtype: object

 

 

 

위에 Jupyter Notebook 에서 pandas DataFrame을 출력한 결과가 중앙 정렬로 되어있어서 보기가 불편한데요, 아래처럼 좌측 정렬 (left alignment) 을 해서 보기에 편하도록 해보았습니다. 

 

## align text of pandas DataFrame to left in Jupyter Notebook
dfStyler = df.style.set_properties(**{'text-align': 'left'})
dfStyler.set_table_styles([dict(selector='th', props=[('text-align', 'left')])])

text preprocessing using regular expressions

 

 

 

(2) 토큰화 (tokenization)

 

토큰화(Tokenization)는 말뭉치(Corpus)를 토큰이라고 불리는 단어 또는 문장으로 나누는 것을 말합니다. 이러한 토큰은 문맥(Context)을 이해하거나 NLP에 대한 모델을 개발하는 데 사용됩니다. 

 

POS 태킹 (Part-of-Speech Tagging) 은 널리 사용되는 자연어 처리 프로세스로, 단어의 정의와 문맥에 따라 언어의 특정 부분에 대응하여 텍스트(corpus)의 단어를 분류하는 것을 말합니다.

 

아래 코드는 위 (1)번의 텍스트 전처리에 이어서, 띄어쓰기가 제대로 되지 않아서 붙어 있는 단어들을, Python KoNLpy 패키지를 사용해서 형태소 분석의 명사를 기준으로 단어 토근화를 한 것입니다. ((2)번 words_tokonizer() UDF 안에 (1)번 text_preprocessor() UDF가 포함되어 있으며, 순차적으로 수행됩니다.)

 

KoNLpy 패키지는 Python으로 한국어 자연어 처리(NLP) 을 할 수 있게 해주는 패키지입니다. 그리고 Kkma 는 서울대학교의 IDS 랩에서 JAVA로 개발한 형태소 분석기(morphological analyzer)입니다.  

 

## insatll konlpy if it is not istalled yet
# ! pip install konlpy


## KoNLpy : NLP of the Korean language
## reference ==> https://konlpy.org/en/latest/
## Kkma is a morphological analyzer 
## and natural language processing system written in Java, 
## developed by the Intelligent Data Systems (IDS) Laboratory at SNU.
from konlpy.tag import Kkma


## define words tokenizer UDF
def words_tokonizer(text):
    from konlpy.tag import Kkma # NLP of the Korean language
    kkma = Kkma()
    
    words = []
    
    # Text preprocessing using the UDF above
    s_list = text_preprocessor(text)
    
    # POS tagging
    for s in s_list:
        words_ = kkma.pos(s)   
        
        # NNG indexing
        for word in words_:
            if word[1] == 'NNG':
                words.append(word[0])
            
    return words
    
    
## apply the UDF above as an example
words_tokonizer('강아지사료')
[Out] ['강아지', '사료']


words_tokonizer('상하세트')
[Out] ['상하', '세트']

 

 

위의 (2) words_tokenizer() UDF를 pandas DataFrame에 적용하기 위해서 apply() 함수와 lambda function 을 사용하면 됩니다. 

 

## apply the text tokenization UDF to pandas DataFrame using apply() and lambda function
df['items'].apply(lambda text: words_tokonizer(text))

[Out]
# 0 [몰티즈, 강아지, 사료, 습식, 소프트]
# 1 [추가, 여름, 신상, 루즈, 핏, 원피스, 상하, 세트, 점프, 슈트]
# 2 [챌린지, 마스크, 국내, 생산, 여름, 황사, 화이트]
# 3 [하림, 용가리, 치킨, 닭, 가슴살, 튀김]
# 4 [종아리, 타파, 무로, 요가, 링, 마사지, 압박, 스타, 킹, 마사지]
# Name: items, dtype: object

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 텍스트를 컴퓨터가 이해할 수 있도록 재표현해주는 text representation 방법 중에서 vectorization approaches 의 하나로서 TF-IDF (Term Frequency - Inverse Document Frequency) 의 개념, 수식에 대해서 알아보고, 간단한 예제 텍스트를 사용해서 설명을 해보겠습니다. 그리고 Python 의 Scikit-Learn 모듈을 사용해서 분석을 해보겠습니다. 

 

(1) TF-IDF (Term Frequency - Inverse Document Frequency) 개념 및 예시

(2) Python scikit-learn 모듈을 사용한 실습

 

 

(1) TF-IDF (Term Frequency - Inverse Document Frequency) 개념 및 예시

 

vectorization apporached 의 text representation 방법으로는

 - One-Hot Encoding

 - Bag of Words (BoW)

 - Bag of N-Grams (BoN)

 - Term Frequency - Inverse Document Frequency (TF-IDF)

등이 있습니다.  

 

이중에서 One-Hot Encoding, Bag of Words (BoW), Bag of N-Grams (BoN) 의 방법은 텍스트 안의 모든 단어를 동일하게 중요하다고 간주합니다. 반면에, TF-IDF 는 문서와 말뭉치에서 어떤 단어가 주어졌을 때 다른 단어 대비 상대적인 중요도를 측정한다는 차이가 있습니다. 

 

만약 어떤 단어 w 가 문서 Di 에서 자주 나타나지만, 다른 문서 Dj 에서는 별로 나타나지 않을 때, 단어 w 는 문서 Di 에서 매우 중요하다고 볼 수 있습니다.

 

- TF의 핵심 개념: 단어 w의 중요도는 문서 d(i) 에서 출현하는 빈도에 비례해서 증가.

- IDF의 핵심 개념: 반면에, 단어 w가 말뭉치의 중요도는 다른 문서 d(j) 에서의 출현 빈도에는 비례해서 감소. 

 

TF-IDF 점수는 TF 점수와 IDF 점수를 곱해서 구합니다. (수식은 아래 참조)

 

TF-IDF

 

TF (Term Freqneucy) 는 문서(document)에서 주어진 단어(term t) 가 얼마나 자주 출현하는지를 측정합니다. 말뭉치(corpus) 안의 여러 문서들은 길이가 서로 다를텐데요, 아무래도 주어진 단어는 길이가 짧은 문서보다는 길이가 긴 문서에서 더 자주 출현할 가능성이 높습니다. 따라서  이런 문제를 해결하기 위해 문서 d(i)에서 단어 t (term t)의 출현 빈도를 문서 d(i)의 총 단어의 수로 나누어서 표준화를 해줍니다. 

 

TF(t, d) = (문서 d 에서 단어 t 의 출현 빈도) / (문서 d 에서 총 단어의 수) 

 

 

IDF (Inverse Document Frequency) 는 말뭉치(corpus)에서 단어 t 의 중요도를 측정합니다. 앞서 TF 를 계산할 때 모든 단어에는 동일한 중요도(가중치)가 부여되었습니다. 하지만 관사(a, the), be 동사(is, am, are) 등의 불용어(stop words)와 같이 문서에서 자주 출현하지만 별로 중요하지 않은 단어도 있습니다. 이런 문제를 해결하기 위해, IDF 는 말뭉치의 여러 문서에 공통적으로 출현하는 단어에 대해서는 중요도(가중치)를 낮추고, 반대로 말뭉치의 여러 문서 중에서 일부 문서에만 드물게 출현하는 단어에 대해서는 중요도(가중치)를 높입니다. 

 

IDF(t, D) = log(말뭉치에서 총 문서의 개수 / 단어 t를 포함하는 문서의 개수)

 

 

TF-IDF score 는 위의 TF점수와 IDF 점수를 곱해주면 됩니다. 

 

TF-IDF(t, d, D) = TF(t, d) x IDF(t, D)

 

 

 

아래에는 4개의 문서에 나오는 단어를 추출하여 만든 말뭉치를 가지고 TF-IDF 점수를 계산해본 예제입니다. 

"Practical Natural Language Processing" (Sowmya Vajjala, et.al. 저) 책의 예제를 사용했는데요, 원서의 계산이 틀렸길레 수정해서 올립니다. (원서에서는 dog와 man의 TF score 가 틀리게 계산됨. IDF score 계산할 때는 밑이 e 이 자연 log 가 아니라 밑이 2인 log를 사용해서 계산함. 암튼, 원서 계산 다 틀렸음)

 

TF-IDF example

 

 

Bag of Words(BoW)와 비슷하게 TF-IDF 벡터는 코사인 거리(cosine distance)나 유클리디언 거리(euclidean distance) 를 사용하여 두 텍스트의 유사성을 계산하는데 사용할 수 있습니다. TF-IDF 는 정보 추출(information retrieval) 이나 텍스트 분류(text classification)에 많이 사용되고 있습니다. 

 

TF-IDF 는 단어 간의 관계를 파악하는데는 한계가 있습니다. 그리고 TF-IDF 는 텍스트를 희소하고 고차원(sparse and high-dimensional)의 행렬로 표현하므로 차원의 저주(curse of dimensionality) 문제가 있습니다. 또한 학습 데이터셋에 없는 단어에 대해서는 처리를 못하는 한계(Out of Vocabulary problem)가 있습니다. 

 

 

 

(2) Python scikit-learn 모듈을 사용한 실습

 

먼저, 실습에 사용할 텍스트로서 4개 문서의 간단한 문장을 아래와 같이 리스트로 입력해주고, 대문자를 소문자로 변환하고 불용어(stop words)인 마침표(.)는 없애주는 텍스트 데이터 전처리를 해보겠습니다. 

 

## TF-IDF (Term Freqneucy - Inverse Document Frequency) 

## input: corpus, terms in documents
documents = ["Dog bites man.", "Man bites dog.", "Dog eats meat.", "Man eats food."]
processed_docs = [doc.lower().replace(".","") for doc in documents]

print(processed_docs)
#['dog bites man', 'man bites dog', 'dog eats meat', 'man eats food']

 

 

 

단어별 TF-IDF 점수 계산은 Python Scikit-Learn 모듈의 TfidfVectorizer 메소드를 사용해서 해보겠습니다. 

앞에서 전처리한 텍스트 리스트를 TfidfVectorizer().fit_transform() 메소드를 사용하면 단어 추출과 TF-IDF 점수 계산이 한꺼번에 됩니다. 

 

 - tfidf.fit_transform() : 말뭉치 안의 단어 추출 및 TF-IDF 점수 계산

 - tfidf.get_feature_names() : 말뭉치 안의 모든 단어 리스트

 - sorted(tfidf.vocabulary_.items(), key=lambda x: x[1]) : 단어 사전을 index 기준으로 내림차순 정렬

 - tfidf.idf_ : IDF score

 

##------------------------------
## TF-IDF using sklearn module
##------------------------------

from sklearn.feature_extraction.text import TfidfVectorizer

tfidf = TfidfVectorizer()
bow_rep_tfidf = tfidf.fit_transform(processed_docs)


## All words in the vocabulary.
print(tfidf.get_feature_names())
#[Out] ['bites', 'dog', 'eats', 'food', 'man', 'meat']


## sorting vocabulary dict by values in ascending order
sorted(tfidf.vocabulary_.items(), key=lambda x: x[1])
#[Out] [('bites', 0), ('dog', 1), ('eats', 2), ('food', 3), ('man', 4), ('meat', 5)]


## IDF for all words in the vocabulary
print("IDF :",tfidf.idf_)
#[Out] IDF : [1.51082562 1.22314355 1.51082562 1.91629073 1.22314355 1.91629073]

 

 

 

본문 상단에 제시한 예제에서 손으로 계산한 TF-IDF 점수와 아래에 Scikit-learn 의 TfidfVedtorizer() 메소드로 계산한 TF-IDF 점수가 서로 다릅니다.

 

두가지 이유가 있는데요, 첫째 Scikit-learn 에서 사용한 IDF 수식이 조금 다릅니다. (소스코드 공식은 여기 참조).  분모가 '0' 일때 'Zero Division Error' 가 발생하지 않도록 분모에 '1'을 더해주었으며, 분자에도 log(0) 도 계산이 안되므로 에러가 발생하지 않도록 분자에도 '1' 을 더해주었고, 전체 값이 '1'을 더해주었습니다.  

 

Scikit-Learn의 IDF 공식: IDF(t) = log((1+n) / (1+df(t))) + 1

 

Scikit-Learn의 TF-IDF score 가 원래 TF-IDF 결과와 다른 두번째 이유는 위의 Scikit-Learn 의 TF-IDF 점수 계산 결과를 유클리디언 거리를 사용해서 표준화를 해주기 때문입니다. (자세한 설명은 여기 참조)

 

## IDF for all words in the vocabulary
## “Sklearn’s TF-IDF” vs “Standard TF-IDF”
## : https://towardsdatascience.com/how-sklearns-tf-idf-is-different-from-the-standard-tf-idf-275fa582e73d
## Scikit-Learn's IDF: IDF(t) = log((1+n)/(1+df(t))) + 1
## normalization by the Euclidean norm

print("IDF :",tfidf.idf_)
#[Out] IDF : [1.51082562 1.22314355 1.51082562 1.91629073 1.22314355 1.91629073]


# IDF for 'dog' word
# number of documents, nN=4 
# number of documents which include term t, df(t) = 3
import numpy as np

np.log((1+4)/(1+3)) + 1 # IDF(t) = log((1+n)/(1+df(t))) + 1
#[Out] 1.2231435513142097

 

 

 

- bow_rep_tfidf.toarray() : 말뭉치의 모든 문서 내 단어에 대한 TF-IDF 점수를 2차원 배열로 표현

 

## TF-IDF representation for all documents in our corpus 
print("TF-IDF representation for all documents in our corpus\n", bow_rep_tfidf.toarray()) 

#[Out] TF-IDF representation for all documents in our corpus
# [[0.65782931 0.53256952 0.         0.         0.53256952 0.        ]
# [0.65782931 0.53256952 0.         0.         0.53256952 0.        ]
# [0.         0.44809973 0.55349232 0.         0.         0.70203482]
# [0.         0.         0.55349232 0.70203482 0.44809973 0.        ]]

 

 

 

- tfidf.transform(new document) : 새로운 문서 내 단어에 대한 TF-IDF 점수 계산

 

## Get the TF-IDF score using this vocabulary, for a new text
temp = tfidf.transform(["dog and man are friends"])
print("Tfidf representation for 'dog and man are friends':\n", temp.toarray())

#[Out] Tfidf representation for 'dog and man are friends':
# [[0.         0.70710678 0.         0.         0.70710678 0.        ]]

 

 

 

[Reference]

(1) Sowmya Vajjala, et.al., "Practical Natural Language Processing", O'Reilly

(2) Scikit-learn TfidfVectorizer methods
    : https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html

(3) Scikit-learn TfidfTransformer (--> check out the formula of TF-IDF in sklearn module)

    : https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfTransformer.html#sklearn.feature_extraction.text.TfidfTransformer

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

지난 포스팅에서는 자연어 처리 (NLP: Natural Language Processing) 란 무엇이며, 어디에 사용되는지에 대해서 살펴보았습니다(https://rfriend.tistory.com/738).

 

이번 포스팅에서는 자연어 처리의 대상이 되는 언어에 대해서 알아보겠습니다. 언어학(linguistics)에서 말하는 언어 구조의 구성요소 관련 용어와 개념을 이해하면 자연어 처리를 공부하는데 큰 도움이 됩니다. 

 

(1) 언어란 무엇인가? (What is language?)

(2) 언어 구조의 구성 요소 (Building Blocks of Language Structure)

  : 음소(Phonemes), 형태소 & 어휘항목 (Morphemes & Lexemes), 구문 (Syntax), 문맥 (Context)

 

 

 

 

(1) 언어란 무엇인가? (What is language?)

 

언어는 인간이 의사소통에 사용하는 구조화된 시스템입니다. 언어는 말, 제스처, 신호, 또는 글로 표현될 수 있습니다. 

 

미국의 언어학자이자, 철학자, 인지 과학자, 역사가, 사회비평가, 정치운동가이자 저술가이기도 한 현대 언어학의 아버지 에이브럼 노엄 촘스키(Avram Noam Chomsky)는 언어에 대해서 이렇게 말했습니다. 한마디로 '언어'는 겁나 어렵다는 의미같습니다. ^^;

 

언어는 단순히 단어들이 아닙니다. 
그것은 문화, 전통, 공동체의 통일, 공동체가 무엇인지를 만드는 것에 대한 전체 역사입니다. 
그것은 모두 언어로 구현되어 있습니다.
- 노암 촘스키

 

language: Noam Chomsky

 

 

 

(2) 언어 구조의 구성 요소 (Building Blocks of Language Structure)

  : 음소(Phonemes), 형태소 & 어휘항목 (Morphemes & Lexemes), 구문 (Syntax), 문맥 (Context)

 

아래의 도식은 Sowmya Vajjala, et.al, "Practical Natural Language Processing", O'REILLY (2020) 에서 인용한 'Building Blocks of Language Structure'와 언어의 각 구성요소별 NLP 응용분야를 정리한 것입니다. 음소, 형태소 & 어휘항목, 구문, 문맥 순서대로 하나씩 소개해보겠습니다. (영어 단어가 생소해서 원서로 처음 읽을 때 뭔 소리인가 했어요..)

 

Building blocks of language structure

 

 

(2-1) 음소 (Phonemes) : 말과 소리 (Speech & Sounds)

 

  음소(Phonemes)는 언어에서 말과 소리의 가장 작은 단위(the smallest units of sound in a language)입니다. 음소는 그 자체로는 아무런 의미도 없지만, 다른 음소들과 함께 사용이 되면 의미를 가지게 될 수 있습니다.[1]  음운론(Phonology)과 언어학(Linguistics)에서 음소는 특정 언어에서 한 단어와 다른 단어를 구별할 수 있는 소리의 단위입니다.[2] 

 

 아래는 영어와 한글의 음소 예시예요. 영어에는 44개의 다른 소리의 음소가 있고, 한글에는 14개의 자음과 10개의 모음 소리의 음소가 있습니다. 

 

음소 (phonemes)

 

음소(Phonemes)는 말을 글로 변환하기(Speech to Text), 글을 말로 변환하기(Text to Speech), 화자 파악하기 (Speaker Identification) 등의 영역에 활용이 됩니다. 

 

 

 

(2-2) 형태소 & 어휘 항목 (Morphemes & Lexemes) : 단어 (Words)

 

  형태소(Morphemes) 는 의미를 가지는 언어의 가장 작은 단위(the smallest unit of language) 이며, 음소(phonemes)의 조합을 통해서 만들어집니다.[1]  형태소는 단어(Words)처럼 보이기는 하지만, 그렇다고 행태소가 곧 단어는 아닙니다. 형태소와 단어의 차이점은, 형태소는 홀로 사용될 수 없지만, 단어는 그 정의상 항상 홀로 자기완결적으로 사용될 수 있다는 점입니다.[3]

 

아래 예에서는 영어 단어를 형태소로 분리해본 것인데요, 아무래도 예를 보는 것이 형태소를 이해하는데 직관적으로 와 닿을것 같습니다. (예: running => run + nning, books => book + s, unreadable => un+read+able, readability => read+able+ity)  unreadable 에서 접두사 'un'이나 접미사 'able'은 모두 형태소로서, 단어의 뜻을 바꾸어줍니다. 

 

[ 단어에서 형태소 분리 예시 (examples of morphemes in words) ]

형태소 (morphemes)

 

 

  어휘항목(Lexemes) 또는 어휘소는 의미에 의해서 서로 관련되어 있는 형태소의 구조적인 변형(the structural variations of morphemes related to one another by meaning)입니다.[1]  어휘항목(어휘소)는 변형을 통해 관련되는 단어들의 기초가 되는 어휘적 의미의 단위입니다. 어근 단어(root word)에 의해 대략적으로 일치하는 형태소 분석의 단위인 기본 추상적 의미 단위입니다.[4] (위키피디아 번역하려니 쉽지가 않네요. -,-;) 예를 들어, 영어에서 Run, Runs, Ran, Running은 "RUN"으로 표현될 수 있는 동일한 어휘소의 형태입니다. 예를 보면 금방 이해가 될 것 같습니다. 

 

[ 어휘항목(어휘소, Lemexmes) 예시 ]

어휘항목, 어휘소 (lexemes)

 

형태소와 어휘소는 토큰화(Tokenization), 단어 임베팅(Word Embedding), 형태소(품사) 분석(POS Tagging: Part-Of-Speech Tagging) 등의 영역에 사용됩니다. 

 

 

 

(2-3) 구문 (Syntax) : 문장 (Phrases & Sentences)

 

  언어학에서 구문론(Syntax)은 단어(Words)와 형태소(Morphemes)가 어떻게 결합되어 구(Phrases)나 문장(Sentences)과 같은 더 큰 단위를 형성하는지 연구하는 학문입니다. 구문론의 중심 관심사는 어순(Word Order), 문법적 관계(Grammatical Relations), 계층적 문장 구조(구성)(Hierarchical Sentence Structure, Constituency), 교차 언어적 변형의 특성(the nature of crosslinguistic variation), 형태와 의미 사이의 관계(the relationship between form and meaning)를 포함합니다. 구문론에는 중심 가정과 목표가 다른 수많은 접근법이 있습니다.[5]

 

  언어학에서 구문론적인 구조는 많은 다양한 형태로 제시될 수 있습니다. 그중에서 문장을 표현하는 일반적인 방법으로 'a Parse Tree' 이 있습니다. Parse Tree는 언어의 계층적 구조(a hierarchical structure of language)를 가지고 있으며, 아래의 예시에서 보는 바와 같이, 제일 밑에는 단어(words), 그 위에는 형태소(품사) 태깅(POS tagging, Part-Of-Speech Tagging), 그 위에는 구(phrase), 제일 위에는 문장(sentence)으로 하여 계층적 구조를 시각화해서 나타내줍니다.[1] 

 

[ A Parse Tree 예시 ]

Syntax: a parse tree

* image: wikipedia.org

 

 

언어학의 구문론(Syntax)은 파싱(Parsing), 객체 추출(Entity Extraction), 관계 추출(Relation Extraction)에 사용됩니다. 

 

 

 

(2-4) 문맥 (Context) : 의미 (Meaning) 

 

  문맥(Context)은 언어의 사용, 언어의 변화, 대화/문장의 요약에 영향을 미치는 의사소통 상황과 관련된 제약을 말합니다.[6]  문맥은 언어의 각 요소들이 합쳐져서 특정 의미(meaning)를 가지고 만드는 것과 관련이 있습니다. 문맥은 단어와 구문의 문자 그대로의 의미(literal meaning of words and phrases)와 함께 장기간의 참조(long-term references), 세계 지식(world knowledge), 상식(common sense)을 포함한다. 문장의 의미는 문맥에 따라 달라질 수 있는데, 이는 단어와 구절이 때로는 여러 의미를 가질 수 있기 때문입니다.[1].

 

바로 언어의 이런 문맥이 가지는 특성 때문에 상식을 배우지 못하는 기계 번역이 굉장히 어려운 과제인 것입니다. 사람도 문맥을 잘 파악하지 못하면 엉뚱하게 해석해서 곤란한 경우가 자주 있는데, 인공지능이라고 예외는 아니겠죠. 

 

example of sentiment analysis

 

 

문맥은 문서 요약(Summarization), 토픽 모델링(Topic Modeling), 감성분석(Sentiment Analysis), 냉소적인 표현 탐지(Sarcasm Detection) 등의 분야에 활용됩니다. 

 

 

이상으로 언어 구조의 구성요소로서 음소(Phonemes), 형태소와 어휘소(Morphemes & Lexemes), 구문(Syntax), 문맥(Context) 에 대한 소개를 마치겠습니다.  (저는 언어학 전공이 아닌지라 공부하면서 번역하는데 용어가 좀 어려웠습니다. ㅋ)

 

 

[ Reference ]

[1] Sowmya Vajjala el.al., "Practical Natural Language Processing: A Comprehensive Guide to Building Real-World NLP Systems", O'REILLY (2020) 

[2] Phonemes (Wikipedia): https://en.wikipedia.org/wiki/Phoneme 

[3] Morphemes (Wikipedia): https://en.wikipedia.org/wiki/Morpheme

[4] Lexemes (Wikipedia): https://en.wikipedia.org/wiki/Lexeme

[5] Syntax (Wikipedia): https://en.wikipedia.org/wiki/Syntax

[6] Context (Wikipedia): https://en.wikipedia.org/wiki/Context

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

빅데이터의 시대에 매 순간 엄청난 양의 텍스트 비정형 데이터가 생성/ 저장/ 분석이 되고 있습니다. 그리고 특히 최근에는 딥러닝을 자연어 처리에 적극 활용함으로써 기존에는 할 수 없었던 놀라운 성과가 속속 나오고 있습니다. 

 

이번 포스팅에서는 자연어 처리(NLP: Natural Language Processing)에 대한 첫발을 떼는 개요로서, 

 

(1) 자연어 처리 이란 무엇인가? (What is NLP?)

(2) 자연어 처리의 응용분야 (NLP Tasks)에는 무엇이 있나?

 

에 대해서 소개하겠습니다. 

 

 

 

(1) 자연어 처리 (NLP: Natural Language Processing) 이란 무엇인가? 

 

자연어 처리(NLP, Natural Language Processing)는 컴퓨터와 인간 언어, 특히 대량의 자연어 데이터를 처리하고 분석하도록 컴퓨터를 프로그래밍하는 방법과 관련된 언어학, 컴퓨터 과학, 인공지능의 하위 분야입니다. [1] 

(Natural language processing (NLP) is a subfield of linguistics, computer science, and artificial intelligence concerned with the interactions between computers and human language, in particular how to program computers to process and analyze large amounts of natural language data.)

 

자연어 처리와 유사한 의미로 많이 사용되는 용어인 텍스트 마이닝(text mining)은 텍스트 분석(text analytics, text analysis), 텍스트 데이터 마이닝 (text data mining)이라고도 하며, 텍스트에서 고품질 정보를 얻는 과정을 말합니다. 텍스트 마이닝은 컴퓨터를 사용해서 텍스트로부터 정보를 자동으로 추출함으로써, 이전에 알려지지 않았던 새로운 정보를 발견을하는 것을 포함합니다. [2] (Text mining, also referred to as text data mining, similar to text analytics, is the process of deriving high-quality information from text. It involves "the discovery by computer of new, previously unknown information, by automatically extracting information from different written resources)

 

 

 

(2) 자연어 처리의 응용분야 (NLP Tasks)에는 무엇이 있나?

 

아래의 도식은 상대적인 난이도에 따라서 자연어 처리의 응용분야 (NLP Tasks) 를 나열해 본 것입니다. [3] 

아래 도식에 소개된 자연어처리(NLP)의 쉬운 과업부터 어려운 과업까지 순서대로 간략하게 설명을 해보겠습니다. 

 

NLP Tasks

* 출처: Sowmya Vajjala et.al, "Practical Natural Language Process: A Comprehensive Guide to Building Real-World NLP Systems", O'REILLY, 2020

 

 

* 맞춤법 검사 (Spell Checking) 

  맞춤법 검사기 (또는 맞춤법 검사기)는 소프트웨어에서 텍스트의 오타를 검사하는 소프트웨어 기능입니다. 워드 프로세서 사용하다 보면 오타에 빨간줄 밑줄 그어진거 보셨을 거예요.  철자 검사 기능은 워드 프로세서, 전자 메일 클라이언트, 전자 사전 또는 검색 엔진과 같은 소프트웨어나 서비스에 내장되어 있는 경우가 많습니다. Grammarly 와 같은 맞춤법 검사 및 문법 검사 서비스 광고를 요즘 많이 보게 되네요. 

 

 

* 키워드 기반 정보 검색 (Keyword-Based Information Retrieval)

  정보 검색은 대규모의 문서를 모아놓은 곳에서 사용자 쿼리와 관련된 문서를 찾는 작업입니다. 구글 검색(Google Search)과 같은 애플리케이션은 정보 검색의 대표적인 사례입니다.

 

 

* 토픽 모델링 (Topic Modeling)

  토픽 모델링은 문서들에 대한 비지도 분류 학습 방법(a method for unsupervised classification of documents)으로, 우리가 무엇을 찾아야 하는지 확실하지 않은 경우에도 자연스러운 항목 그룹을 찾는 숫자 데이터에 대한 클러스터링과 유사합니다. 토픽 모델링은 거대한 문서들의 집합에서 토픽 구조를 발견하는데 사용합니다. 잠재 디리클레 할당(LDA: Latent Dirichlet Allocation) 은 주제 모델을 적합시키기 위해 특히 인기 있는 기법입니다.

 

 

* 텍스트 분류 (Text Classification)

  텍스트 분류는 텍스트를 내용에 따라 알려진 범주 집합으로 분류하는 작업입니다. 텍스트 분류는 자연어 처리(NLP)에서 단연코 가장 인기 있는 작업이며, 전자 메일 스팸 식별에서 감성 분석(sentiment analysis)에 이르기까지 다양한 도구에 사용됩니다. 

 

 

* 정보 추출 (Information Extraction)

  정보 추출은 이메일이나 소셜 미디어 게시물에서 언급된 사람의 이름과 같은 관련 정보를 텍스트에서 추출하는 작업입니다.

 

 

* 텍스트 요약 (Text Summarization) 

    자동 텍스트 요약(Automatic Text Summary)은 원본 내용 내에서 가장 중요하거나 관련 있는 정보를 나타내는 부분 집합(요약)을 만들기 위해 계산적으로 데이터 집합을 요약, 단축하는 과정을 말합니다.  

 

 

* 질의 응답 (Question Answering)

  질의 응답(QA)은 정보 검색 및 자연어 처리(NLP) 분야의 컴퓨터 과학 분야로, 자연 언어로 인간이 제기하는 질문에 자동으로 답변하는 시스템을 구축하는 것과 관련이 있습니다.

 

 

* 기계 번역 (Machine Translation)

  기계 번역은 텍스트나 음성을 한 언어에서 다른 언어로 번역하는 소프트웨어의 사용을 연구하는 컴퓨터 언어학의 하위 분야입니다. Google Translator, Papago 번역기 등이 대표적인 예가 되겠습니다. 

 

 

* 열린 주제의 대화 에이전트 (Open Domain Conversational Agent)

  대화 시스템 또는 대화 에이전트(CA)는 인간과 대화하기 위한 컴퓨터 시스템입니다. 대화 시스템은 입력 채널과 출력 채널 모두에서 통신을 위해 하나 이상의 텍스트, 음성, 그래픽, 촉감, 제스처 및 기타 모드를 사용합니다. (위 도식의 오른쪽 부분 워크 플로우별 과업 참조). 애플의 Siri, Kakao Mini 등의 인공지능 스피커가 대화 에이전트(CA)의 대표적인 예가 되겠네요. 

 

 

 

[ Reference ]

1. NLP (Natural Language Processing)
    : https://en.wikipedia.org/wiki/Natural_language_processing

2. Text Mining(or Text Data Mining, Text Analytics, Text Analysis)
    : https://en.wikipedia.org/wiki/Text_mining

3. Sowmya Vajjala et.al, "Practical Natural Language Process: A Comprehensive Guide to Building Real-World NLP Systems", O'REILLY, 2020

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요.  :-)

 

728x90
반응형
Posted by Rfriend
,

딥러닝 모델을 훈련할 때 사용하는 GPU 장치가 무엇인지, GPU Driver version, CUDA version 등의 정보를 확인하고 싶을 때, 또 모델 훈련 중에 GPU의 총 메모리 중에서 현재 활용되고 있는 메모리는 어느정도 인지, 총 사용 가능한 전력 사용량 중에서 현재 사용하고 있는 전력량은 어느정도 인지 등을 모니터링 하고 싶을 때 nvidia-smi 유틸리티를 사용합니다. 

 

NVIDIA 시스템 관리 인터페이스(nvidia-smi, NVIDIA System Management Interface)는 NVIDIA GPU 장치의 관리 및 모니터링을 지원하기 위한 NVML (NVIDIA Management Library)을 기반으로 하는 command line utility입니다.

 

nvidia-smi, NVIDIA System Management Interface

 


이 유틸리티를 사용하면 관리자가 GPU 장치 상태를 쿼리할 수 있으며 적절한 권한으로 관리자가 GPU 장치 상태를 수정할 수 있습니다. TeslaTM, GRIDTM, QuadroTM 및 Titan X 제품을 대상으로 하지만 다른 NVIDIA GPU에서도 제한된 지원이 가능합니다.

NVIDIA-smi는 Linux의 NVIDIA GPU 디스플레이 드라이버와 64비트 Windows Server 2008 R2 및 Windows 7과 함께 제공됩니다. Nvidia-smi는 쿼리 정보를 XML 또는 사람이 읽을 수 있는 일반 텍스트로 표준 출력이나 파일에 보고할 수 있습니다. 

 

 

command line 창에서  $ nvidia-smi -q   (또는  $ nvidia-smi -query ) 명령어를 실행하면 아래와 같이 NVIDIA GUP 장치에 대한 정보와 현재 사용 중인 GPU 상태에 대한 모니터링 정보를 한꺼번에 알 수 있습니다. 

(Jupyter Notebook cell에서는 느낌표를 먼저 써주고,   ! nvidia-smi -q  를 입력해주면 됩니다.)

 

(Jupyter Notebook 에서 실행 시)
! nvidia-smi -q

(출력)

==============NVSMI LOG==============

Timestamp                                 : Sun Jan  9 12:55:56 2022
Driver Version                            : 460.32.03
CUDA Version                              : 11.2

Attached GPUs                             : 1
GPU 00000000:00:04.0
    Product Name                          : Tesla K80
    Product Brand                         : Tesla
    Product Architecture                  : Kepler
    Display Mode                          : Disabled
    Display Active                        : Disabled
    Persistence Mode                      : Disabled
    MIG Mode
        Current                           : N/A
        Pending                           : N/A
    Accounting Mode                       : Disabled
    Accounting Mode Buffer Size           : 4000
    Driver Model
        Current                           : N/A
        Pending                           : N/A
    Serial Number                         : 0320617086266
    GPU UUID                              : GPU-ed69a555-6186-feff-25f8-615b2ac9859f
    Minor Number                          : 0
    VBIOS Version                         : 80.21.25.00.02
    MultiGPU Board                        : No
    Board ID                              : 0x4
    GPU Part Number                       : 900-22080-6300-001
    Module ID                             : Uninitialized
    Inforom Version
        Image Version                     : 2080.0200.00.04
        OEM Object                        : 1.1
        ECC Object                        : 3.0
        Power Management Object           : N/A
    GPU Operation Mode
        Current                           : N/A
        Pending                           : N/A
    GSP Firmware Version                  : Uninitialized
    GPU Virtualization Mode
        Virtualization Mode               : Pass-Through
        Host VGPU Mode                    : N/A
    IBMNPU
        Relaxed Ordering Mode             : N/A
    PCI
        Bus                               : 0x00
        Device                            : 0x04
        Domain                            : 0x0000
        Device Id                         : 0x102D10DE
        Bus Id                            : 00000000:00:04.0
        Sub System Id                     : 0x106C10DE
        GPU Link Info
            PCIe Generation
                Max                       : 3
                Current                   : 1
            Link Width
                Max                       : 16x
                Current                   : 16x
        Bridge Chip
            Type                          : N/A
            Firmware                      : N/A
        Replays Since Reset               : 0
        Replay Number Rollovers           : 0
        Tx Throughput                     : N/A
        Rx Throughput                     : N/A
    Fan Speed                             : N/A
    Performance State                     : P8
    Clocks Throttle Reasons
        Idle                              : Active
        Applications Clocks Setting       : Not Active
        SW Power Cap                      : Not Active
        HW Slowdown                       : Not Active
            HW Thermal Slowdown           : N/A
            HW Power Brake Slowdown       : N/A
        Sync Boost                        : Not Active
        SW Thermal Slowdown               : Not Active
        Display Clock Setting             : Not Active
    FB Memory Usage
        Total                             : 11441 MiB
        Used                              : 0 MiB
        Free                              : 11441 MiB
    BAR1 Memory Usage
        Total                             : 16384 MiB
        Used                              : 2 MiB
        Free                              : 16382 MiB
    Compute Mode                          : Default
    Utilization
        Gpu                               : 0 %
        Memory                            : 0 %
        Encoder                           : 0 %
        Decoder                           : 0 %
    Encoder Stats
        Active Sessions                   : 0
        Average FPS                       : 0
        Average Latency                   : 0
    FBC Stats
        Active Sessions                   : 0
        Average FPS                       : 0
        Average Latency                   : 0
    Ecc Mode
        Current                           : Enabled
        Pending                           : Enabled
    ECC Errors
        Volatile
            Single Bit            
                Device Memory             : 0
                Register File             : 0
                L1 Cache                  : 0
                L2 Cache                  : 0
                Texture Memory            : 0
                Texture Shared            : N/A
                CBU                       : N/A
                Total                     : 0
            Double Bit            
                Device Memory             : 0
                Register File             : 0
                L1 Cache                  : 0
                L2 Cache                  : 0
                Texture Memory            : 0
                Texture Shared            : N/A
                CBU                       : N/A
                Total                     : 0
        Aggregate
            Single Bit            
                Device Memory             : 2
                Register File             : 0
                L1 Cache                  : 0
                L2 Cache                  : 0
                Texture Memory            : 0
                Texture Shared            : N/A
                CBU                       : N/A
                Total                     : 2
            Double Bit            
                Device Memory             : 4
                Register File             : 0
                L1 Cache                  : 0
                L2 Cache                  : 0
                Texture Memory            : 0
                Texture Shared            : N/A
                CBU                       : N/A
                Total                     : 4
    Retired Pages
        Single Bit ECC                    : 0
        Double Bit ECC                    : 2
        Pending Page Blacklist            : No
    Remapped Rows                         : N/A
    Temperature
        GPU Current Temp                  : 52 C
        GPU Shutdown Temp                 : 93 C
        GPU Slowdown Temp                 : 88 C
        GPU Max Operating Temp            : N/A
        GPU Target Temperature            : N/A
        Memory Current Temp               : N/A
        Memory Max Operating Temp         : N/A
    Power Readings
        Power Management                  : Supported
        Power Draw                        : 31.51 W
        Power Limit                       : 149.00 W
        Default Power Limit               : 149.00 W
        Enforced Power Limit              : 149.00 W
        Min Power Limit                   : 100.00 W
        Max Power Limit                   : 175.00 W
    Clocks
        Graphics                          : 324 MHz
        SM                                : 324 MHz
        Memory                            : 324 MHz
        Video                             : 405 MHz
    Applications Clocks
        Graphics                          : 562 MHz
        Memory                            : 2505 MHz
    Default Applications Clocks
        Graphics                          : 562 MHz
        Memory                            : 2505 MHz
    Max Clocks
        Graphics                          : 875 MHz
        SM                                : 875 MHz
        Memory                            : 2505 MHz
        Video                             : 540 MHz
    Max Customer Boost Clocks
        Graphics                          : N/A
    Clock Policy
        Auto Boost                        : On
        Auto Boost Default                : On
    Voltage
        Graphics                          : Uninitialized
    Processes                             : None

 

 

 

위의 실행 결과에 NVIDIA GPU 의 장치 및 실행 모니터링의 모든 정보가 출력이 되다보니 양이 너무나 많습니다. 만약 간단하게 시스템에 연결된 NVIDIA GPU 의 장치 리스트의 이름 (Product Name)과 UUID 정보만 알고 싶으면 command line 에서  $ nvidia-smi -L  (혹은  $ nvidia-smi --list-gups ) 를 실행시켜주면 됩니다. 

 

(Jupyter Notebook에서 실행 시)
! nvidia-smi -L

(출력)

GPU 0: Tesla K80 (UUID: GPU-ed69a555-6186-feff-25f8-615b2ac9859f)

 

 

만약 시스템에 연결된 NVIDIA GPU 의 메모리의 상태에 대해서 알고 싶으면 command line 창에서  $ nvidia-smi -q -d memory  를 입력해주면 됩니다. 

 

(Jupyter Notebook에서 실행 시)
! nvidia-smi -q -d memory

(출력)

[Out]
==============NVSMI LOG==============

Timestamp                                 : Sun Jan  9 12:59:09 2022
Driver Version                            : 460.32.03
CUDA Version                              : 11.2

Attached GPUs                             : 1
GPU 00000000:00:04.0
    FB Memory Usage
        Total                             : 11441 MiB
        Used                              : 0 MiB
        Free                              : 11441 MiB
    BAR1 Memory Usage
        Total                             : 16384 MiB
        Used                              : 2 MiB
        Free                              : 16382 MiB

 

 

 

[ Reference ]

(1) NVIDIA System Management Interface (NVIDIA-smi)
    : https://developer.nvidia.com/nvidia-system-management-interface

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 TensorFlow Keras의 손실함수 중에서 다중분류 문제(multiclass classification problem) 에 대한 딥러닝 모델을 훈련할 때 사용하는 손실함수에 대해서 소개하겠습니다. 

 

(1) 손실함수란 무엇인가? 

(2) 문제 유형별 Keras의 손실함수는 무엇이 있나? 

(3) 교차 엔트로피(Cross Entropy) 란 무엇인가?

(4) sparse_categorical_crossentropy() vs. categorical_crossentropy() 비교

 

 

 

(1) 손실함수란 무엇인가? 

 

 기계학습(Machine Learning), 딥러닝(Deep Learning) 은 손실함수(Loss Function)을 통해서 학습합니다. 손실함수는 다른 이름으로 비용함수(Cost Function)라고도 합니다. 

 

 손실함수는 특정 알고리즘이 주어진 데이터를 얼마나 잘 모델링하는지를 측정하는 방법입니다. 만약 학습모델을 사용해 예측한 값(predicted value)이 참 값(true value, actual value)과 차이가 많이 날 경우 손실함수의 값은 매우 커지게 되며, 손실함수 값이 작을 수록 알고리즘이 주어진 데이터를 잘 모델링했다고 평가할 수 있습니다. 

 

 기계학습, 딥러닝에서는 손실함수의 손실값(loss value)을 점점 작게 해서 최소의 손실 값을 찾아가는 최적화 함수(optimization function)을 사용해서 데이터로 부터 모델을 학습하게 됩니다. 최적화 함수에 대해서는 별도의 포스팅을 통해서 나중에 소개하도록 하겠습니다. 

 

 

 

(2) 문제 유형별 Keras의 손실함수는 무엇이 있나? 

 

 모든 문제에 공통으로 적용할 수 있는 만능의 손실함수는 없습니다. 각 문제 유형(예: 회귀, 분류)과 데이터 형태(y label 이 정수, onehot encoded), 미분 계산의 용이성, 이상치(outliers)의 포함 정도 등에 따라서 사용하는 손실함수는 달라집니다. 

 아래의 표는 TensorFlow Keras의 문제 유형(problem types) 별로 마지막층의 활성화 함수(last layer's activation function)와 손실함수/클래스를 표로 정리한 것입니다.

 

이번 포스팅에서 다루고자 하는 TensorFlow Keras의  sparse_categorical_crossentropy()와 categorical_crossentropy() 손실함수는 다중분류 문제(multiclass classification problem)에 사용하는 손실함수입니다. 

 

 

[ TensorFlow Keras의 손실 함수, 손실 클래스 (Loss Functions, Loss Classes) ]

TensorFlow Keras Loss Functions, Loss Classes

 

 

 

(3) 교차 엔트로피(Cross Entropy) 란 무엇인가?

 

교차 엔트로피 개념은 정보이론(information theroy)에서 나왔습니다. 교차 엔트로피(Cross Entropy)는 동일한 근간의 사건의 집합(over the same underlying events set)에서 뽑은 두 개의 확률 분포 p와 q에서 만약 집합에 사용된 코딩 체계가 실제 확률분포 p보다 추정 확률 분포 q에 최적화되어 있는 경우 집합으로 부터 뽑힌 사건을 식별하는데 필요한 평균 비트 수를 측정합니다.

 

위의 정의는 위키피디아(https://en.wikipedia.org/wiki/Cross_entropy) 에서 인용한 것인데요, 무슨 말인지 잘 이해하기 힘들지요? 아래의 유튜브 링크는 "Hands-on Machine Learning with Scikitlearn, Keras & TensorFlow" 책의 저자인 Aurelien Geron 님께서 "Entropy, Cross Entropy, KL Divergence"에 대해서 소개해주고 있는 영상인데요, 이걸 참고하시면 이해하는데 훨씬 쉬울거예요. 

 

 

이 정의는 다시 확률분포 q로 부터의 p의 차이인 Kullback-Leibler Divergence  Dkl(p||q) 로 공식화(be formulated)될 수 있습니다. 이산형 확률분포와 연속형 확률분포일 경우별로 교차엔트로피를 구하는 수식은 아래의 내용을 참고하세요. 

 

 

교차 엔트로피는 기계학습과 최적화에서 손실 함수를 정의하는 데 사용될 수 있습니다. 참 확률 p(i)는 정답 레이블이고, 주어진 분포 q(i)는 현재 모델의 예측 값입니다. 언어 모델을 예로 들면, 훈련 데이터셋을 기반으로 언어모델을 생성한 다음, 교차 엔트로피를 테스트 세트에서 측정하여 모델이 테스트 데이터를 예측하는 데 얼마나 정확한지 평가합니다. 이 언어모델 예에서 p는 모든 말뭉치에서 단어의 실제 분포이고, q는 모델에 의해 예측된 단어의 분포입니다. 

 

y(i) 를 실제의 참 값(actual true value), y_hat(i)를 모델이 예측한 값(predicted value)라고 했을 때, 분류 문제의 교차 엔트로피는 아래와 같은 수식으로 표현할 수 있습니다. (이진분류의 경우 y(i)가 0 또는 1 의 값을 가짐). 아래 수식을 보면 알 수 있듯이, 이진분류문제의 교차 엔트로피 손실함수는 실제 값이 0이면 아래 수식의 왼쪽 부분이 없어지고, 실제 값이 1이면 아래 수식의 오른쪽이 없어집니다. 따라서 만약 이진분류 모델이 실제 값을 틀리게 예측하고 또 예측확률값이 높을 수록 교차 엔트로피 손실함수 값이 더 커지게끔 설계되어 있습니다. (틀렸으면 벌을 주는데, 더 확신을 가지고 틀렸으면 더 큰 벌을 주는 개념). 

Cross Entropy Loss for Classification Problem

 

 

 

(4) sparse_categorical_crossentropy() vs. categorical_crossentropy() 비교

 

(4-1) 다중분류 문제(multiclass classification problem) 에 사용하는 함수 중에서 y label 의 형태에 따라서, 

 - tf.keras.losses.sparse_categorical_crossentropy(): y label 이 정수 (integer) 

 - tf.keras.losses.categorical_crossentropy(): y label 이 one-hot encoded 

를 선택해서 사용하면 됩니다.

아래의 화면캡쳐한 코드 예시를 보면 y label의 형태가 어떻게 다른지 금방 알 수 있을 거예요. 

 

(4-2) 또 하나 차이점이 있다면, 문제의 유형(problem types)에 따라서, 

 - tf.keras.losses.sparse_categorical_crossentropy(): multiclass single-label classification 만 가능

 - tf.keras.losses.categorical_crossentropy(): multiclass single-label classification, multiclass multilabel classification 둘다 사용 가능

하다는 차이점이 있습니다.  

multiclass single-label classification 문제는 다중 클래스 중에서 관측치는 단 한개의 클래스에만 속하는 문제(예: MNIST의 이미지 숫자 분류)를 말하며, multiclass multilabel classification 문제는 관측치가 여러개의 클래스에 속할 수 있는 문제(예: 음악 장류 분류, 영화 장르 분류 등)를 말합니다. 

 

Keras: sparse_categorical_crossentropy vs. categorical crossentropy

 

 

 

[ Reference ]

* TensorFlow 손실함수 (Loss Functions/ Classes)
   : https://www.tensorflow.org/api_docs/python/tf/keras/losses

* Keras 손실함수 (Loss Functions/ Classes): https://keras.io/api/losses/

* Cross Entropy: https://en.wikipedia.org/wiki/Cross_entropy

* Keras sparse_categorical_crossentropy()
   : https://www.tensorflow.org/api_docs/python/tf/keras/metrics/sparse_categorical_crossentropy

* Keras categorical_crossentropy()
   : https://www.tensorflow.org/api_docs/python/tf/keras/metrics/categorical_crossentropy

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,