by Yngie

Numpy (1) - ndarray 생성, 데이터 타입 및 크기 다루기

|

이번 포스팅의 내용은 파이썬 라이브러리를 활용한 데이터 분석(2판) 의 내용을 참조하여 작성하였습니다.

Numpy

Numpy(넘파이)는 Numerical Python의 줄임말입니다. 말 그대로 수학 계산을 위한 패키지이지요. 넘파이의 코드는 C, C++, Fortran 등으로 작성되었으며 파이썬으로 래핑되어 상당히 빠른 연산 속도를 보장합니다. 넘파이 배열(Array) 연산시에는 반복문(for loop)을 사용하지 않고 벡터화된 연산을 수행합니다.

ndarray 생성하기

ndarray는 넘파이가 제공하는 $N$ 차원의 배열 객체입니다. 넘파이 패키지를 import 한 뒤에 ndarray 를 생성해보겠습니다. 생성된 객체의 타입을 확인할 수 있습니다.

>>> import numpy as np

>>> arr1 = np.array([1, 2, 3])

>>> print(type(arr1))
<class 'numpy.ndarray'>

리스트를 변환하여 새로운 배열을 생성할 수도 있습니다.

>>> lst1 = [1, 4, 9, 16]
>>> arr2 = np.array(lst1)
>>> arr2

array([ 1,  4,  9, 16])

ndarray 데이터 타입 다루기

생성된 배열의 요소 타입을 확인하는 메서드로 .dtype 이 있습니다. 배열 생성 시 타입을 지정해주지 않는다면 int64 혹은 float64 로 생성됩니다. 만약 크기가 크지 않은 정수형 데이터를 다루거나, 부동 소수점에 만감하지 않은 실수형 데이터를 다루기 위해 배열을 생성할 때 데이터 타입을 int32, float32 로 지정해주면 메모리를 절약할 수 있습니다.

# 따로 지정해주지 않은 경우 `int64'로 생성
>>> print(arr1.dtype)
int64

# 생성할 때 요소의 타입을 지정해주면 그대로 생성
>>> arr3 = np.array([1, 2, 3], dtype='int32')
>>> print(arr3.dtype)
int32

# float(실수형)도 마찬가지
>>> arr_float1 = np.array([1, 2.5, 4, 5.5])
>>> print(arr_float1.dtype)
float64

# float32로 지정해주면 그대로 생성한다
>>> arr_float2 = np.array([1, 2.5, 4, 5.5], dtype='float32')
>>> print(arr_float2.dtype)
float32

.astype 메서드를 활용하면 배열의 데이터 타입을 다른 형태로 바꾸어 새로운 형태로 할당할 수 있습니다.

>>> arr_float3 = arr1.astype('float64')
>>> print(arr_float3.dtype)
float64

실수형(float) 데이터 타입을 정수형으로 변경한 경우에는 소수점 아래 자리가 버려집니다. .astype 메서드를 활용하면 숫자를 담고 있는 문자열도 숫자로 변환할 수 있습니다.

# 실수형 데이터타입을 정수형으로 변경한 경우
>>> arr_int1 = arr_float1.astype('int64')
>>> arr_int1
array([1, 2, 4, 5])
# 2.5 -> 2로, 5.5 -> 5로 소수점이 버려진 것을 알 수 있습니다.
# 음수의 경우 -1.5 -> -1, -3.7 -> -3 과 같이 변합니다.

# 숫자를 품고 있는 문자열 숫자로 변환하기
>>> arr_str1 = np.array(['1.3', '4.24', '-5'])
>>> arr_num1 = arr_str1.astype('float64')
>>> arr_num1
array([ 1.3 ,  4.24, -5.  ])

ndarray의 크기 다루기

.ndim 메서드를 사용하면 해당 배열의 차원 수를 알 수 있고 .shape 메서드로는 해당 배열의 크기(형태)를 알 수 있습니다.

>>> arr_2dim = np.array([[1, 2, 3], [4, 5, 6]])
>>> arr_2dim
array([[1, 2, 3],
       [4, 5, 6]])

>>> print(f"""배열의 차원 수 : {arr_2dim.ndim}
배열의 크기 : {arr_2dim.shape}""")

배열의 차원  : 2
배열의 크기 : (2, 3)

2차원 배열을 생성하였으므로 .ndim 을 사용하여 확인한 값은 $2$ 가 나왔고 2행 3열 이므로 배열의 크기는 $(2, 3)$ 이 나왔습니다. 차원은 알기 쉽지만 크기는 선뜻 알기 쉽지 않습니다. 3차원 배열을 생성하여 크기가 어떻게 결정되는지 한 번 더 알아보겠습니다.

>>> arr_3dim = np.array([[[1, 2, -3], [3, 4, -5]], [[5, 6, -7], [7, 8, -9]]])
>>> arr_3dim

array([[[ 1,  2, -3],
        [ 3,  4, -5]],

       [[ 5,  6, -7],
        [ 7,  8, -9]]])

>>> print(f"""배열의 차원 수 : {arr_3dim.ndim}
배열의 크기 : {arr_3dim.shape}""")

배열의 차원  : 3
배열의 크기 : (2, 2, 3)

.reshape 메서드를 사용하면 행렬의 차원이나 크기를 변경할 수 있습니다. 요소의 개수가 24개인 행렬을 만들고 이를 다양한 차원과 크기로 변형해보겠습니다.

