분류 전체보기 (312)

반응형




Cookiecutter 패키지는 프로젝트 템플릿을 쉽게 생성해주는 파이썬 패키지입니다. 1) 자신이 만든 템플릿을 저장해서 reproducible 하게 사용할 수 있고, 2) 이미 만들어져 있는 템플릿을 불러와서 거기서부터 새로 프로젝트를 생성할 수 있습니다. 특히, cookiecutter-pypackage/ 를 많이 사용하는듯합니다. 이 템플릿은 PyPI 등록을 위한 파이썬 패키지를 위한 템플릿을 제공합니다. 기본적인 PyPI 등록을 위한 패키지 구조와 기본 파일 (setup.py 등), nox, tox, Click, travis 등과 같은 파이썬 패키지 관련 코드를 담은 파일이 탑재되어 있기 때문에 패키지 개발의 start point 로서 유용하고 실제로 많이 사용하고 있는 패키지입니다. 


homepage

https://cookiecutter.readthedocs.io


tutorial

https://cookiecutter.readthedocs.io/en/latest/tutorial1.html

https://cookiecutter-pypackage.readthedocs.io/en/latest/tutorial.html

반응형
반응형


다른 컴퓨터로 conda 가상환경 옮기는 방법


참고

conda-cheatsheet.pdf


기존에 사용하던 컴퓨터 A 에서 컴퓨터 B 로 conda 가상환경을 옮겨야할 때가 있다. 


컴퓨터 A 에서 해야할 일 


1. 가상환경 켜기


source activate [이름]


2. 가상환경이 켜진 상태에서 아래 명령어로 dependency 를 export 할수 있다.


conda env export > environment.yaml

environment.yaml 파일을 열어보면 아래와 같이 잘 export 되었다는 것을 확인할 수 있다. 



3. 현재 환경의 python 버전 체크


현재 사용하고 있는 가상환경에서 사용하고 있는 python version 을 체크한다. 


python --version
Python 3.6.6


컴퓨터 B 에서 해야할 일 


Requirements! 

  • 컴퓨터 B 에서는 컴퓨터 A 에서와 같은 anaconda (python 2 또는 python3) 를 사용해야한다. 만약 anaconda 버전이 하위버전이면 잘 안돌아갈 수도 있을듯 하다. 

4. 가상환경 생성 


conda create --name [이름] python=3.6


5. prefix 변경


environment.yaml 을 열고 원하는 경우, 가상 환경의 이름을 바꾸고, prefix 를 경로에 맞게 바꾸어준다. 예를 들어, 


prefix: C:\Users\[사용자이름] \Anaconda3\envs\[가상환경이름]


5. yaml 파일을 통한 가상환경 생성 


conda env create --file environment.yaml


이 때, 


Solving environment: failed

ResolvePackageNotFound:


에러가 뜰 수 있다. 이것은 A 컴퓨터에서 설치된 라이브러리가 B 컴퓨터에서 설치가 불가능한 것인데, 컴퓨터의 운영체제가 다른 경우에 발생하는 것으로 보인다. 해결 방법은 수동으로 ResoevePackageNotFound 에서 출력된 리스트를 environment.yaml 파일에서 지운 후, 다시 시도하면 된다. (참고)



6. 주피터를 사용하는 경우, 커널에 가상환경 등록


source activate myenv python -m ipykernel install --user --name myenv --display-name "Python (myenv)"


반응형
반응형

Django REST Framework



최근 tensorflow/keras 기반의 파이썬 어플리케이션을 코드를 공개하지 않으면서 서비스하기 위한 방향을 고민하던 도중, Web API 를 이용하면 좋을 것이라는 생각이 들었다. 찾아보니 Django REST Framework 라고 하는 Django 기반 프레임워크를 통해 이러한 Web API 를 간단하게 구현할 수 있는 것 같다. 


Django REST Framework 는 Django 기반의 Web API 개발을 위한 Framework이다. 홈페이지에 있는 튜토리얼을 따라하면 다음과 같이 간단한 정보를 요청하고 받아오는 간단한 샘플 어플리케이션을 만들어볼 수 있다. 


일반적인 application 의 경우, json 을 통해 정형화된 데이터를 주고 받으면 되겠지만, 딥러닝을 기반으로한 어플리케이션이니만큼 파일이나 numpy array 와 같은 json 이 아닌 타입의 데이터를 어떻게 전송할 수 있는지를 조사해보는 게 필요해보인다. 개/고양이 이미지  사진을 전달하고 분류 결과를 출력하는 정도의 간단한 앱을 만들고자해도, 파일 및 numpy array 의 전송이 필수적일 것이기 때문이다. 우선 홈페이지에 튜토리얼을 살펴보면서 차근차근 이 프레임워크를 공부해나갈 예정이다. 혹시 Tensorflow/keras/pytorch 기반 appilcation을 서비스하고자 하는 데이터과학자/개발자라면 유용하게 사용할 수 있을 것 같다! 


반응형
반응형


Cross-entropy 의 이해: 정보이론과의 관계



1. 손실함수로서의 Cross-entropy


딥러닝에서 분류 모델에 대한 손실 함수로 cross-entropy 혹은 binary entropy 나 log loss 라는 것을 사용하게 된다. 손실함수로서의 cross-entropy 는 아래 식으로 계산할 수 있다. 

$$ - \frac{1}{n} \sum_{i=1}^{n} \sum_{c=1}^{C} L_{ic}log(P_{ic}) $$ 

이 때, 

  • n = 데이터 갯수
  • C = 범주 갯수
  • L = 실제 값 (주로 0 또는 1)
  • P = 실제 값에 대한 확률 값 (0~1)  

