1. Tensorflow에서 Tensor를 생성하는 방법

텐서플로에서 사용하는 주 자료구조가 텐서(Tensor)입니다. 텐서는 변수로 선언할 수도 있고, 데이터 투입 대상인 Placeholder로 선언할 수도 있습니다. 텐서를 생성하는 방법은 여러가지가 있습니다. 텐서를 생성하기 위한 여러가지 내장 함수를 살펴보도록 하겠습니다.


1. 고정 텐서

텐서플로에서 고정된 값으로 텐서를 생성하기 위한 방법은 아래와 같습니다.

tf.zeros()

0 값으로 채워진 텐서를 생성하기 위한 함수입니다.

1zeros_tensor = tf.zeros([row_dim, col_dim])

tf.ones()

1값으로 채워진 텐서를 생성하기 위한 함수입니다.

1ones_tensor = tf.ones([row_dim, col_dim])

tf.fill()

동일한 상수 값으로 채워진 텐서를 생성하기 위한 함수입니다.

1filled_tensor = tf.fill([row_dim, col_dim])

tf.constant()

기존 상수를 이용해 텐서를 생성하기 위한 함수입니다.

1constant_tensor = tf.constant([1, 2, 3])

2. 비슷한 값을 가지는 텐서

기존 텐서의 형태를 바탕으로 텐서 변수를 초기화하는 것도 가능합니다.

tf.zeros_like / tf.ones_like

1zeros_similar = tf.zeros_like(constant_tensor)
2ones_similar = tf.ones_like(constant_tensor)

3. 시퀀스 텐서

구간을 지정하는 방식으로 텐선을 선언할 수 있습니다.

tf.range()

정수 시퀀스 텐서를 생성합니다.

1# range(start, limit=None, delta=1, name='range')
2integer_sequence_tensor = tf.range(start=6, limit=15, delta=3)
  • start : 시퀀스의 시작값이며, 기본값은 0
  • limit : 시퀀스의 상한값이며, 시퀀스에 포함되지 않음
  • delta : start를 증가시키는 수
  • name : 연산의 명칭(선택)

tf.linspace()

일정 구간 사이의 값을 생성합니다.

1# linspace(start, stop, num, name=None)
2linear_tensor = tf.linspace(start=0, stop=1, num=3)
  • start : 시퀀스의 시작값
  • stop : 시퀀스의 상한값
  • num : 생성할 값들의 개수

4. 랜덤 텐서

난수 기반의 텐서를 생성하는 방법은 아래와 같습니다.

tf.random_uniform()

균등 분포를 따르는 난수를 생성합니다.

1# random_uniform(shape, minval=0, maxval=None, dtype=tf.float32, seed=None, name=None)
2randunif_tensor = tf.random_uniform([row_dim, col_dim], minval=0, maxval=1)
  • shape : 정수값의 D-1 텐서 또는 파이썬 배열 입력
  • minval : 난수값 생성 구간의 하한
  • maxval : 난수값 생성 구간의 상한
  • dtype : 반환값의 타입 설정 (float32, float64, int32, int64)
  • seed : 난수 시드값 설정에 사용
  • name : 연산의 명칭(선택)

tf.random_normal()

정규 분포를 따르는 난수를 생성합니다.

1# random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)
2randnorm_tensor = tf.random_normal([row_dim, col_dim], mean=0.0, stddev=1.0)
  • shape : 정수값의 D-1 텐서 또는 파이썬 배열 입력
  • mean : 정규분포의 평균값
  • stddev : 정규분포의 표준 편차
  • dtype : 반환값의 타입 설정 (float32, float64, int32, int64)
  • seed : 난수 시드값 설정에 사용
  • name : 연산의 명칭(선택)

tf.truncated_normal()

지정한 평균에서 표준편차 2배 이내의 값을 생성합니다. 특정 범위에 속하는 정규 분포 임의의 값을 생성하고 싶은 경우 사용합니다.

1# truncated_normal(shape, mean, stddev=1.0, dtype=tf.float32, seed=None, name=None)
2runcnorm_tensor = tf.truncated_normal([row_dim, col_dim], mean=0.0, stddev=1.0])
  • shape : 정수값의 D-1 텐서 또는 파이썬 배열 입력
  • mean : 정규분포의 평균값
  • stddev : 정규분포의 표준 편차
  • dtype : 반환값의 타입 설정 (float32, float64, int32, int64)
  • seed : 난수 시드값 설정에 사용
  • name : 연산의 명칭(선택)

tf.random_shuffle()

배열 항목을 뒤섞을 때 사용합니다. random_shuffle() 함수는 값의 첫번째 차원을 기준으로 랜덤하게 섞어줍니다.

1# random_shuffle(value, seed=None, name=None)
2shuffled_output = tf.random_shuffle(input_tensor)
  • value : 입력 텐서