# .arange는 range와 비슷한 역할을 하는 메서드입니다 
>>> arr_12 = np.arange(12)
>>> arr_12

array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

# 배열의 shape을 (3,4)로 변경하기 (1차원 -> 2차원)
>>> arr_3x4 = arr_24.reshape(3,4)
>>> arr_3x4

array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

# 배열의 shape을 (2,3,4)로 변경하기 (1차원 -> 3차원)
>>> arr_2x2x3 = arr_12.reshape(2,2,3)
>>> arr_2x2x3

array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])

위와 같이 .reshape 을 사용하면 행렬의 크기와 차원을 변경할 수 있습니다. .reshape 메서드 사용시 주의할 점은 바꿀 대상의 요소의 개수와 행렬의 크기가 맞아야 한다는 것입니다. 아래와 같이 요소의 개수와 바꾸고자 하는 행렬의 크기가 맞지 않으면 에러가 발생합니다.

>>> arr_2x2x2 = arr_12.reshape(2,2,2)
>>> arr_2x2x2

ValueError: cannot reshape array of size 12 into shape (2,2,2)

원래 배열의 요소는 12개인데 바꾸고자 하는 크기인 $(2,2,2)$ 는 이와 맞지 않습니다. 숫자가 많아지면 .reshape 사용시 암산으로만 숫자를 배정하기가 힘듭니다. 넘파이에서는 이를 위해서 한 가지 편의 기능을 제공합니다. .reshape 의 인자로 $-1$ 을 넣어주면 숫자 하나를 대체할 수 있습니다. 아래 예시를 보겠습니다.

>>> arr_2x2x_1 = arr_12.reshape(2,2,-1)
>>> arr_2x2x_1

array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])

>>> arr_2x_1x3 = arr_12.reshape(2,-1,3)
>>> arr_2x_1x3

array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])

각각 $3$과 $2$의 자리를 $-1$을 사용하여 잘 대체한 것을 볼 수 있습니다. 이 기능을 사용하면 편하게 행렬의 크기를 변경할 수 있습니다. 그런데 $-1$ 을 2개 이상 사용하면 어떻게 될까요?

>>> arr_2x_1x_1 = arr_12.reshape(2,-1,-1)
>>> arr_2x_1x_1

ValueError: can only specify one unknown dimension

unknown dimension, 즉 $-1$ 로 대체할 수 있는 차원은 2개 이상 지정할 수 없음을 알리는 에러가 발생했습니다.

Conclusion

이번 게시물에서는 넘파이 패키지를 사용하여 배열(ndarray)을 생성하고 생성한 배열의 데이터 타입과 크기를 다뤄보았습니다. 다음 게시물에서는 배열의 슬라이싱에 대해서 알아보겠습니다.

Comment  Read more

배치 정규화 (Batch Normalization)

|

Batch Normalization

이번 게시물에서는 배치 정규화(Batch normalization)에 대해서 알아보겠습니다. 배치 정규화의 장점은 세 가지가 있습니다. 먼저 학습 속도를 빠르게 합니다. 학습률을 높게 설정해도 최적화가 잘 되기 때문이지요. 두 번째로 신경망을 가중치 초기화(Weight Initialization)나 하이퍼파라미터 설정에 대해 강건(Robust)하게 만들어줍니다. 즉, 이 값을 좀 더 자유롭게 설정해도 수렴이 잘 되지요. 마지막으로 오버피팅을 막아줍니다. 드롭아웃(Dropout)과 같은 스킬을 사용하지 않아도 모델이 일반화(Generalization)됩니다.

Normalization

신경망에 데이터를 넣을 때 입력값에 정규화를 해줍니다. 배치 정규화를 알아보기에 앞서 입력값을 정규화해주는 이유에 대해서 알아보겠습니다. 대부분의 데이터는 특성마다 가지는 값의 범위가 다릅니다.

단순한 예로 성인의 손뼘 길이와 신장의 연관 관계를 알아보기 위한 데이터를 가지고 있다고 해보겠습니다. 신장를 특성으로 하는 데이터는 대략 $[145, 210]$ 범위를 가질 것입니다. 나머지 특성인 손뼘 길이는 $[15, 30]$ 정도의 범위를 가지겠지요. 위처럼 대부분의 데이터는 특성값에 따라 다른 범위를 가지는데요. 데이터의 분포를 그려보면 아래 그림의 왼쪽 그래프처럼 그려지게 됩니다.

input_normalization

이미지 출처 : www.jeremyjordan.me

문제는 왼쪽처럼 생긴 데이터는 비효율적인 최적화 경로를 갖는다는 점입니다. 주로 편차가 큰 특성의 파라미터를 갱신하는 방향으로 학습이 진행되기 때문이지요. 상대적으로 적은 편차를 갖는 특성의 영향력은 줄어듭니다. 위 그림에서도 X축 특성의 값을 최적화하는 방향으로만 학습이 진행되고, Y축에 나타나는 특성값은 상대적으로 무시되는 것을 볼 수 있습니다.

입력값 정규화는 이런 문제를 해결하기 위해서 사용하는 방법입니다. 정규화는 특성마다의 범위를 동일하게 만들어줍니다. 이와 같이 범위가 비슷해지면 학습 과정에서 모든 특성에 대한 파라미터가 동일하게 개선되어 훨씬 더 효율적인 최적화 경로를 갖게 되지요.