만약 k = 3 이면 L_1 = [0, 0, 1] P_1 = [0.1, 0.2, 0.7] 과 같이 정의 될 수 있다. 이 때, 해당 데이터 포인트 (1) 에서 cross entropy 는 0*log(0.1) + 0*log(0.2) + 1*log(0.7) = -log(0.7) = 0.35 이다. 만약 L_2 = [0, 0, 1] P_2 = [0.5, 0.3, 0.2] 라면, 예측 모델은 상당히 잘못 예측했다는 것을 알 수 있고, 이 데이터 포인트 (2) 에서의 cross-entropy 는 -log(0.2) = 1.6 이다. 


딥러닝을 통한 예측 모델링에 있어, 실제 값과 예측값의 차이 (dissimilarity) 계산한다는 관점에서 cross-entropy 사용하는 것의 의미를 직관적으로 이해할 수 있다. 하지만 본 포스팅에서 이러한 식이 나오게 된 배경을 정보 이론 (Information theory) 을 기반으로 알아보려고한다. 


2. entropy 란 무엇인가?


entropy 란 불확실성 (uncertainty) 에 대한 척도이다. 결국 예측 모형으로 하고자 하는 것은 불확실성을 제어하고자 하는 것이다. 가방 안에 빨간공만 들어있다고 하자. 이 경우, 불확실성은 없다. 왜냐하면 어떤공을 꺼내도 빨간 공이기 때문이다. 따라서 이 경우 entropy 는 0이다. 우리가 신경써야하는 부분은 가방 안에서 꺼내는 공에 불확실성이 있는 경우이다. 


만약, 어떠한 사건이 같은 비율로 발생한다고 하고, 사건의 갯수를 n이라고 하면 entropy 는 log(n) 이다. 예를 들어, 가방 안에 빨간공과 녹색 공이 50:50으로 들어있다면 이 경우 entropy 는 log(2)=0.69 이다. 두 색깔의 공만 들어있는 경우, 50:50 으로 들어있을 때, 가장 entropy (불확실성) 이 크다. 이를 직관적으로 이해하면, 우리가 공을 꺼낼 때, 반반으로 들어있다면, 어떤 공이 더 자주 관찰될지 예측할 수 없기 때문에 entropy 가 크다고 이해할 수 있다.


하지만 일반적으로 가방 안에 각기 다른색의 공들이 다른 비율로 들어있는 경우가 많을 것이다. 이 때는 위와 같은 공식으로 구할 수 없으며, entropy 를 아래와 같은 식으로 구하게 된다. 

$$ H(q) = -\sum_{c=1}^{C} q(y_c)log(q(y_c)) $$ 


이 때, C는 범주의 갯수이고, q는 사건의 확률질량함수 (probability mass function) 이다. 예를 들어, 가방 안에 빨간공과 녹색공이 20:80 으로 들어있는 경우, H(q)=-(0.2log(0.2)+0.8log(0.8))=0.5 이다. 더욱 쉬운 이해를 위해 가방에서 공을 꺼낼 때, 더 많은 경우의 수가 존재한다고 해보자. 가령 100개의 각기 다른 색깔과 모양의 공이 가방 안에 들어있다. 이 경우, 가방에서 공을 꺼냈을 때 어떤 색과 모양을 갖는 공이 관찰될지 알기 매우 힘들다. 각 공이 동일한 확률로 관찰된다고 가정할 때 entropy = log(100) = 4.6 이다. 하지만 100개의 공이 들어있다고 하더라도, 한 종류의 공이 99 %를 차지하고 있으면 어떨까? 이 경우, 위 식에 의해 entropy는 매우 작아진다 (-(0.99*log(0.99)+99*(0.01/99*log(0.01/99))) = 0.1). 즉, entropy 는 예측하기 쉬운 일에서보다, 예측하기 힘든일에서 더 높다. 


3. Cross-entropy 


예측 모형은 실제 분포인 q 를 모르고, 모델링을 하여 q 분포를 예측하고자 하는 것이다. 예측 모델링을 통해 구한 분포를 p(x) 라고 해보자. 실제 분포인 q를 예측하는 p 분포를 만들었을 때, 이 때 cross-entropy 는 아래와 같이 정의된다. 

$$ H_p(q) = -\sum_{c=1}^{C} q(y_c)log(p(y_c)) $$ 


이 때, q와 p가 모두 식에 들어가기 때문에, cross-entropy 라는 이름이 붙었다고 할 수 있다. 머신러닝을 통한 예측 모형에서 훈련 데이터에서는 실제 분포인 p 를 알 수 있기 때문에 cross-entropy 를 계산할 수 있다. 즉, 훈련 데이터를 사용한 예측 모형에서 cross-entropy 는 실제 값과 예측값의 차이 (dissimilarity) 를 계산하는데 사용할 수 있다는 것이다. 또한, Cross-entropy > entropy 이다. 


예를 들어, 가방에 0.8/0.1/0.1 의 비율로, 빨간/녹색/노랑 공이 들어가 있다고 하자, 하지만 직감에는 0.2/0.2/0.6의 비율로 들어가 있을 것 같다. 이 때, entropy 와 cross-entropy 는 아래와 같이 계산된다. 


$$ H(q) = -[0.8log(0.8) + 0.1log(0.1) + 0.1log(0.1)] = 0.63 $$

$$ H_p(q) = -[0.8log(0.2) + 0.1log(0.2) + 0.1log(0.6)] = 1.50 $$


4. Kullback-Leibler Divergence


 “KL Divergence” 라고 주로 부르는 서로 다른 두 분포의 차이 (dissimilarity) 를 측정하는데 쓰이는 measure 이다. 이를 entropy 와 cross-entropy 개념에 대입하면 두 entropy 의 차이로 계산된다. KL Divergence 의 정의는 아래와 같다 (아래 정의는 p와 q가 이산분포일 때 정의되는 것이며, 연속 분포일 때는 sum 대신 integral 이 들어갈 것임을 예상해볼 수 있다.). 두 분포, q (실제)와 p (예측)가 있을 때, 