tf.random_crop(value, size, seed=None, name=None)

텐서를 주어진 사이즈만큼 랜덤하게 잘라내고 싶을 때 사용합니다.

1# random_crop(value, size, seed=None, name=None)
2cropped_output = tf.random_crop(input_tensor, crop_size)
  • value : 입력 텐서
  • size : 잘라내고 싶은 텐서의 사이즈


Tensorflow와 Algorithm Flow

구글 텐서플로를 사용하면 머신 러닝 문제를 아주 효과적으로 해결할 수 있습니다. 머신 러닝은 음성 인식, 자연어 처리, 영상 처리 등의 다양한 분야에서 사용되고 있습니다. 텐서플로가 동작하는 방식이 처음에는 낮설게 느껴질 수 있지만, 이러한 복잡한 계산 방식 덕분에 복잡한 알고리즘을 쉽게 개발할 수 있습니다.

텐서플로는 Linux, MacOS, Window를 지원합니다. 텐서플로의 핵심 코드들은 C++로 작성되어 있지만, Python으로 구현된 라이브러리만으로도 충분히 머신 러닝을 진행할 수 있습니다.


텐서플로 참고 사이트

  1. https://www.tensorflow.org/api_docs/python/
  2. https://www.tensorflow.org/tutorials

텐서플로 알고리즘의 흐름

  1. 데이터셋 생성
  2. 데이터 전처리
  3. 데이터셋 분할
  4. 머신 러닝 알고리즘 파라미터 설정
  5. 변수 및 플레이스홀더 초기화
  6. 모델 구조 정의
  7. 비용 함수(Loss Function) 선언
  8. 모델 초기화 및 학습
  9. 모델 평가
  10. 파라미터 재정의 (선택)
  11. 적용 및 결과 예측

데이터셋 생성

머신 러닝 뿐만 아니라 데이터 분석을 위해서는 데이터셋이 필요합니다. 데이터셋은 직접 생성하거나 외부에서 가져오는 방식으로 얻을 수 있습니다.

데이터 전처리

데이터 전처리는 머신 러닝을 진행하는 데 있어 아주 중요한 역할을 수행합니다. 대부분의 데이터셋은 머신 러닝을 진행하는데 적합한 형태로 제공되지 않기 때문에 적절한 형태로 변환할 필요성이 있습니다. 텐서플로는 데이터 전처리를 위한 다양한 내장 함수를 제공합니다.

데이터셋 분할

머신 러닝 알고리즘 테스트를 위해 일반적으로 Test Set과 Train Set으로 데이터를 구분합니다. 필요에 따라서는 알고리즘 매개변수의 조절이 필요하기 떄문에 매개변수의 최적 값을 정하기 위해 검증셋까지 구분하는 경우도 있습니다.

머신 러닝 알고리즘 파라미터 설정

일반적인 알고리즘에는 학습을 위해 다양한 파라미터가 존재하고, 파라미터에 따라 예측 결과가 변화합니다. 따라서, 학습을 진행하기 이전에 파라미터를 적절히 설정하는 것이 중요합니다.

변수 및 플레이스홀더 초기화

텐서플로는 수정할 수 있는 값과 수정할 수 없는 값이 있습니다. 텐서플로는 비용 함수를 최소화하는 최적화 과정에서 변수 값, 가중치(Weight)와 편향(Bias) 값을 조정합니다. 데이터를 플레이스 홀더 자리에 투입해 최적화를 진행합니다. 변수 및 플레이스 홀더의 크기와 타입을 모두 초기화 시점에 지정하여 처리 대상에 대한 정보를 텐서플로에 알려주어야 합니다. 또한, 텐서플로가 처리할 데이터의 타입도 알려주어야 합니다.
(*플레이스홀더(Placeholder)에 대한 설명은 추후에 진행하도록 하겠습니다.)

1a_var = tf.constant(42)
2x_input = tf.placeholder(tf.float32, [None, input_size])
3y_input = tf.placeholder(tf.float32, [None, num_classes])

모델 구조 정의

학습을 위한 모델을 정의해야 합니다. 모델 정의는 계산 그래프 생성을 통해 이루어 집니다. 텐서플로는 모델의 결과를 얻기 위해 특정 연산과 값을 변수 및 플레이스홀더에 지정해야 합니다.
(*계산 그래프에 대한 설명 또한 추후에 진행하도록 하겠습니다)

비용 함수 선언

모델을 정의한 이후 모델 평가를 진행해야 합니다. 이를 위해 비용 함수를 정의합니다. 비용 함수는 해당 모델이 예측한 값이 실제 값과 얼마나 차이가 있는지를 알려주는 중요한 요소입니다.

모델 초기화 및 학습

그래프 인스턴스를 생성하고 플레이스홀더에 데이터를 투입해 학습을 진행합니다.