ICS(Internal Covariate Shift)

위와 같이 입력값은 신경망에 들어가기 전에 적당하게 조정해 줄 수 있습니다. 하지만 신경망 내부에서 파라미터와의 연산을 통해 은닉층을 빠져나오는 값은 다른 분포를 나타냅니다. 은닉층마다 이런 현상이 생긴다면 학습이 제대로 이루어지지 않지요.

ics

이미지 출처 : imgur.com

이렇게 신경망 내부의 은닉층마다 입력되는 값의 분포가 달라지는 현상을 ICS(Internal covariate shift, 내부 공변량 변화)라고 합니다.

internal_covariate_shift

이미지 출처 : www.slideshare.net/ssuser950871

배치 정규화는 “ICS를 해결해주면 신경망의 성능이 훨씬 더 좋아지지 않을까?”라는 아이디어에서 시작되었습니다.

Batch Normalization

배치 정규화는 완전 연결층(Fully Connected Layer)과 활성화 함수 사이에 배치 정규화 층(Batch norm layer)을 하나 더 삽입합니다. 층이 추가된 후의 순서는 아래 이미지와 같습니다.

batch_norm_layer

이미지 출처 : stats.stackexchange.com

배치 정규화 층에서는 완전 연결 층에서 계산된 값을 미니배치 단위로 정규화 합니다. 미니배치 $B$ 의 사이즈가 $m$ 이라면 각 데이터의 평균 $\mu_B$ 와 분산 $\sigma_B^2$ 를 구하고 표준화(Standardization)을 수행하여 $\hat{x_i}$ 를 구합니다.

[\begin{aligned} \mu_B &\leftarrow \frac{1}{m} \sum_{i=1}^m x_i
\sigma_B^2 &\leftarrow \frac{1}{m} (x_i - \mu_B)^2
\hat{x_i} &\leftarrow \frac{x_i - \mu_B}{\sqrt{\sigma_B^2+\epsilon}} \end{aligned}]

위 식에서 $\epsilon$ 은 계산 안정성을 위한 매우 작은 상수입니다. 이렇게 계산된 값은 표준정규분포 $N(0,1)$ 를 나타냅니다. 하지만 여기서 끝나면 안됩니다. 표준정규분포에서는 $68.26\%$ 만큼이 $[-1,1]$ 범위에 있고, $95.44\%$ 의 값이 $[-2,2]$ 범위에 있습니다. 하지만 이 구간에서는 활성화 함수인 시그모이드 함수가 선형 함수에 근사한 형태를 가집니다.

sigmoid2

로지스틱 함수(Logistic function)y=0.24x + 0.5

tanh

하이퍼탄젠트 함수(Hypertangent function)y=0.9x

이곳에서 알아본 것처럼 활성화 함수로 선형 함수를 사용하게 되면 층을 깊게 쌓을 때의 이점이 사라집니다. 이런 문제를 해결하기 위해서 정규화한 값 $\hat{x_i}$ 을 적당이 조작해줍니다. 파라미터 $\gamma, \beta$ 를 각각 곱해주고 더해준 값 $y_i$ 를 활성화 함수에 입력하지요. 수식으로 나타낸 배치 정규화 층의 최종 출력값은 다음과 같습니다.

[y_i \leftarrow \gamma_j\hat{x_i} + \beta_j]

이 때 곱해지고 더해지는 파라미터 $\gamma, \beta$ 는 각 노드마다 다른 값이 적용됩니다. 특정 층의 노드가 64개라면 배치 정규화 층에도 파라미터가 각각 크만큼 있는 것이지요. $\gamma_j, \beta_j (j = 1, \cdots, 64)$ 가 됩니다. 이 때 $y$ 의 분포는 $N(\beta_j, \gamma_j^2)$ 이며 $\gamma_i, \beta_i$ 는 학습을 통해 결정됩니다. 배치 정규화의 계산 그래프는 아래와 같습니다.

batch_norm_graph

이미지 출처 : costapt.github.io

배치 정규화를 사용했을 때와 사용하지 않았을 때 학습 데이터셋과 검증 데이터셋에 대한 학습 결과는 아래와 같습니다.

effect

이미지 출처 : learnopencv.com

배치 정규화를 했을 때 훨씬 더 좋은 결과를 보여주는 것을 볼 수 있습니다.

However,

배치 정규화의 효과에 대해서는 의심할 바가 없습니다. 많은 모델이 배치 정규화를 통해서 좋은 성능을 보여왔습니다. 그런데 배치 정규화가 이렇게 좋은 성능을 보이는 이유가 정말 ICS를 해결해서일까요? 아니, 배치 정규화가 진짜로 ICS를 해결해주기는 하는 것일까요?

2018년에는 배치 정규화가 어떻게 최적화에 도움을 주는지에 대해 연구한 논문이 발표되었습니다. 논문에 따르면 배치 정규화가 ICS를 해결해주지도 못한다는 것이지요. 아래는 배치 정규화를 적용했을 때(오른쪽)와 적용하지 않았을 때(왼쪽), 3번째 층과 11번째 층에 들어오는 값의 분포를 시각화한 것입니다. 학습에 사용되는 미니배치마다 그래프를 그렸습니다.

batch_norm_layer_distribution

이미지 출처 : gradientscience.org