$$ D_{KL}(q||p) = -\sum_{c=1}^{C} q(y_c) [log(p(y_c)) - log(q(y_c))] = H_p(q) - H(q) $$ 


cross-entropy = H_p(q) 는 실제 entropy = H(q) 보다 항상 크기 때문에 KL Divergence 는 항상 0보다 큰 값을 갖게된다. 예측 분포인 p 를 실제분포 q에 가깝게 하는 것이, 예측모형이 하고자하는 것이며, p가 q에 가까이갈 수록 KL Divergence 0에 가까워질 것이다. 그리고 H(q) 는 고정이기 때문에, H_p(q)를 최소화 시키는 것이 예측 모형을 최적화 시키는 것이라고 할 수 있다. 따라서 cross-entropy 를 최소화 시키는 것이 KL Divergenece 를 최소화 시키는 것이며, 이것이 불확실성을 제어하고자하는 예측모형의 실질적인 목적이라고 볼 수 있다. 


5. Cross-entropy 를 통한 loss function 


예를 들어, 이미지를 읽어들여 개/고양이/물고기를 분류하는 3개의 클래스를 갖는 다중 분류 문제를 생각해보자. 가방에 개/고양이/물고기라고 쓰인 공이 들어있다. 이 공은 해당 이미지에 대한 정답을 사람이 적어 놓은 것이다. 예측 모형은 주어진 정보 (이미지) 를 살펴본 후, 예측 분포를 산출했는데, p(y) = [0.2, 0.3, 0.5] 으로 예측했다. 즉, 공 (실제 정답) 을 꺼냈을 때, 개/고양이/물고기를 관찰할 확률이 각각 0.2/0.3/0.5 일 것이라고 예측 한 것이다. 하지만 실제 분포, q(y) = [0, 0, 1] 이다. 이 때, cross-entropy 는 매우 간단하게, -log(0.5) 이다.


2에서 예로 든, 빨간공 녹색공 예제와 다른점은, 빨간공 녹색공 예제에서는 공이 어떠한 확률질량함수를 갖고 가방 안에 들어있을 것이라고 가정한 것이지만, 현실의 분류 문제에서는 정답이 있다고 가정하고 하기 때문에 (즉, 공을 꺼낼 때 관찰하는 것이 100 % 정해져 있다.), 실제 분포인 q(y)가 [0,0,1], [1,0,0] .. 과 같은 one-hot encoding 된 벡터로 나타내어진다는 것이다. 왜냐하면 실제 이미지가 0.2 의 확률로 개일 수는 없다. 왜냐하면 그 이미지가 개라는 것이 "정답" 이라고 사람이 정의했기 때문이다. 즉, 어떠한 이미지가 무엇이냐는 것은 확률적이지 않다는 것이기 때문에 실제 분포의 entropy = H(q) = 0 이다. 하지만 cross-entropy 는 p와 q에서 정의되는 것이므로 구할 수 있다. 실제 분포의 entropy 가 0이기 때문에, cross-entropy = KL(q||p) 이다. 


이 경우, p와 q의 cross-entropy 는 실제로 아래와 같이 계산된다. 

$$ -\sum_{c=1}^{C} L_{c}log(P_{c}) $$  

$$ L_{c} = q(y_c)  $$

$$ P_{c} = p(y_c) $$ 


그리고 n 개의 데이터포인트에 대해 cross-entropy 의 평균을 구하는 것이 아래의 식이다. 

$$ - \frac{1}{n} \sum_{i=1}^{n} \sum_{c=1}^{C} L_{ic}log(P_{ic}) $$ 


지금까지 손실함수로 cross-entropy 를 사용한다는 것이 무엇을 의미하는 것인지, entropy 를 기반으로 설명하였다. 손실함수로서의 cross-entropy 를 정보 이론의 관점, entropy 의 관점에서 이러한 관련성을 갖고 있다는 것을 이해하는데 도움이 되었으면 한다.  


참고

https://towardsdatascience.com/understanding-binary-cross-entropy-log-loss-a-visual-explanation-a3ac6025181a 


반응형
반응형


Jupyter 유용한 확장기능 - lab_black


설치


pip install nb_black


사용법


notebook 사용자의 경우, 첫번째 셀에 아래 코드 실행 


%load_ext nb_black


lab 사용자의 경우, 첫번째 셀에 아래 코드 실행 


%load_ext lab_black


이후 코드를 실행하면, 자동으로 black format 으로 포매팅이 되는 것을 볼 수 있다. 따로 command 를 이용해서 formatting 을 하지 않아도 실행하는 즉시 formatting 이 되기 때문에 매우 유용하다!


링크 

https://github.com/dnanhkhoa/nb_black?source=your_stories_page

반응형
반응형

Early Stopping 이란 무엇인가? 


딥러닝을 비롯한 머신러닝 모델의 한 가지 중요한 딜레마는 다음과 같다. 


너무 많은 Epoch 은 overfitting 을 일으킨다. 하지만 너무 적은 Epoch 은 underfitting 을 일으킨다. 


이런 상황에서 Epoch 을 어떻게 설정해야하는가? 

Epoch 을 정하는데 많이 사용되는 Early stopping 은 무조건 Epoch 을 많이 돌린 후, 특정 시점에서 멈추는 것이다. 


그 특정시점을 어떻게 정하느냐가 Early stopping 의 핵심이라고 할 수 있다. 일반적으로 hold-out validation set 에서의 성능이 더이상 증가하지 않을 때 학습을 중지시키게 된다. 본 포스팅에서는 Keras 를 이용하여 Early stopping 을 구현하는 법과 성능이 더 이상 증가하지 않는다는 것은 어떤 기준으로 정하는 것인지를 중점으로 정리해보고자 한다.  


Early Stopping in Keras


Keras 의 Early stopping 을 구현하는 Early stopping 함수를 통해 구현할 수 있다. 


from keras.callbacks import EarlyStopping