모델 평가

구축한 모델이 얼마나 잘 예측하는지를 알아보기 위해 모델 평가를 진행합니다. Train set을 통해 학습한 모델이 Test set에서는 어떻게 예측하는지 파악합니다. 결과로서 모델의 과적합, 과소적합 등의 여부를 판단할 수 있습니다.

파라미터 재정의

필요에 따라서는 구축한 모델의 성능이 만족스럽지 않을 때 알고리즘의 매개변수를 변경하고 싶을 수 있습니다. 알고리즘의 매개변수를 조정해가며 모델의 성능을 향상시킵니다.

적용 및 결과 예측

새로운 데이터를 생성해보고 구축한 모델에 적용해보며 얼마나 잘 예측하는지 확인합니다.




파이썬 2와 파이썬 3 중 무엇을 써야할까?

파이썬의 주요 버전은 크게 버전 2와 버전 3 두 가지로 나뉩니다. 버전 3이 최신이지만 버전 2가 여전히 과학 분야에서 가장 흔하게 사용되고, 여러 운영체제에서 기본적으로 채택하고 있는 버전입니다. 버전 3이 릴리즈됐을 때 대부분의 과학용 패키지는 이를 지원하지 않았기 때문에 버전 2를 고수해왔지만, 이후 파이썬 3과 호환이 불가능한 일부를 제외하고는 거의 모든 패키지들이 업데이트 되었습니다.

최근에는 파이썬 3에 대한 인기가 늘어나고 있지만, 여전이 데이터 사이언티스트들과 데이터 분석가 사이에서 널리 사용되는 버전은 파이썬 2입니다. 하지만, 파이썬 3을 사용한다고 해서 문제될 것은 없습니다. 파이썬 3 사용자라면 파이썬 2에서 구현된 코드를 파이썬 3로 변환하는 것이 어렵지 않기 때문입니다.


Python Packages in ML

Numpy

트라비스 올리펀트(Travis Oliphant)가 개발한 Numpy는 파이썬 언어를 기반으로 하는 모든 분석용 솔루션의 핵심입니다. Numpy는 다차원 배열과 이 배열을 대상으로 여러 가지 수학적 연산을 수행하는 많은 함수들을 제공합니다. 배열은 다차원으로 배열된 데이터 블록으로서 벡터와 행렬을 구현합니다. 배열은 데이터 저장뿐만 아니라 빠른 행렬 연산(벡터화, Vectorization)에 유용하며, 특별히 데이터 과학 분야의 문제를 해결하려고 할 때 반드시 필요한 패키지 입니다.


Scipy

Scipy는 본래 트라비스 올리펀트, 페루 피터슨, 에릭 존슨이 시작한 프로젝트로, 선형 대수, 희소행렬, 신호 및 이미지 처리, 최적화, 급속 퓨리에 변환(Fast Fourier Transformation)등 다양한 종류의 과학용 알고리즘을 제공하면서 Numpy의 기능을 보완합니다.


Pandas

Pandas는 Numpy와 Scipy로 불가능한 모든 기능을 지원합니다. 특히 Pandas 특유의 객체 데이터 구조, 데이터 프레임(DataFrame), 시리즈(Series) 덕분에 서로 다른 데이터 타입으로 구성된 복잡한 테이블과 시계열 데이터를 처리할 수 있습니다. 데이터의 분할, 정제, 유실 데이터 처리, 추가, 재명명, 병합, 변환을 지원해 결국 사용자 의도에 따라 시각화가 가능하도록 합니다.


Scikit-Learn

Scikits(Scipy Toolkit)의 일부로 시작된 Scikit-learn은 파이썬을 사용하는 데이터 과학 연산의 핵심 패키지입니다. Scikit-learn은 데이터 전처리, 지도 및 비지도 학습, 모델 선택, 검증, 오차 기준에 필요한 모든 기능을 제공합니다.

  • 웹 사이트 : http://scikit-learn.org/stable/
  • 데이터 처리 : sklearn.preprocessing, sklearn.feature_extraction)
  • 모델 선택 및 검증 : sklearn.cross_validation, sklearn.grid_search, sklearn.metrics)
  • 목표 값 에측 : sklearn.linear_model

Matplotlib

Matplotlib는 배열로부터 고품질 도표(Plots)를 생성하고 그 도표를 대화형으로 시각화하기 위해 제작된 블록 모두를 포함하는 라이브러리입니다. PyLab 모듈 안에 포함된 MATLAB 방식의 도표 프레임워크를 모두 사용할 수 있습니다.


Gensim

Gensim은 병렬 분산 온라인 알고리즘을 사용하는 대형 문자 집합 분석용 오픈소스 패키지입니다. 잠재 의미 분석(Latent Semantic Analysis, LSA), 잠재 디리클레 할당(Latent Dirichlet Allocation, LDA)에 의한 주제 모델링, 구글의 지도 및 비지도 머신 러닝에서 사용하기 위해 텍스트를 벡터 특징으로 변환하는 알고리즘인 word2vec을 구현할 수 있습니다.