그림을 보면 둘 사이에 획기적인 변화가 없습니다. 3번째 층이든 11번째 층이든 배치 정규화를 사용했을 때와 그렇지 않았을 때 큰 차이가 없음을 볼 수 있지요. 논문 저자들은 배치 정규화를 적용한 뒤에 노이즈를 주어 일부러 분포를 흐트린 모델을 추가하여 실험해보기도 했습니다. 아래는 세 모델을 시각화한 결과입니다.

batch_norm_with_noisy

이미지 출처 : gradientscience.org

노이즈가 추가된 모델은 반복 스텝마다 매우 다른 분포를 보이고 있습니다. 그렇다면 세 모델의 성능은 각각 어떻게 될까요? 세 모델의 성능을 비교한 학습 그래프입니다.

comparison

이미지 출처 : gradientscience.org

노이즈가 추가된 모델은 ICS가 오히려 심해졌음에도 배치 정규화를 적용하지 않은 모델보다 훨씬 더 좋은 성능을 보였습니다. 논문을 통해 배치 정규화가 ICS를 해결하는지도 알 수 없고, ICS를 해결하는 것이 좋은 성능을 보장하는 것도 아님을 증명했습니다. 그렇다면 배치 정규화는 실질적으로 어떤 작용을하여 최적화에 어떤 도움을 가져다주는 것일까요?

Smoothing!

논문의 저자는 배치 정규화가 스무딩(Smoothing)을 만들어준다고 이야기하고 있습니다. 배치 정규화를 적용하지 않은 손실 함수가 왼쪽과 같이 생겼다면, 배치 정규화를 적용한 손실 함수는 오른쪽처럼 생겼다는 것이지요.

smoothing

이미지 출처 : Visualizing the Loss Landscape of Neural Nets

본 실험에서 손실 함수의 평면과 기울기를 나타낸 그래프입니다. 배치 정규화를 적용했을 때가 그렇지 않을 때보다 훨씬 더 완만한 경사를 가지는 것을 볼 수 있습니다.

landscape

이미지 출처 : gradientscience.org

결론은 배치 정규화가 좋은 성능을 보이는 이유가 ICS를 해결했기 때문이 아니라 스무딩 덕분이라는 것이지요. 마지막으로 배치 정규화의 장점을 다시 떠올려 보겠습니다. 첫 번째는 “학습률을 크게 설정할 수 있다.”, 두 번째는 “가중치 초기화에 덜 민감하다.”, 세 번째는 “모델이 잘 일반화되어 있다.”는 것이었습니다. 배치 정규화가 스무딩, 즉 복잡한 손실 함수의 평면을 부드럽게 만들어준다는 것을 알고 있다면 위와 같은 장점이 생김을 자연스레 이해할 수 있습니다. 배치 정규화는 여러 모델에 대해서 간단한 아이디어에도 좋은 성능을 보여주기 때문에 SOTA를 달성한 많은 모델에 쓰였던 기법입니다.

Comment  Read more

반복형 언패킹 (Iterable Unpacking)

|

아래 내용은 전문가를 위한 파이썬 - 루시나누 하말류(한빛미디어, 2016)을 참조하여 작성하였습니다. 예시 코드는 모두 직접 작성하였습니다. 아래 게시물과 관련된 파이썬 공식 문서는 PEP 3132 – Extended Iterable Unpacking 에서 확인하실 수 있습니다.

반복형 언패킹

파이썬에는 리스트, 튜플, 문자열 등 다양한 시퀀스(Seqeunce)가 있습니다. 이번 게시물에서는 시퀀스를 언패킹하는 반복형 언패킹(Iterable Unpacking)에 대해서 알아보겠습니다.

병렬 할당

병렬 할당(Pararell assignment)이란 시퀀스의 요소를 각 변수에 할당하는 것을 말합니다. 병렬 할당으로 리스트를 언패킹하는 아래의 코드를 보겠습니다.

>>> number_list = [1, 2, 5]
>>> a, b, c = number_list
>>> print(f"a : {a}, b : {b}, c : {c}")

a : 1, b : 2, c : 5

리스트의 각 값이 a,b,c 에 순서대로 할당된 것을 확인할 수 있습니다. 병렬 할당을 확장하면 변수 간 값을 교환하는 코드도 간단하게 나타낼 수 있습니다. 파이썬에서는 다음과 같이 한 줄로 두 변수의 값을 교환할 수 있습니다.

>>> x, y = y, x

꼭 두 변수의 값만 교환할 수 있는 것은 아닙니다. 이 방법을 사용해서 언패킹 했던 a,b,c 의 값을 바꾸어 보겠습니다.

>>> c, a, b = a, b, c
>>> print(f"a : {a}, b : {b}, c : {c}")

a : 2, b : 5, c : 1

세 변수의 값이 할당 해준대로 (c = a, a = b, b = c) 잘 바뀐 것을 확인할 수 있습니다.

병렬 할당은 반복문에서도 자주 사용됩니다. 병렬 할당을 사용하여 요소가 튜플 (idx, prime_num)idx 번째 소수 prime_num 을 리스트를 idx, prime_num을 각각 key, value 로 갖는 딕셔너리로 만들 수 있습니다.

>>> prime_idx_dict = {}
>>>
>>> for idx, prime_num in prime_number_list:
>>>    prime_idx_dict[idx] = prime_num
>>>
>>> prime_idx_dict