Earlystopping 클래스의 구성 요소

  • Performance measure: 어떤 성능을 monitoring 할 것인가?
  • Trigger: 언제 training 을 멈출 것인가?

Earlystopping 객체는 초기화될 때 두개의 요소를 정의하게 된다. 


아래와 같이 지정하면 validation set 의 loss 를 monitoring 한다는 뜻이다. 


es = EarlyStopping(monitor='val_loss')


만약 performance measure가 최소화 시켜야하는 것이면 mode를 min 으로, 최대화 시켜야하는 것이면 mode를 max로 지정한다. loss 의 경우, 최소화 시키는 방향으로 training 이 진행되므로 min 을 지정한다. 


es = EarlyStopping(monitor='val_loss', mode='min')


mode 의 default 는 auto 인데, 이는 keras 에서 알아서 min, max 를 선택하게 된다. 여기까지가 가장 기본적인 Early stopping 의 사용법이다. performance measure를 정의하고, 이것을 최대화 할지, 최소화 할지를 지정하는 것이다. 그러면 keras 에서 알아서 적절한 epoch 에서 training 을 멈춘다. verbose=1 로 지정하면, 언제 keras 에서 training 을 멈추었는지를 화면에 출력할 수 있다. 


성능이 증가하지 않는다고, 그 순간 바로 멈추는 것은 효과적이지않을 수 있다. patience 는 성능이 증가하지 않는 epoch 을 몇 번이나 허용할 것인가를 정의한다. partience 는 다소 주관적인 기준이다. 사용한 데이터와 모델의 설계에 따라 최적의 값이 바뀔 수 있다. 


es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=50)


만약 performance measure 를 practical 하게 설정한 경우 성능의 증가의 기준을 직접 정의할 수 있다. 예를 들어 아래 코드는 validation accuracy 가 1% 증가하지 않는 경우, 성능의 증가가 없다고 정의한다. 


특정값에 도달했을 때, 더 이상 training 이 필요하지 않은 경우가 있다. 이 경우 baseline 파라미터를 통해 정의할 수 있다. 


es = EarlyStopping(monitor='val_loss', mode='min', baseline=0.4)


최종적으로 mode.fit 함수의 callback 으로 early stopping 객체를 넣어주면 early stopping 을 적용할 수 있다. 


hist = model.fit(train_x, train_y, nb_epoch=10,  

                 batch_size=10, verbose=2, validation_split=0.2,   

                 callbacks=[early_stopping])  


Model Choice


Early stopping 객체에 의해 트레이닝이 중지되었을 때, 그 상태는 이전 모델에 비해 일반적으로 validation error 가 높은 상태일 것이다. 따라서, Earlystopping 을 하는 것은 특정 시점에 모델의 트레이닝을 멈춤으로써, 모델의 validation error 가 더 이상 낮아지지 않도록 조절할 수는 있겠지만, 중지된 상태가 최고의 모델은 아닐 것이다. 따라서 가장 validation performance 가 좋은 모델을 저장하는 것이 필요한데, keras 에서는 이를 위해 ModelCheckpoint 라고 하는 객체를 존재한다. 이 객체는 validation error 를 모니터링하면서, 이전 epoch 에 비해 validation performance 가 좋은 경우, 무조건 이 때의 parameter 들을 저장한다. 이를 통해 트레이닝이 중지되었을 때, 가장 validation performance 가 높았던 모델을 반환할 수 있다. 


from keras.callbacks import ModelCheckpoint


mc = ModelCheckpoint('best_model.h5', monitor='val_loss', mode='min', save_best_only=True)


위 ModelCheckpoint instance를 callbacks 파라미터에 넣어줌으로써, 가장 validation performance 가 좋았던 모델을 저장할 수 있게된다.


hist = model.fit(train_x, train_y, nb_epoch=10,  

                 batch_size=10, verbose=2, validation_split=0.2,   

                 callbacks=[early_stopping, mc])  

참고

https://machinelearningmastery.com/how-to-stop-training-deep-neural-networks-at-the-right-time-using-early-stopping/

https://machinelearningmastery.com/early-stopping-to-avoid-overtraining-neural-network-models/

반응형
반응형

효율적으로 이메일을 쓰는 8가지 팁


학교에서 이메일을 쓰는 법을 알려주지는 않는다. 하지만 업무 환경에서 이메일을 잘쓰는 것은 매우 중요한 스킬 중의 하나이다. 특히, 대학원생과 같은 재택 근무를 하는 직업에 있어서는 이메일이 전적인 커뮤니케이션 수단일 수도 있으며,  교수와 컨택을 하거나, 회사에 지원하는 상황에서 이메일은 그 사람의 첫 인상을 결정지을 수 있다. 실제 업무에 있어서도 내용이 명확하지 않은 이메일은 혼란과 지연을 일으킬 수 있기 때문에 이메일을 효율적으로 쓰면 업무의 능률을 높일 수 있을 것이다. 본 포스팅에서는 어떻게 하면 효율적으로 이메일을 쓸 수 있을지 8가지로 정리해보고자 한다. 영어 이메일을 쓰는데 중점을 두고 정리했지만, 한국어로 이메일을 보낼 때도 마찬가지로 적용할 수 있는 내용이다. 


1. 머릿속으로 먼저 내용을 구상하기 / 수신자 입장에서 생각하기  


이메일을 쓰기 위하여 키보드에 손을 올리기 전, 먼저 전체 내용에 대해 구상하는 것이 좋다. 특히 다음과 같은 것을 먼저 생각해보면 좋다. 

  • 왜 이메일을 쓰는가?
  • 어떤 내용을 전달할 것인가?
  • 어떤 답을 원하는가?

만약 상대방에게 요청하는 종류의 이메일이라면 요청을 명확하게 하는 것이 좋다.