H2O

H2O는 빅데이터 분석용 오픈소스 프레임워크입니다. R, Python, Scala, Java 프로그래밍 언어로 사용할 수 있으며, 단독 머신 혹은 하둡 클러스터를 쉽게 사용할 수 있도록 하였습니다. 스케일 업과 스케일 다운 기능을 지원합니다.


XGBoost

XGBoost는 확장과 이식이 가능한 분산형 경사 부스팅(Gradient Boosting) 라이브러리입니다. Python, R, Java, Scala, Julia, C++를 지원하며, 단일 머신 뿐만 아니라 하둡과 스파크 클러스 모두에서 동작 가능합니다.


Theano

Theano는 다차원 배열을 포함한 수학적 표현식을 효율적으로 정의하고, 최적화하며, 평가할 수 있도록 하는 파이썬 라이브러리입니다. 기본적으로 심층 신경망(Deep Neural Networks)를 만들기 위해 필요한 모든 빌딩 블록을 제공합니다.


TensorFlow

TensorFlow는 배열이 아닌 데이터 플로 그래프를 사용해 수치 연산을 하는 오픈소스 소프트웨어 라이브러리입니다. 그래프 표현에서 노드(Node)는 수학적 연산을 나타내고, 그래프 엣지(Edge)는 노드들 사이를 이동하는 텐서라는 다차원 데이터 배열을 나타냅니다.


sknn library

sknn 라이브러리는 Pylearn2 래퍼(Wrapper)로서, Theano의 전문가가 아니더라도 심층 신경망 네트워크를 구현할 수 있도록 하였습니다.


Theanets

Theanets 패키지는 파이썬으로 작성된 딥러닝 및 신경망 툴킷으로, Theano를 사용해 연산을 가속화한다. sknn처럼 딥러닝 모델 생성을 위해 Theano 기능이 쉽게 연결될 수 있도록 합니다.


Keras

Keras는 고수준으로 최소화된 단위 신경망 라이브러리로, 파이썬으로 작성되었으며 Tensorflow 혹은 Theano상에서 사용할 수 있습니다.


확장성이란 무엇인가?

엄청난 양의 데이터는 언제나 과학자들과 데이터 분석가들이 당면하는 도전 과제였습니다. 훈련 객체의 개수를 n이라 할 때 최근 머신 러닝 알고리즘의 계산 복잡도는 O(n²), 심지어 O(n³)에 이르는데, 과거에 과학자들과 데이터 분석가들은 좀 더 효율적인 데이터 알고리즘에 의존함으로써 그런 대용량 데이터세트와 관련된 문제를 처리했습니다.

데이터 세트는 사례가 많거나 변수들이 많은 경우, 아니면 이 둘 모두가 많은 경우 크기가 커질 수 있는데, 확장 가능한 알고리즘은 문제의 크기에 따라 실행 시간이 거의 선형으로 증가하므로 이런 데이터세트를 효율적으로 처리할 수 있습니다. 따라서 이는 더 많은 시간을 더 많은 데이터와 1:1로 교환하는 문제일 뿐입니다. 하지만, 어떠한 머신 러닝 알고리즘은 대용량 데이터를 다뤄야 하는 상황에서 확장되지 않습니다. 단순히 작업이 멈춘다거나 실행 시간이 지수 함수처럼 비선형적인 형태로 증가해서 학습이 불가능한 경우가 있습니다.

근래에는 저렴한 스토리지, 대용량 RAM, 다중 프로세서 CPU의 도입으로 엄청난 변화의 물결이 있었습니다. 이러한 큰 변화의 주인공은 바로 하둡 분산 시스템(Hadoop Distributed File System) 기반의 오픈소스 프레임워크인 하둡(Hadoop), 맵리듀스(Map Reduce), 그리고 일반적인 컴퓨터 네트워크상의 병럴 처리 기법이 있습니다.

이러한 변화가 규모가 큰 문제를 해결하는 방법에 얼마나 깊고 긍정적인 영향을 미쳤는지 확인하기 위해 대용량 데이터세트의 분석을 방해했던, 방해하고 있는 요인들을 알아보도록 하겠습니다.

  • 분석에 걸리는 시간에 영향을 미치는 연산(Computing)
  • 단위 시간당 스토리지에서 메모리로 이동하는 데이터양에 영향을 미치는 I/O
  • 한 번에 처리할 수 있는 데이터양에 영향을 미치는 메모리