{1: 2, 2: 3, 3: 5, 4: 7, 5: 11, 6: 13, 7: 17, 8: 19}

초과된 항목을 가져오는 *(Asterisk)

함수를 선언할 때 초과되는 파라미터(parameter)를 *args 로 나타내듯 파이썬에서는 *(Asterisk)를 붙여 초과된 인수를 가져올 수 있습니다. 이 방법을 사용하면 시퀀스를 좀 더 다양하게 언패킹 할 수 있습니다.

>>> first, second, *others = (1, 2, 3, 4, 5)
>>> print(f"first : {first}, second : {second}, others : {others}")

first : 1, second : 2, others : [3, 4, 5]

Asterisk는 시퀀스의 마지막 부분 뿐만 아니라 앞부분과 가운데 부분도 가져올 수 있습니다. 아래의 코드를 보겠습니다.

# 앞부분 가져오기
>>> *others, last = ('a', 'b', 'c', 'd', 'e')
>>> print(f"others : {others}, last : {last}")

others : ['a', 'b', 'c', 'd'], last : e

# 가운데 부분 가져오기
>>> first, second, *others, last = ('u', 'w', 'x', 'y', 'z')
>>> print(f"first : {first}, second : {second}, others : {others}, last : {last}")

first : u, second : w, others : ['x', 'y'], last : z

가져와 주기로 지정했던 first, second, last 를 제외한 나머지 요소가 others 에 리스트로 할당된 것을 확인할 수 있습니다. 만약 요소가 초과하여 할당될 요소가 없는 경우에는 빈 리스트를 반환합니다.

# 예시 1
>>> first, second, *others = (1, 2)
>>> print(f"first : {first}, second : {second}, others : {others}")

first : 1, second : 2, others : []

            
# 예시 2
>>> first, second, *others, last = ('x', 'y', 'z')
>>> print(f"first : {first}, second : {second}, others : {others}, last : {last}")

first : x, second : y, others : [], last : z

이 방법의 한계는 오직 하나의 변수에만 *를 사용할 수 있다는 점입니다. 아래의 코드를 보겠습니다.

>>> first, *others_first, fifth, sixth, *others_second = (2, 3, 5, 7, 11 ,13 ,17, 19)

'SyntaxError: two starred expressions in assignment'

위와 같이 “2개의 asterisk를 할당에 사용하지 말라”는 메시지의 SyntaxError 가 발생하는 것을 확인할 수 있습니다.

내포된 시퀀스 언패킹하기

파이썬에서는 내포된 시퀀스도 언패킹 할 수 있습니다. 말로만 설명하면 이해하기 어려우니 아래의 예시 코드를 보겠습니다. 내포된 리스트의 요소를 언패킹하는 코드입니다.

>>> language, version, [first_data_type, second_data_type, third_data_type]  = ('python', '3.6,9', ['int', 'float', 'string'])
>>> print(f"first_data_type : {first_data_type}, first_data_type : {second_data_type}, third_data_type : {third_data_type}")

first_data_type : int, first_data_type : float, third_data_type : string

내포된 리스트의 요소가 제대로 언패킹 된 것을 볼 수 있습니다. 이 때 [first_data_type, second_data_type, third_data_type] 에서 리스트를 나타내는 [] 를 제거하면 어떻게 될까요? 아래와 같은 코드를 작성하여 보겠습니다.

>>> language, version, first_data_type, second_data_type, third_data_type  = ('python', '3.6,9', ['int', 'float', 'string'])

'ValueError: not enough values to unpack (expected 5, got 3)'

위와 같이 ValueError가 뜨는 것을 알 수 있습니다.

내포된 시퀀스 언패킹 방법을 확장하면 3중으로 내포된 시퀀스도 언패킹 할 수 있습니다. 아래의 코드를 실행해 보겠습니다.

>>> language, version, (first_type, second_type, third_type, (fourth_type, fifth_type)) = ('python', '3.6,9', ('int', 'float', 'string', ('list', 'tuple')))
>>> print(f"first_data_type : {first_data_type}, first_data_type : {second_data_type}, third_data_type : {third_data_type}, fourth_type : {fourth_type}, fifth_type : {fifth_type}")

first_data_type : int, first_data_type : float, third_data_type : string, fourth_type : list, fifth_type : tuple

제대로 언패킹되는 것을 확인할 수 있습니다.

Comment  Read more

2021 계획

|

Plan. 2021

2021년에는 개발이나 자연어를 공부하는 분량은 아마 좀 줄어들지 않을까합니다. 아무래도 기획자로서 일을 하고 있고, 이쪽 분야는 취미로서만 다루고 있다 보니 작년에 비해 공부량은 좀 줄어들지 않을까합니다.

Python

이것저것 공부하다보면 개발 언어에 대한 공부량을 많이 가져갈 수는 없을 듯 합니다. 하지만 파이썬은 개발뿐만 아니라 데이터분석에서도 강력한 언어이기 때문에 파이썬을 좀 더 잘 다루어보려고 합니다.