다음으로 수신자의 관점에서 생각하라. 

  • 수신자가 답을 주려면 어떤 정보를 제공해야하는가? 
  • 수신자에게 답변을 받기 위해 충분한 'Background information' 을 제공하면 답을 받을 수 있다. 
  • 이메일에는 수신자에 따라 적절한 에티켓이 존재함을 명심하라. (예를 들어, OMG, LOL, ㅠㅠ 등의 이모티콘은 Business 이메일에서는 좋지 않다.


2. 이메일 제목을 잘 정하기 


두 번째는 이메일 제목 (Subject line) 을 정하는 것이다. "안녕하세요." 와 같은 제목은 스팸 메일함으로 가기 딱 좋은 제목이다. 포인트는 이메일의 제목을 모호하지 않고, 목적을 포괄하면서도 간결하게 정하는 것이다. 예를 들어, 회사에 지원을 하기 위한 이메일이라면 지원하고자하는 직위명을 메일 제목에 명시하자. 또한 제목을 정하는 것은 나중에 수신 메일함에서 검색을 할 때에도 용이하다. 단순히 "질문입니다." 와 같은 이메일 보다, "마케팅 방법에 대한 질문입니다." 와 같이 보다 구체적으로 적으면 나중에 메일을 검색하기 쉽다. 


3. 적절한 인사의 중요성  


수신자의 이름을 안다면, Title 을 붙여 부른다. 예를 들어 영어 이메일의 경우, 그 사람을 사적으로 아는 것이 아니라면 Ms, Mrs, Miss 를 붙여야 한다.  만약에 성을 모른다면 Dear Chris Smith 와 같이 Last name 으로 부르는 것이 좋다. 만약 이름을 모른다면, Hello, Dear Manager 와 같이 시작하면 좋다. 만약 아는 사람이라면 늘 부르는 이름을 쓰면 된다. 


4. 완벽한 문법과 구둣점


이메일에서 문법을 정확하게 지켜 쓰는 것을 중요하다. 왜냐하면 문법에 문제가 있을 경우, 수신자가 발신자에 대해 의식적 혹은 무의식적으로 판단을 내릴 수 있기 때문이다. 예를 들어 다음과 같은 것에 중점을 두고 문법을 정확히 작성하는 방법을 익혀보자.  

  • 만연체: 영어에서 여러개의 절이 합쳐진 매우 긴 문장을 run-on sentences 라고 한다. 이메일에서는 이러한 run-on sentences 를 지양해야한다. 만약에 이메일을 작성한 후, 문장이 너무 길다면 여러개의 짧은 문장으로 분할하는 것을 고려하자. 
  • Comma: Comma는 너무 많아서도, 너무 적어서도 안된다. 적절한 위치에 Comman 를 사용하는 것을 배우자. 
  • 주어-동사 일치: 주어-동사 일치는 1인칭, 2인칭, 3인칭 주어에 맞게 동사를 사용하는 것을 말한다. 주어-동사 일치가 맞지 않으면 좋은 커뮤니케이션을 가진 사람으로 인정받기 힘들 수도 있다. 


5. 정확한 스펠링과 대소문자 구분 


Spelling 을 체크하기 위해 여러번 읽어보는 것이 좋다. 하지만 여의치 않는 경우, Spell checker 프로그램을 사용하면 좋다. 필자는 Grammarly 의 크롬 확장 프로그램을 이용중인데, Gmail 과 함께 이용하기 좋고, 특히 editor 를 사용해 글을 작성할 때, 팝업창을 띄워 스펠링을 체크할 수 있는 점이 매우 좋다. 하지만 이러한 프로그램에 지나치게 의존하는 것은 좋지 않다. 단지 spelling 만 체크해주고, 문맥은 고려하지 않기 때문이다. 고급 기능을 활용하기 위해서는 유료 결제를 해야한다. 


Grammarly 를 이용한 tistory editor 의 팝업창 - spelling 이 잘못된 단어 빨간 밑줄을 쳐준다.


정확한 대문자를 사용하자. 생각보다 외국인은 대문자에 민감하게 반응한다. 

  • 문장의 첫 단어를 대문자로 시작한다. 
  • 적절한 단어 (예를 들어 회사 명, 나라 이름 등) 의 첫 글자를 대문자로 쓴다. 

대문자가 되어야할 글자가 소문자로 되어있거나, 소문자로 되어야할 글자가 대문자로 되어있으면, 수신자에게 혼란을 줄 수 있다. 


6.  이메일의 포맷은 최대한 심플하게


이메일은 최대한 format 이 없는 plain text 로 작성하는 것이 좋다. 워드나 에버노트 같은 텍스트 편집기의 내용 (특히 테이블 등) 을 그대로 복사-붙여넣기 하는 경우, 다른 이메일 플롯폼을 사용하는 수신자에게는 format 이 깨져서 보일 수도 있다. 



7. 최대한 간결히 


이메일을 최대한 간결하게 작성한다. 횡설수설하지 않고, 최대한 요점을 전달하는 것이 좋다. 그렇지 않은 이메일은 포인트를 놓치기 쉽고, 수신자의 이해를 떨어트린다. 이메일을 보내는 목적을 명확히 하고, 명료한 언어로 작성하자. 특히 아래 내용을 참고하면 더욱 간결하고 효과적인 이메일을 작성할 수 있다. 

  • 장황함을 줄이기: 특히, 능동태를 사용하자. "Jack sent me the forms" 은 "The forms were sent to me by Jack" 보다 이해가 쉽다. 
  • 포인트에 집중: 어떤 아이디어에 대한 추가적인 정보를 알려주고 싶은 유혹에 빠지지 말자. 수신자가 알고싶어 하는 내용, 포인트에 집중하는 것이 좋다.
  • Bullet Points 를 이용하자: Bullet Points (혹은 -, * 등도 좋다.) 는 수신자에게 무엇이 중요한 정보인지 알려줄 수 있고, 논리 구성을 쉽게 알 수 있도록 한다. 


8. 보내기 전에 다시 한 번 생각하기 


보내기전에 다시 한 번 확인한고, 최대한 줄일 수 있는 부분을 줄여서 전달하는 것이 좋다. 같은 내용이라면 최대한 짧은 것이 좋다. 특히, 이메일을 작성할 때, 화나 있거나, 감정적인 경우도 많은데, 본인의 이메일을 썼을 때의 감정을 다시 되돌아보고, 마음에 걸린다면 바로 보내지말고 Save (임시보관) 버튼을 누르자. 그리고 몇 시간이 지난 후 다시 한 번 내용을 확인하고 보내는것도 좋은 방법이다. 


예약 발송 기능을 활용하는 것도 좋은 팁이다. 이메일의 단점은 보낸 순간 돌이키기 힘들다는 것인데, 예약 발송기능을 확인하면, 실제로 보내지기 전까지 여유 텀을 주기 때문에 혹시 추가할 내용이 생각나거나, 내용의 수정이 필요한 경우 반영하여 다시 보낼 수 있다는 장점이 있다. Gmail 의 경우 보내기 옆에 화살표 모양을 클릭하면, 예약 발송기능을 활용할 수 있다. 


이러한 모든 방법을 고려해서 이메일을 보내는 것은 다소 시간이 소요될 수도 있다. 하지만, 이메일이 주 커뮤니케이션 수단일 경우, 이메일을 신중하게 작성하는 것이 결국 업무의 효율을 결정한다. 또한 이메일을 작성하는 능력은 본인의 업무 능력을 가늠할 수 있는 하나의 판단 기준이 되기도 한다. 따라서 심사숙고해서 이메일을 작성하는 것을 습관을 들이는 것은 전혀 시간 낭비가 아니다. 뱉은 말은 다시 담을 수 없듯, 이메일도 마찬가지이다. 


참고

https://www.thebalancecareers.com/write-email-that-gets-response-3542570

반응형

'Soft skills > Communication' 카테고리의 다른 글

영어 이메일 잘 쓰는 18가지 팁  (0) 2019.06.28
반응형

영어 이메일 잘 쓰는 18가지 팁


편한 관계에서 이메일을 주고 받는 경우, 의미만 통하면 그만이지만, 비지니스 관계에서는 에티켓을 숙지하는 것이 관계에 있어 중요하다고 할 수 있다. 하지만 영어에 익숙하지 않은 경우 이것을 자연스럽게하기 힘들다. 어떻게 하면 프로답게 이메일을 작성할 수 있을까? 먼저, 기본적인 이메일의 포맷을 배우고, 많이 사용하는 표현을 익히고 상황에 맞게 변형하여 사용하는 것이 첫 번째일 것이다. 이를 학습하기 위한 유용한 링크를 첨부한다.


https://www.fluentu.com/blog/english-kor/%EC%98%81%EC%96%B4-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%93%B0%EB%8A%94-%EB%B0%A9%EB%B2%95-18%EA%B0%9C%EC%9D%98-%EC%A4%91%EC%9A%94-%ED%8C%81%EA%B3%BC-%EC%83%98%ED%94%8C-%EC%9D%B4%EB%A9%94%EC%9D%BC-3/

반응형

'Soft skills > Communication' 카테고리의 다른 글

효율적으로 이메일을 쓰는 8가지 팁  (0) 2019.06.28
반응형

Pandas 에서 반복을 효율적으로 처리하는 방법


Pandas 를 통해 데이터 프로세싱을 할 때 종종 해야할일은 행에 반복적으로 접근을 하면서 그 값을 조작하는 일이다. 예를 들어, missing value 가 0 으로 코딩이 되어있는데, 이를 다른 값으로 바꾸고 싶을 경우 또는 A 컬럼의 값이 missing 일 때, B 컬럼의 값을 수정하고 싶은 경우 등이 있다. 이러한 작업을 하기 위해서는 모든 행을 조회 하면서 값을 조회하고 수정하는 일이 필요하다. 이번 포스팅에서는 이러한 반복작업이 필요한 상황에서 어떤 방법이 가장 효율적일지에 대해 정리해보려고한다.


사용할 데이터

diabetes.csv


1) pd.iterrows()