또한, 하드웨어가 가지는 한계는 분석 중인 데이터 유형에 따라 많은 영향을 미치게 됩니다.

  • 긴 데이터(Tall Data) : 사례의 수가 많은 데이터
  • 넓은 데이터(Wide Data) : 특징(Featuress)의 개수가 많은 데이터
  • 길고 넓은 데이터(Tall and Wide Data) : 특징과 사례가 모두 많은 데이터
  • 희소 데이터(Sparse Data) : 0 성분 개수가 많거나, 0으로 변환돌 가능성이 있는 성분 데이터가 많은 데이터

추가적으로, 데이터로 학습을 진행하기 위해서는 사용할 알고리즘이 중요합니다. 각 알고리즘마다 자신만의 특성을 가지는데, 이 특성은 편향(Bias) 혹은 분산(Variance)에 따라 서로 상이하게 영향을 받는 방법을 사용해서 데이터를 매핑하는 방식에 기인합니다. 따라서 지금까지 머신 러닝으로 해결해왔던 문제들에 관해서는 경험 혹은 실증적 검증에 근거해 특정 알고리즘이 다른 알고리즘보다 더 낫다고 판단했습니다. 규모가 큰 문제를 다룰 때는 알고리즘을 결정할 때 이외에 또 다른 사항들을 추가로 고려해야 합니다.

알고리즘이 얼마나 복잡한가?

즉, 데이터에서 행과 열의 개수가 선형 혹은 비선형 비례 관계로 연산 횟수에 영향을 미치는지 살펴봐야 합니다. 대부분의 머신 러닝 기법들은 이차(Quadratic) 혹은 삼차(Cubic) 복잡도를 갖는 알고리즘에 기반하므로 이들을 빅데이터에 적용하는 데에는 많은 제약이 따릅니다.


모델이 얼마나 많은 파라미터를(Parameters)를 갖는가?

이는 단순히 예측값들의 분산에 관한 문제(과적합)가 아닌 그 모두를 계산하는 데 걸리는 시간과 관련된 문제입니다.


최적화 과정이 병렬로 처리될 수 있는가?

다수의 노드들 혹은 CPU 코어들로 연산을 쉽게 분할할 수 있는지? 혹은 순차적인 단일 최적화 과정에 의존해야만 하는가?


해당 알고리즘은 한 번에 모든 데이터로부터 학습을 하는가? 아니면 단일 객체들(Examples) 혹은 작은 배치(Batches) 데이터를 사용할 수 있는가?

위와 같은 문제들은 다음과 같은 접근 방식을 통해 해결할 수 있습니다.

  • 스케일 업(Scale-up) : 소프트웨어 혹은 하드웨어 교체를 통해 단일 머신의 성능을 향상시키는 방법
  • 스케일 아웃(Scale-out) : 주로 스토리지 디스크와 그 외 CPU 같은 외부 자원들을 활용하는 다수의 머신들로 연산을 분산시키는 방법
  • 스케일 업 및 스케일 아웃, 최적의 스케일 업 기법과 스케일 아웃 기법을 함께 활용하는 방법


3. 데이터 선택하기 (Data Selection)
.iloc.locindex slicingpandas

특정 열 선택

DataFrame이 가지고 있는 []를 이용해 슬라이싱하여 출력하는 방법입니다. 특정 열 값만 가지고 오고 싶다면'데이터프레임명'['Column명']과 같은 형태로 입력합니다. 이는 df.A와 동일합니다. 리턴되는 값은 Series의 자료구조를 가지고 있습니다.

print(df['A']) # 'A'
print(df.A) #

특정 행 선택

특정 행 추출과 특정 행 범위 추출은 사용하는 방식이 다릅니다. 특정 행 및 행 범위 추출을 위해서는 인덱스 슬라이싱 기법을 사용해야 합니다.

print(df[0:3]) #
print(df['20130102' : '20130104']) #
print(df['20130102' : '20130102']) #

.loc (이름을 이용한 데이터 선택)

라벨의 이름을 이용하여 선택할 수 있는 .loc 속성도 있습니다. 첫 번째 인덱스 값인 '2013-01-01'에 해당하는 모든 컬럼의 값 가져오기와 같은 작업을 수행할 수 있습니다.

print(df.loc[dates[0]]) # dates[0]
print(df.loc[:, ['A', 'B']]) # , 'A' 'B'
print(df.loc['20130102':'20130104',['A','B']]) # '20130102':'20130104', 'A' 'B'

.iloc (위치를 이용한 데이터 선택)

위치를 나타내는 인덱스 번호를 사용하여 데이터를 선택할 수 있습니다.

print(df.iloc[3]) # 3
print(df.iloc[3:5, 0:2]) # 3:5 , 0:2
print(df.iloc[:, 1:3]) # , 1:3
print(df.iloc[:, 1:3].name)

조건을 이용한 데이터 선택

특정한 행이나 열에 조건을 달아 만족하는 행이나 열만 선택하여 데이터를 추출할 수 있습니다.