Book

  • 처음 시작하는 파이썬 : 초보자를 위한 책이지만 워낙 넓은 범위를 다루고 있는 책이기 때문에 책을 다시 한 번 보려고 합니다. 기본적인 문법 이외에 웹에 관련된 파트, 시스템이나 병행성을 다루고 있는 부분에 대해서는 아직도 모르는게 많습니다. 그렇기 때문에 처음부터 끝까지 책을 보면서 기초를 좀 더 다져보고자 합니다.
  • 파이썬 코딩의 기술 : 이번에 2판이 나오면서 내용이 좀 더 풍부해진 파이썬 코딩의 기술입니다. 여전히 모르는 부분이 많고 보지 않을 수 없는 책입니다.
  • 전문가를 위한 파이썬 : 물론 이 책을 처음부터 끝까지 다 보기에는 무리가 있습니다. 하지만 아래에 있는 강의나 위에 있는 책을 보면서 부족한 부분에 대한 세부적인 내용을 채우는 사전으로 사용할 생각입니다.
  • 파이썬 라이브러리를 활용한 데이터 분석 : 데이터 분석을 위해서는 넘파이 혹은 판다스에 대한 이해가 필수적인데 아직 모자른 부분이 많아 해당 책을 보며 채워가려고 합니다.
  • (위키독스)점프 투 장고 : 2020년 프로젝트를 할 당시에는 플라스크를 사용했었는데 이번에는 장고를 공부해보려고 합니다. 아래에 있는 장고 강의와 병행하며 사전식으로 볼 예정입니다.

Lecture

  • 프로그래밍, 데이터 과학을 위한 파이썬 : 제 파이썬 첫걸음을 함께한 최성철 교수님의 강의입니다. 처음 시작하는 파이썬을 보며 잘 모르는 내용에서 겹치는 부분이 있다면 다시 볼 생각입니다.
  • 우리를 위한 프로그래밍 : 파이썬 중급 : 인프런 오리지널 파이썬 중급 강의입니다. 초급 강좌에서 다루지 않았던 클래스의 심화적인 내용이나 병행성 등에 대해서 공부하고자 합니다.
  • 작정하고 장고 : 유튜브에 있는 장고 강의입니다. Pinterest를 클론하며 장고와 이를 서빙하는데 필요한 기술을 다룹니다. 1월부터는 유료 강의가 된다고 하여 빨리 볼 생각입니다.
  • 데이터 구조 및 분석(선택) : 지난번에 들었던 자료구조 강의의 후속강의 입니다. 고급 자료구조형이나 유전알고리즘, 네트워크 등에 대해 다룹니다. 나중에 기억하기 위해 공부하기 위해 기록은 해놓고는 있지만 일단은 못 볼 확률이 높아 (선택)을 붙였습니다.

Math

수학은 선형대수학과 통계를 다시 복습하려고 합니다.

Book

  • 김도형의 데이터 사이언스 스쿨 : 수학 편 : 다양한 수학적 지식을 다루고 이를 파이썬 라이브러리를 통해서 실제로 계산해볼 수 있는 예제를 주는 책입니다. 데이터 분석을 하면서 필요한 부분을 해당 책을 보면서 톺아보려고 합니다.
  • 데이터 과학을 위한 통계 : 오라일리의 통계 꽃게 책입니다. 기초 통계에 대한 내용이 조금 있어 공부방향을 잡는 데에 사용하려고 합니다.

Lecture

  • 수리통계학 : KOCW에 있는 부산대학교 김충락 교수님의 수리통계학입니다. 현재도 듣고 있으며 아직 못들은 부분이 많아 지속적으로 들을 예정입니다. 아마 2학기 수업 내용인 수리통계학2가 올라오면 계속 이어서 듣지 않을까 합니다.

ML/DL

Lecture

  • 인공지능 및 기계학습 개론 2 : PRML의 뒷부분을 담당하고 있는 강의입니다. 통계학을 조금 공부했으니 이전보다 어렵지 않게 공부할 수 있을 듯 하여 목표 리스트에 올려보았습니다.
  • Business Analytics : 차원 축소 이후 부분을 미뤄두고 있습니다. 새해에는 부디 나머지 부분도 다 공부할 수 있기를 바라봅니다.

NLP

Book

Study

  • 집현전 : 자연어처리 논문 모임인 집현전입니다. 매주 한 번씩 논문을 보면서 기존에 부족했던 부분에 대한 내용을 채워넣고, 최신 논문에서는 어떤 문제를 다루고 있는지 따라가보려고 합니다.

Comment  Read more

2020년 돌아보기

|

2020년 돌아보기

어릴 적 만화영화나 SF영화에나 나올 것 같던 2020년을 맞이했습니다. 물론 2020년의 첫 해가 뜬지 2주만에 코로나가 퍼지는 바람에 이번 해는 그 어떤 SF보다도 픽션같은 한 해가 되었지만요. 그래도 시간은 흘러흘러 어느 새 이번 년도도 끝을 바라보고 있습니다. 개인적으로도 많은 변화가 있었던 해였습니다. 블로그를 시작한 것도 올해고요. 월 별로 어떤 일을 했는지 간단히 적어보고 올 해에 대한 짧은 감상을 남기려 합니다.