가장 기본적이고 많이 사용하는 방법이 iterrows 함수를 이용하는 것이다. 하지만 iterrows 함수는 다른 방법에 비해 느린 편이다. 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

diabetes = pd.read_csv("diabetes.csv")
diabetes.head()


PregnanciesGlucoseBloodPressureSkinThicknessInsulinBMIDiabetesPedigreeFunctionAgeOutcome
061487235033.60.627501
11856629026.60.351310
28183640023.30.672321
318966239428.10.167210
40137403516843.12.288331


missing value 가 0 으로 코딩이 되어있는데, 이를 nan 으로 바꾸는 코드를 iterrows 를 이용해서 짜보자. 

def fix_missing(df, col):
    for i, row in df.iterrows():
        val = row[col]
        if val == 0:
            df.loc[i, col] = np.nan

%timeit fix_missing(diabetes, "SkinThickness")


33.9 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)



2) pd.loc[]/pd.iloc[]


두 번째 방법은 index 를 통해 for 문을 돌면서, loc 또는 iloc 함수를 이용해 dataframe의 row에 접근하는 방법이다. 

def fix_missing2(df, col):
    for i in df.index:
        val = df.loc[i, col]
        if val == 0 :
            df.loc[i, col] = np.nan

%timeit fix_missing2(diabetes, "Insulin")


9.54 ms ± 130 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)


1) iterrow 방법에 비해 약 3배 빨라졌다는 것을 알 수 있다. 따라서 iterrows 가 익숙하다고 하더라도 다른 방법으로 바꾸는 것이 같은 작업을 더 빠르게 실행할 수 있어 효율적이다.  


3) pd.get_value()/pd.set_value()