isin()

필터링을 해야 하는 경우에 사용합니다.

print(df[df.A > 0]) # 'A' 0
print(df[df > 0] # 0
print(df['E'] = ['one', 'one','two','three','four','three']) # df 'E'
print(df[df['E'].isin(['two', 'four'])]) # 'E' 'two', 'four'


'Machine Learning > Pandas' 카테고리의 다른 글

[Pandas] 데이터 확인하기  (2) 2018.11.29
[Pandas] 데이터 오브젝트 생성  (0) 2018.11.29
2. 데이터 확인하기 (Viewing Data)
.columns.index.T.valuedescribe()head()pandassortsort_indexsort_valuetail()Transpose

DataFrame에 들어있는 자료들을 확인하기 메서드를 몇 가지 살펴보도록 하겠습니다.

head(), tail()

DataFrame의 첫 부분, 마지막 부분의 데이터를 보고싶을 때 사용하는 메서드입니다. 파라미터로 숫자를 넣으면 해당 숫자만큼의 데이터가 출력됩니다.

import pandas as pd
import numpy as np
dates = pd.date_range('20130101', periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
print('\n')
print(df.head(5))
print('\n')
print(df.tail(3))

.index / .columns / .value

DataFrame의 행를 보려면 .index를, 열을 보려면 .column, numpy 데이터를 보려면 .value 속성을 통해 확인하면 됩니다.

print('\n')
print(df.index)
print('\n')
print(df.columns)
print('\n')
print(df.values)

describe()

DataFrame에 대한 간단한 통계 정보를 출력합니다.

  • 컬럼별 데이터 개수(Count)
  • 데이터 평균 값(Mean)
  • 표준편차 (Standard)
  • 최소값 (Minimum)
  • 최대값 (Maximum)
  • 4분위수(Quantile / 25%, 50%, 75%)
print(df.describe())

.T (Transpose)

.T 속성은 DataFrame에서 행과 열을 바꾼 형태의 DataFrame을 출력합니다.

print(df.T)

sort_index() / sort_value()

sort_index()

행과 열 이름을 정렬하여 나타낼 수 있습니다. 정렬할 대상 축을 결정할 때에는 axis 파라미터를 이용합니다.  axis = 0은 행를 기준(행)으로, axis = 1 컬럼을 기준으로 정렬하겠다는 뜻입니다. 정렬의 방향은 ascending파라미터를 사용합니다. ascending = True는 오름차순, ascending = False는 내림차순을 의미합니다.

axis

  • axis = 0 # 행 기준 정렬
  • axis = 1 # 열 기준 정렬

ascending

  • ascending = True # 오름차순 정렬
  • ascending = False # 내림차순 정렬

sort_value()

DataFrame 내부에 있는 값으로 정렬할 수 있습니다.

print(df.sort_index(axis = 1, ascending = False))
print(df.sort_value(by = 'B', ascending = True))




'Machine Learning > Pandas' 카테고리의 다른 글

[Pandas] 데이터 선택하기  (0) 2018.11.29
[Pandas] 데이터 오브젝트 생성  (0) 2018.11.29
1. 데이터 오브젝트 생성
DataFrame()pandasseries()

Pandas에서 제공하는 자료 구조들을 확인하려면 https://pandas.pydata.org/pandas-docs/stable/dsintro.html#dsintro를 참고하면 됩니다.

Reference

https://dandyrilla.github.io/2017-08-12/pandas-10min/#ch1

series()

Pandas의 데이터 구조 중 하나인 Series는 다음과 같이 값들의 리스트를 넘겨주어 만들게 됩니다. 인덱스는 기본적으로 지정되는 정수 인덱스를 사용합니다.

import pandas as pd
import numpy as np
s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s)

DataFrame()

import pandas as pd
import numpy as np
# s = pd.Series([1, 3, 5, np.nan, 6, 8])
dates = pd.date_range('20130101', periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
df2 = pd.DataFrame({'A': 1.,
'B': pd.Timestamp('20130102'),
'C': pd.Series(1, index=list(range(4)), dtype='float32'),
'D': np.array([3]*4, dtype='int32'),
'E': pd.Categorical(['test', 'train', 'test', 'train']),
'F': 'foo'})
# DataFrame
print(df)
print('\n')
print(df2)
# DataFrame Column
print(df2.dtypes)


'Machine Learning > Pandas' 카테고리의 다른 글

[Pandas] 데이터 선택하기  (0) 2018.11.29
[Pandas] 데이터 확인하기  (2) 2018.11.29

MNIST 데이터셋 검증 - 오차행렬

1. 오차 행렬

분류기의 성능을 평가하는 더 좋은 방법은 오차 행렬(Confusion Matrix)을 조사하는 것입니다. 클래스 A의 샘플이 클래스 B로 분류된 횟수를 세는 것입니다.

오차 행렬을 만들기 위해서는 실제 타깃과 비교할 수 있도록 먼저 예측값을 만들어야 합니다. 테스트 세트로 예측을 만들 수 있지만 여기서 사용해서는 안됩니다. 대신 cross_val_predict() 함수를 사용할 수 있습니다.

Code

from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
print(confusion_matrix(y_train_5, y_train_pred))

Output

54,125개를 '5 아님'으로 정확하게 분류하였고(TN), 나머지 454개는 '5'라고 잘못 분류하였습니다(FP).
1,567개를 '5 아님'으로 잘못 분류하였고(FN), 나머지 3,854개를 정확히 '5'라고 분류하였습니다(TP). 

완벽한 분류기라면 진짜 양성진짜 음성만 가지고 있을 것이므로 오차 행렬의 주대각선만 0이 아닌 값이 됩니다.



오차 행렬이 많은 정보를 제공해주지만, 가끔 더 요약된 지표가 필요할 때도 있습니다.
살펴볼만한 것 하나는 양성 예측의 정확도입니다. 이를 분류기의 정밀도(Precision)라고 합니다. 


< Exp. 1. 정밀도 공식 >

TP는 진짜 양성의 수이고, FP는 거짓 양성의 수입니다.

확실한 양성 샘플 하나만 예측하면 간단히 완벽한 정밀도를 얻을 수 있지만, 이는 분류기가 다른 모든 양성 샘플을 무시하기 때문에 그리 유용하지 않습니다. 정밀도는 재현율(Recall) 이라는 또 다른 지표와 같이 사용하는 것이 일반적입니다. 재현율은 분류기가 정확하게 감지한 양성 샘플의 비율로, 민감도(Sensitivity), TPR(True Positive Rate) 이라고도 합니다.



2. 정밀도와 재현율

사이킷런에서는 정밀도와 재현율을 포함하여 분류기의 지표를 계산하는 여러 함수를 제공하고 있습니다.

Code

from sklearn.metrics import precision_score, recall_score
print(precision_score(y_train_5, y_train_pred))
print(recall_score(y_train_5, y_train_pred))

Output

5로 판별된 이미지 중 74%만 정확합니다. 전체 숫자에서는 85%만 감지하였습니다.



정밀도와 재현율을 F₁ 점수라고 하는 하나의 숫자로 만들면 편리할 때가 많습니다. 특히 두 분류기를 비교할 때 유용합니다.
F₁ 점수는 정밀도와 재현율의 조화 평균(Harmonic Mean)입니다.


< Exp. 2. F₁ 점수 공식 >


F₁ 점수를 계산하기 위해서는 f1_score() 함수를 호출하면 됩니다.

Code

from sklearn.metrics import f1_score
print(f1_score(y_train_5, y_train_pred))

Output

정밀도와 재현율이 비슷한 분류기에서는 F₁ 점수가 높습니다. 하지만 이게 항상 바람직한 것은 아닙니다. 상황에 따라 정밀도가 중요할 수도 있고 재현율이 중요할 수도 있습니다.
아쉽지만 정밀도와 재현율을 둘다 얻을 수는 없습니다. 정밀도를 올리면 재현율이 줄고 그 반대도 마찬가지 입니다. 이를 정밀도 / 재현율 트레이드오프라고 합니다.



References

  • 오렐리앙 제롱, '핸즈온 머신러닝', 한빛미디어, 2018


MNIST 데이터셋 분류


1. MNIST

MNIST는 고등학생과 미국 인구조사국 직원들이 손으로 쓴 70,000개의 작은 숫자 이미지를 모은 데이터셋입니다.
각 이미지에는 어떤 숫자를 나타내는지 레이블 되어 있습니다. 이 데이터셋은 학습용으로 아주 많이 사용됩니다.

사이킷런에서 제공하는 여러 헬퍼 함수를 사용해 MNIST 데이터셋을 내려받을 수 있습니다.

Code

from sklearn.datasets import fetch_mldata
X, y = mnist["data"], mnist["target"]
print(X.shape)
print(y.shape)

Output

이미지가 70,000개가 있고 각 이미지에는 784개의 특성이 있습니다. 이미지가 28 × 28 픽셀이기 때문입니다.
개개의 특성은 단순히 0(흰색) 부터 255 (검은색) 까지의 픽셀 강도를 나타냅니다.



데이터셋에서 이미지 하나를 확인해보도록 하겠습니다. 샘플의 특성 벡터를 추출해서 28 × 28 배열로 크기를 바꾸고 맷플롯립의 imshow() 함수를 활용합니다.

Code

import matplotlib
import matplotlib.pyplot as plt

some_digit = X[36000]
some_digit_image = some_digit.reshape(28, 28)

plt.imshow(some_digit_image, cmap=matplotlib.cm.binary,
interpolation="nearest")
plt.axis("off") plt.show() print(y[36000])

Output


>> 5.0

그림 상으로 숫자 '5' 처럼 보이는데, 실제 레이블을 확인해보니 5.0으로 나타납니다.



데이터를 분석하기 전 테스트 세트를 만들고 시작하도록 하겠습니다. MNIST 데이터셋의 경우 이미 훈련 세트(앞쪽 60,000개)와 테스트 세트(뒤쪽 10,000)로 나누어져 있습니다.

Code

import numpy as np
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
shuffle_index = np.random.permutation(60000)
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]

훈련 세트를 섞어 모든 교차 검증 폴드가 비슷해지도록 만들었습니다. 특정 학습 알고리즘은 훈련 샘플의 순서에 민감하게 반응해서 많은 비슷한 샘플이 연이어 나타나면 성능이 나빠집니다. 데이터셋을 섞으면 이러한 문제를 방지할 수 있습니다.



2. 이진 데이터 훈련

문제를 단순화해서 하나의 숫자만 식별해보도록 하겠습니다. 이 감지기는 '5'와 '5가 아님' 두개의 클래스를 구분할 수 있는 이진 분류기(Binary Classifier) 의 예입니다.

Code

from sklearn.linear_model import SGDClassifier

y_train_5 = (y_train == 5)
y_test_5 = (y_test == 5)

sgd_clf = SGDClassifier(max_iter=5, random_state=42)
sgd_clf.fit(X_train, y_train_5)

print(sgd_clf.predict([some_digit]))

Output

>> [True]

분류기가 해당 이미지가 5를 나타낸다고 추측했습니다.



3. 성능 측정

3.1 교차 검증을 사용한 정확도 측정

교차 검증은 모델을 평가하는 좋은 방법 중 하나입니다. 사이킷런에서 교차 검증 함수를 제공하지만, 교차 검증 과정을 더 많이 제어해야 하는 경우도 있습니다.
이때는 교차 검증 기능을 직접 구현하면 됩니다. 아래 코드는 사이킷런의 cross_val_score() 함수와 거의 같은 작업을 수행하고 동일한 결과를 출력합니다.

StratifiedKFold는 클래스별 비율이 유지되도록 폴드를 만들기 위해 계층적 샘플링을 수행합니다. 매 반복에서 분류기 객체를 복제하여 훈련 폴드로 훈련시키고 테스트 폴드로 예측을 만듭니다. 이후 올바른 예측 수를 세어 정확한 예측의 비율을 출력합니다.

Code

from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import StratifiedKFold
skfolds = StratifiedKFold(n_splits=3, random_state=42)

for train_index, test_index in skfolds.split(X_train, y_train_5):
clone_clf = clone(sgd_clf)
X_train_folds = X_train[train_index]
y_train_folds = y_train_5[train_index]
X_test_fold = X_train[test_index]
y_test_fold = y_train_5[test_index]

clone_clf.fit(X_train_folds, y_train_folds)
y_pred = clone_clf.predict(X_test_fold)
n_correct = sum(y_pred == y_test_fold)
print(n_correct / len(y_pred))

Output



사이킷런의 cross_val_score() 함수를 사용하여 폴드가 3개인 K-겹 교차 검증을 사용해 SGDClassifier 모델을 평가해보겠습니다. K-겹 교차 검증은 훈련 세트를 K개의 폴드로 나누고, 각 폴드에 대해 예측을 만들고 평가하기 위해 나머지 폴드로 훈련시킨 모델을 사용합니다.

Code

from sklearn.model_selection import cross_val_score

print(cross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring="accuracy"))

Output

모든 교차 검증 폴드에 대해 정확도(Accuracy)가 95% 이상임을 확인할 수 있습니다.



그렇다면, 모든 이미지를 '5가 아님' 클래스로 분류하는 더미 분류기를 만들어 성능을 비교해보도록 하겠습니다.

Code

from sklearn.base import BaseEstimator
class Never5Classifier(BaseEstimator):
def fit(self, X, y=None):
pass

def predict(self, X):
return np.zeros((len(X), 1), dtype=bool)


never_5_clf = Never5Classifier()
print(cross_val_score(never_5_clf, X_train, y_train_5, cv=3, scoring="accuracy"))

Output

정확도가 90% 이상 나오는 것을 확인할 수 있습니다만, 숫자 '5'를 분류할 때보다 성능이 떨어지는 것을 확인할 수 있었습니다.
이 예제는 정확도를 분류기의 성능 지표로 선호하지 않는 이유를 보여줍니다. 특히 불균형한 데이터셋을 다룰 때 더욱 그렇습니다.



References

  • 오렐리앙 제롱, '핸즈온 머신러닝', 한빛미디어, 2018


+ Recent posts