2020. Jan

  • 파이썬 공부하기 : 일기를 뒤져보니 파이썬을 열심히 공부했던 기록이 있네요. 당시에 국비지원 과정에서 웹 크롤러 만들기를 해서 평소에 크롤링 해보고 싶었던 알라딘 중고매장 페이지를 긁어봤습니다. 3월에 했던 프로젝트의 초석이 되기도 했네요. 그리고 학원 내에서 자체적으로 파이썬 코테 스터디가 있어서 프로그래머스 문제를 열심히 풀었습니다.
  • 블로그 개설 : 설날 연휴를 맞이하여 블로그를 개설했습니다. 몇 번 언급했지만 자연어처리로 너무나도 유명하신 Ratsgo님의 블로그를 허락 후에 포크하였습니다. 공부한 내용에 대해 줄줄 써야 머리에 남는 타입이라 지금까지 즐겁게 쓰고 있습니다.
  • 지금은 기획일을 하고 있습니다만 이 때는 아직 개발자의 꿈을 꾸었던 듯 하네요. OS랑 데이터 엔지니어링 공부해야 된다고 구석에 써놓은 걸 보니.

2020. Feb

  • Learning, Machine Learning : 직접 구매했던 핸즈온 머신러닝과 학원 교재였던 파이썬 머신러닝 완벽 가이드를 바탕으로 머신러닝 공부를 열심히 했습니다. 당시에는 이정도로 심각성을 못느껴서 코로나 시국에 집도 안가고 ICT COC에서 잠자고 헬스장에서 씻으면서 공부만 했네요.
  • 추가적으로는 코테 문제를 계속 풀면서 선형대수 등을 공부했습니다. 그리고 데이콘에서 있었던 ‘국민은행 스미싱 분류’ 시상식에도 다녀왔습니다. 배경지식이 없는 상태에서 가긴 했지만 얉게나마 자연어를 어떻게 다뤄야 하는 지에 대해 볼 수 있었던 경험이 되었습니다.

2020. Mar

  • 알라딘 중고서점 알리미 프로젝트 : 코로나로 국비 과정도 중단되었기에 할 만한 것을 찾다가 학원에서 같이 공부하던 형과 프로젝트를 시작했습니다. 중고서적을 사모으는 게 취미였던 저는 매번 10개 가량의 검색어를 머리에 넣어놓고 검색하곤 했는데요. 이게 귀찮아서 일정 시각에 알림이 오는 서비스를 만들었습니다. 가볍게 헤로쿠로 돌리는 거라 성능이 좋거나 하진 않습니다만 지금도 잘 쓰고 있습니다.

  • 갑자기 다닐 곳이 제한되다 보니 플젝하면서 슬럼프에 빠지기도 했는데요. 같이 했던 형 덕분에 잘 마칠 수 있었습니다.

2020. Apr

  • 잠깐의 잡일 : 알고 지내던 형이 대표로 있는 회사에서 아르바이트 식으로 일을 했습니다. 지금 다니고 있는 회사이기도 하고요. 플젝 마치고 조금 답답했었는데 몸을 이끌고 나올 곳이 생겨 좋았습니다.
  • 최종 플젝 주제를 정하자 : 이 때부터 최종 플젝 주제를 정하기 시작했습니다. 이 이후로 한 달을 주제 선정하는 데만 시간을 쏟았지만요. 주제 선정, 그리고 그에 수반되는 데이터 구하기는 플젝에서 가장 어려운 난관 중 하나라는 생각이 한 번 더 들었습니다.

2020. May

  • 주제 확정 : 한 달 간의 알바도 끝나고 최종 프로젝트 주제도 확정했습니다. 5월의 시작과 함께 코로나 때문에 강의장이 경복궁쪽으로 옮겨졌던 기억이 있네요. 이 때의 기억이라곤 KoGPT2 어떻게 좀 써보겠다고 크롤링한 데이터 전처리한 기억밖에 나질 않네요. Tmi로 날씨가 참 좋았었습니다.

2020. Jun

  • 자소서 작성 도우미 프로그램 : 6월 초에 대략적인 프로젝트를 마치고 발표자료를 만든 뒤 12일 최종 발표를 끝으로 국비과정이 마무리되었습니다. 같이 노력해준 조원들 덕분에 재밌는 프로젝트를 할 수 있었습니다. 성적이 무슨 의미가 있는지는 모르겠지만 아무튼 등수(1등)도 좋았고요. 이 자리를 빌어 2달 간 고생해준 조원에게 감사를 드립니다.
  • 교육 과정이 끝나고 나니 이런 저런 생각을 많이 하게 되었습니다. 이후에 뭘 해먹고 살 지에 대해서요. 고민 끝에 개발자보다는 기획자가 되기로 했습니다. 여러 가지를 고려해 봤을 때 제가 하고 싶은 일에 기획자가 가장 가깝더라고요. 저랑 가장 맞기도 했고요. 머신러닝과 자연어는 일단 취미이자 강점으로 남겨두기로 했습니다.

2020. Jul

  • 텍스트 분석 강의 : 7월에는 텍스트 분석을 완강하였습니다. KoGPT2 프로젝트를 할 때는 “GPT만이라도 알아보자!”라는 생각으로 중간을 뛰어넘었던지라 중간 과정을 채우기 위해 처음부터 끝까지 들었지요. 지금 알고있는 자연어처리에 대한 지식도 이 강의로부터 알게 된 게 거의 전부입니다. 감성 분석을 정리한 글은 블로그 방문자의 1/3 이상을 맞이하고 있기도 하고요. 자연어를 취미로 이어나가는 데 가장 많은 도움이 되었던 강의입니다.
  • 면접 : 자연어처리 기술을 다루는 스타트업에서 기술 기획 직무를 채용하고 있길래 무턱대고 지원했는데 서류를 잘 봐주셔서 면접까지 가볼 수 있었습니다. 과제를 해결하는 과정이 꽤 재밌었던 기억이 있네요.