다음은 위 방법과 마찬가지로 index를 통해 for 문을 돌면서 get_value 와 set_value 함수를 이용하는 방법이다. 2) 방법이 내부적으로 get_value, set_value를 호출하는 것이기 때문에 3) 이를 직접적으로 호출하는 방법이므로 더욱 빠르다. 

def fix_missing3(df, col):
    for i in df.index:
        val = df.get_value(i, col)
        if val == 0:
            df.set_value(i, col, np.nan)

%timeit fix_missing3(diabetes, "BMI")


3.65 ms ± 31.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


2)에 비해 3배 정도 빨라졌으며, 1)에 비해서는 거의 10배 정도의 속도차이가 난다. 


4) pd.apply()


네 번째 방법은 apply 를 이용하는 것이다. apply 를 이용하는 것은 특별한 형태의 function 을 필요로 하는데 (이를 helper function 이라고도 한다), 이것은 Series 혹은 Dataframe의 각 원소마다 적용시킬 함수이다. 

def fix_missing4(x):
    if x == 0 : 
        return -999
    else: return x
    
%timeit diabetes.Age.apply(fix_missing4)
483 µs ± 3.89 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

3) 방법과 비교하여 3650/484 = 7.5 배 속도가 증가했다. apply 함수를 이용하는 것의 장점은 작업이 "비교적 간단할 때" 유용하다. 만약, 여러개의 column 에서 if 문을 적용하서 값을 다이나믹하게 바꾸어야하는 작업에 있어서는 apply 함수보다 for 문을 이용하는 방법이 더 적절할 수 있다. 

정리 
  • Default 방법으로 index 를 돌면서 set_value 와 get_value 를 호출하는 방법을 추천
  • 비교적 큰 데이터에셋에서 비교적 간단한 작업을 할 때, apply 함수가 가장 효율적


참고

https://medium.com/@rtjeannier/pandas-101-cont-9d061cb73bfc

반응형
반응형

Model Calibration


예측모형 (predicted model) 을 어떻게 평가할 수 있을까? 가장 직관적이면서 많이 쓰이는 평가 방법은 정확도 (accuracy), 즉, 예측한 것중 몇퍼센트나 맞았는가에 관한 지표일 것이다. 하지만 좋은 모델이란 정확해야할 뿐만아니라 잘 보정 (calibration) 되어야할 필요가 있다. 


calibration 을 평가하기 위해 사용되는 calibration plot 은 예측된 확률과, 실제 확률의 관계를 보여준다. 이를 통해 모델의 예측이 얼마나 "현실적인지" 를 측정하게 된다. 예를 들어, 이미지를 인풋으로 받아 개와 고양이를 분류하는 모델을 생각해보자. 어떤 이미지에 대해 0.8 의 확률로 개라고 반환했다면, "정말 이 이미지가 개일 확률이 0.8 인가?" 에 대한 답을 주는 것이 calibration plot 이다. 정확도란 (일반적으로 이진 분류에 관하여) 50 % 를 cutoff 로 사용하여, 예측을 A와 B 클래스로 나누어, 실제 값이랑 맞는지를 확인하는 것이지만, calibration 은 보다 면밀하게 모델의 결과값을 검증하는 과정이라고 볼 수 있다. 


Calibration plot 


만약 데이터의 실제 정답이 알려져 있다면, Calibration 을 평가하기 위해 Calibration plot 을 많이 그리게 되는데, 일반적인 방법은 다음과 같다. 


1. 모델의 예측값을 기준으로 [0,10%], (10,20%], (20,30%], … (90,100%] 에 맞게 데이터를 분할한다 (이를 binning 이라고도 한다).  

2. 각 카테고리에서 예측하고자 한 클래스의 비율 (event rate) 를 계산한다 (예제의 경우 개의 비율을 계산한다).

3. calibration plot을 그린다 : 각 카테고리에서의 중앙 값 (5 %, 15 %, 20 % ...) 를 x 로 놓고, event rate 를 y 로 놓고 그린 그림이다. 

4. calibration plot 의 선이 일직선 (45◦)임을 확인한다. 


Example


R을 통해 Calibration 을 실제로 해보자. 


diabetes.csv


실습 데이터는 Pima diabetes 데이터셋을 이용해보겠다. Pima diabetes 데이터셋은 사람들의 임상정보와 당뇨병 여부에 관한 정보를 갖고 있는 데이터셋이다. 이 때 당뇨병 여부를 예측하는 모형을 로지스틱 회귀분석 및 랜덤포레스트을 이용해 구축하고, 이 두 모델의 정확도 및 Calibration 을 평가해보자. 


데이터 로드 및 train/test split 

  • 이 데이터셋의 경우, missing value 가 많은 것이 특징이다. 
  • 아래 코드는 평균으로 missing 을 채워넣는 mean imputation 을 수행하고 train/test 를 50:50으로 나누는 코드이다. 
suppressPackageStartupMessages(library(tidyverse))
library(data.table) 
data <- readr::read_csv("../PimaDiabetes/diabetes.csv") 
data$Outcome <- factor(data$Outcome)

## Imputation
fix_missing <- function(x, missing_value) { 
  x[x == missing_value] <- NA 
  x 
} 
cols <- colnames(data)[1:8]
data[, cols] <- lapply(data[, cols], fix_missing, 0)

impute_mean <- function(x) {
    x[is.na(x)] <- mean(x, na.rm = TRUE)
    return(x)
}
data[, cols] <- lapply(data[, cols], impute_mean)
data %>% head

##  Train/Test Split
set.seed(123)
smp_size <- floor(0.5 * nrow(data))
train_ind <- sample(seq_len(nrow(data)), size = smp_size)
train <- data[trai n_ind, ]
test <- data[-train_ind, ]


로지스틱 회귀분석 모형 구축 및 test set 에 대한 예측

  • Pregnancies + Glucose + BloodPressure + Insulin + BMI + DiabetesPedigreeFunction + Age 를 통해 Outcome 을 예측하는 모형을 만든다. 
lrmodel <- glm(data = train, Outcome ~ Pregnancies + Glucose + BloodPressure + Insulin + BMI + DiabetesPedigreeFunction + Age, family = binomial("logit"))

x = predict(lrmodel, newdata = test)
p = (1 / (1+exp(-x)))
test <- test %>% mutate(lrmodel = p)

랜덤 포레스트 모형 구축 및 test set 에 대한 예측 

  • 랜덤 포레스트의 hyperparameter 인 mtry 와 ntree 는 적절한 값을 선택한다. 
library(randomForest)

rfmodel = randomForest(Outcome ~ Pregnancies + Glucose + BloodPressure + Insulin + BMI + DiabetesPedigreeFunction + Age
                      , data = train, mtry = floor(sqrt(7)), ntree = 500, importance = T)

p = predict(rfmodel, newdata = test, type = "prob")[, 2]
test <- test %>% mutate(rfmodel = p)

cutoff 정하기

  • 모형은 0~1사이의 확률을 의미하는 값을 내보내는데, 여기에 threshold 를 적용해서 0 또는 1로 변환한다. 
test <- test %>% mutate(
  rfclass = if_else(rfmodel >= 0.5, 1, 0),
  lrclass = if_else(lrmodel >= 0.5, 1, 0)
)
test$rfclass <- factor(test$rfclass)
test$lrclass <- factor(test$lrclass)


로지스틱 회귀분석 정확도 

  • 정확도는 최종 예측값 (0 또는 1) 을 기준으로, 예측한 값중 실제 정답으로 맞춘 비율을 의미하는 값이다. 
  • 로지스틱 회귀분석의 경우, 78.9 % 의 정확도를 보여준다. 

library(caret) confusionMatrix(test$lrclass, test$Outcome)

Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 227  58
         1  23  76
                                          
               Accuracy : 0.7891          
                 95% CI : (0.7448, 0.8288)
    No Information Rate : 0.651           
    P-Value [Acc > NIR] : 2.494e-09       
                                          
                  Kappa : 0.5058          
                                          
 Mcnemar's Test P-Value : 0.0001582       
                                          
            Sensitivity : 0.9080          
            Specificity : 0.5672          
         Pos Pred Value : 0.7965          
         Neg Pred Value : 0.7677          
             Prevalence : 0.6510          
         Detection Rate : 0.5911          
   Detection Prevalence : 0.7422          
      Balanced Accuracy : 0.7376          
                                          
       'Positive' Class : 0  


로지스틱 회귀분석 Calibration plot

  • Calibration plot 을 그릴 수 있는 방법은 여러가지가 있지만, caret 패키지의 calibration 함수를 통해 쉽게 그려볼 수 있다. 

calibration 함수는 아래의 calibration plot 을 그릴 수 있는 정보를 dataframe으로 만들어 반환해준다. 
  • 모델의 예측값을 기준으로 [0,10%], (10,20%], (20,30%], … (90,100%] 에 맞게 데이터를 분할한다 (이를 binning 이라고도 한다).  
  • calibration plot을 그린다 : 각 카테고리에서의 중앙 값 (5 %, 15 %, 20 % ...) 를 x 로 놓고, event rate 를 y 로 놓고 그린 그림이다. 
library(caret)

cal_plot_data_lr = calibration(Outcome ~ lrmodel, 
  data = test, cuts = seq(0, 1, by=0.1), class = 1)$data 

ggplot() + xlab("Bin Midpoint") +
  geom_line(data = cal_plot_data_lr, aes(midpoint, Percent),
            color = "#F8766D") +
  geom_point(data = cal_plot_data_lr, aes(midpoint, Percent),
            color = "#F8766D", size = 3) +
  geom_line(aes(c(0, 100), c(0, 100)), linetype = 2, 
            color = 'grey50')

랜덤포레스트 정확도

  • 랜덤포레스트의 경우 로지스틱 회귀분석보다 조금 작은 0.77 % 의 정확도를 보인다. 
confusionMatrix(test$rfclass, test$Outcome)
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 213  51
         1  37  83
                                          
               Accuracy : 0.7708          
                 95% CI : (0.7255, 0.8119)
    No Information Rate : 0.651           
    P-Value [Acc > NIR] : 2.421e-07       
                                          
                  Kappa : 0.4831          
                                          
 Mcnemar's Test P-Value : 0.1658          
                                          
            Sensitivity : 0.8520          
            Specificity : 0.6194          
         Pos Pred Value : 0.8068          
         Neg Pred Value : 0.6917          
             Prevalence : 0.6510          
         Detection Rate : 0.5547          
   Detection Prevalence : 0.6875          
      Balanced Accuracy : 0.7357          
                                          
       'Positive' Class : 0               
                                          


랜덤포레스트 Calibration plot

  • 랜덤포레스트에서도 같은 방법으로 calibration plot 을 그릴 수 있다. 
  • 정확도는 랜덤포레스트에서 약간 작았지만, Calibration 은 더 좋은 모습을 보인다.
  • 하지만 train/test 의 비율, hyperparameter 구성에 따라 calibration 이 달라지니, 다양한 세팅에서 검증해볼 필요가 있다. 
cal_plot_data_rf = calibration(Outcome ~ rfmodel, 
  data = test, class = 1)$data

ggplot() + xlab("Bin Midpoint") +
  geom_line(data = cal_plot_data_rf, aes(midpoint, Percent),
            color = "#F8766D") +
  geom_point(data = cal_plot_data_rf, aes(midpoint, Percent),
            color = "#F8766D", size = 3) +
  geom_line(aes(c(0, 100), c(0, 100)), linetype = 2, 
            color = 'grey50')


https://medium.com/optima-blog/model-calibration-4d710a76c54

http://appliedpredictivemodeling.com/blog?offset=1532965627474


반응형
반응형