2020. Aug

  • 블로그 글 다시쓰기 : 블로그에 글이 한 70개 가량 쌓였는데 틀린 내용도 많고 대충 적은 내용들이 많아서 복습도 할 겸 블로그 글을 거의 처음부터 다시 작성했습니다. 지금도 틀린 내용이 중간중간 있긴 합니다마는 이 때 다시 작성했던 글은 그래도 조금 읽을만한 수준이 되었네요.
  • 스터디 : 이런저런 스터디를 했습니다. 부스트코스에서 하는 CS50 스터디에 조장으로 참가했고, 팀원 모두 무사히 수료했습니다. 짧은 기간이었지만 이전에 파이썬으로 자료구조 공부하면서 애매했던 부분을 다시 공부할 수 있었습니다. 추가적으로 3/4분기 회고를 뒤져보니 강의 자료 번역 작업도 했었네요.

2020. Sep

  • 일 시작 : 늦은 나이에 첫 일을 시작했습니다. 창업하겠다고 돌아다니다 보니 이제 와서야 첫 일을 시작했네요. 사실 11월 까지는 급히 처리해야하는 플젝이 있어서 그 일을 했습니다. 기획과는 별 상관이 없었지만 사전에 합의된 부분이라서 나름 재밌게 했습니다.

2020. Oct

  • 일일일 : 끝내야 하는 플젝이 있어서 거의 일만 했던 시기네요. 아래 있는 풀잎을 제외하고는 내내 일만 했습니다. 아마 플젝이 끝나는 11월 13일까지 5주 동안 5일 정도 제외하고 매일 출근한 듯하네요.

  • 수리통계학 풀잎 : 모두의 연구소 풀잎스쿨에서 수리통계학을 공부했습니다. 다만 이 때는 쉬웠는데 점점 어려워져 12월에는 거의 이해하지 못하는 불상사가… 수리통계학 그렇게 어려울 줄 (이때는 특히 더) 몰랐습니다 ㅠㅠ

2020. Nov

  • 플젝 끝, 그리고 휴식 기간 : 13일까지 플젝이 끝나고 제주도에 가서 2주 동안 쉬었습니다. 책방 투어도 하고요. 앞으로 뭘 해야할 지에 대해서도 정리할 수 있는 시간이 되었습니다.
  • 간만에 판다스 : 휴식 기간동안 다른 일이 들어와서 잠깐 외주 일을 했습니다. 나눠진 파일을 하나의 장표로 취합하는 거였는데 간만에 판다스 이용해서 코드 짰더니 재밌더라고요. 중간마다 포맷을 마음대로 낸 파일이 “꽤” 많아서 짜증나긴 했습니다만… 그런 빌런은 결국 수기로 처리했습니다 ㅠㅠ 데이터 품질의 중요성을 새삼 느끼게 된 계기가 되었습니다.

2020. Dec

  • 서비스 기획 : 휴식이 끝나고부터는 자체 서비스 론칭을 위해 열심히 기획을 하고 있습니다. 구조상 애자일한 방식으로 진행되지는 않습니다만 나름대로 재미있게 하고 있네요. 뭔가를 만드는 것은 언제나 재미있는 일입니다. 아마 크리스마스 때도 회사를 나가는 불상사(?)가 있을 예정이지만 재미있으면 그만입니다 :)
  • 자연어 논문 읽기 모임 집현전 시작 : 자연어 관련 오픈 톡방에서 논문 읽기 모임을 시작해서 참여하게 되었습니다. 강의로 공부를 했다보니 중간중간 빠뜨리게 되는 지식이 많았습니다. 이런 부분을 논문을 읽어가며 채우기 위해 논문 읽기 모임에 참여하게 되었습니다. 저는 초급반으로 참여하게 되었고 매주 주말마다 즐겁게 참여하고 있습니다.
  • 글쓰기 : 금요일마다 글쓰는 계정을 따로 만들었습니다. 예전에 브런치를 만들어 놓고도 (심지어 작가 한 방에 통과했는데) 아무런 글도 안쓰는 계정이 있었는데요. 이번에 금요일마다 그곳과 인스타에 글을 올리기로 했습니다.
  • 브랜딩이라고 하기에는 애매합니다마는 커스텀 도메인을 사용한 노션 페이지와 개인 명함을 만들었습니다. 원래부터 하고 싶기도 했거나와 새해에는 제 삶에서 ‘나’의 비중을 좀 더 높여보고자 연말에 맞추어 결행(?)했네요.
  • 마지막으로 30일 누적 블로그 방문자가 1000명을 넘겼습니다. 감성분석 덕분에 달성할 수 있었고 다른 글도 검색순위 잘 걸렸으면 좋겠네요. 날 잡고 SEO를 손봐야 하려나…

over1000

모두에게 힘든 한 해였지만 제게는 나름대로 의미있었던 한 해였습니다. 그만큼 변화도 많았고요. 어려운 상황에서도 주변 사람들 덕분에 계속해서 나아갈 수 있었습니다. 이 자리를 빌어 제 블로그를 읽어주시는 모든 분들과 주변 사람에게 감사의 말씀을 전합니다. 다음 주에 공부 계획으로 다시 찾아오겠습니다.

Comment  Read more