분류 전체보기 (340)

반응형

Keras- Tensorflow Backend에서 특정 디바이스 사용법


Keras에 tensorflow backend를 사용할 때, 기본적으로 gpu를 사용하여 돌아갑니다. gpu가 있는데 cpu를 사용할 필요는 없겠지만, gpu의 성능을 측정하거나 하는 목적을 위해 강제로 cpu를 사용하도록 하는 방법에 대해 알아보겠습니다.


keras + tensorflow에서 사용가능한 하드웨어 자원보기


아래와 같이 tensorflow의 device_lib이라는 함수를 통해 현재 사용가능한 하드웨어 디바이스들의 리스트를 볼 수 있습니다. 여기서 name을 통해 해당 하드웨어에 접근할 수 있습니다. 제가 사용하는 환경의 경우 1080ti 4개를 사용하는데, 이 디바이스들의 리스트가 나오는 것을 볼 수 있습니다.

from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())
[name: "/cpu:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: ....
, name: "/gpu:0"
device_type: "GPU"
memory_limit: 295043072
locality {
  bus_id: 1
}
incarnation: .....
physical_device_desc: "device: 0, name: GeForce GTX 1080 Ti, pci bus id: 0000:02:00.0"
, name: "/gpu:1"
device_type: "GPU"
memory_limit: 366346240
locality {
  bus_id: 1
}
...

특정 device 사용하여 모델 구축, 트레이닝하기


아래와 같이 keras.backend.tensorflow_backend를 K 라는 이름으로 불러오고 with 문을 통해 해당 환경에서 모델을 구축후, fitting을 하면 해당 디바이스 환경에서 모델을 트레이닝 할 수 있습니다. 주의할 점은 model = Sequential()을 통해 모델을 생성할 때부터 with문을 통해 해당 device를 사용한다는 것을 알려줘야 한다는 것입니다. 단순히 model.fit 만 with 아래에서 돌리면 with 문이 먹히지 않더군요..

import keras.backend.tensorflow_backend as K
with K.tf.device('/gpu:0'):
    model = Sequential()
    model.add(Dense(512, input_dim=28*28, activation='relu'))
    model.add(Dense(256, activation='relu'))
    model.add(Dense(128, activation='relu'))
    model.add(Dense(32, activation='relu'))
    model.add(Dense(10, activation='softmax'))

    model.compile(loss='categorical_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    h = model.fit(X_train, y_train_cat, batch_size=128*4, epochs=10, verbose=1, validation_split=0.3)
Train on 42000 samples, validate on 18000 samples
Epoch 1/10
42000/42000 [==============================] - 0s - loss: 0.5832 - acc: 0.8240 - val_loss: 0.4741 - val_acc: 0.8254
Epoch 2/10
42000/42000 [==============================] - 0s - loss: 0.2057 - acc: 0.9379 - val_loss: 0.1414 - val_acc: 0.9566
Epoch 3/10
42000/42000 [==============================] - 0s - loss: 0.1359 - acc: 0.9585 - val_loss: 0.1454 - val_acc: 0.9548
Epoch 4/10
42000/42000 [==============================] - 0s - loss: 0.0919 - acc: 0.9717 - val_loss: 0.0964 - val_acc: 0.9716
Epoch 5/10

gpu를 사용하면 아래와 같이 한 epoch 당 1초도 안되어서 트레이닝이되는 것을 볼 수 있습니다. 이번엔 cpu로 한 번 모델을 구축해보겠습니다. 아래와 같이 device 이름을 /cpu:0으로 변경한 후 모델을 구축, fitting을 하면, 한 epoch 당 2초가 걸리는 것을 확인할 수 있습니다.

import keras.backend.tensorflow_backend as K
with K.tf.device('/cpu:0'):
    model = Sequential()
    model.add(Dense(512, input_dim=28*28, activation='relu'))
    model.add(Dense(256, activation='relu'))
    model.add(Dense(128, activation='relu'))
    model.add(Dense(32, activation='relu'))
    model.add(Dense(10, activation='softmax'))

    model.compile(loss='categorical_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    h = model.fit(X_train, y_train_cat, batch_size=128*4, epochs=10, verbose=1, validation_split=0.3)
Train on 42000 samples, validate on 18000 samples
Epoch 1/10
42000/42000 [==============================] - 2s - loss: 0.6009 - acc: 0.8115 - val_loss: 0.3323 - val_acc: 0.8966
Epoch 2/10
42000/42000 [==============================] - 2s - loss: 0.2008 - acc: 0.9404 - val_loss: 0.3604 - val_acc: 0.8832
Epoch 3/10
42000/42000 [==============================] - 2s - loss: 0.1293 - acc: 0.9605 - val_loss: 0.1384 - val_acc: 0.9578
Epoch 4/10
42000/42000 [==============================] - 2s - loss: 0.0914 - acc: 0.9716 - val_loss: 0.1376 - val_acc: 0.9590
Epoch 5/10
42000/42000 [==============================] - 2s - loss: 0.0676 - acc: 0.9796 - val_loss: 0.1145 - val_acc: 0.9674
Epoch 6/10
42000/42000 [==============================] - 2s - loss: 0.0494 - acc: 0.9842 - val_loss: 0.0903 - val_acc: 0.9742


반응형
반응형

Medical Image 분야에서의 Deep Learning 응용


약 100여년 전, 의학분야에 처음 Medical Image가 도입되었을 때 그것은 의학 분야의 패러다임을 바꾸었습니다. X-RAY와 같은 의영상 기술을 통해 비침습적으로 내부 장기들을 볼 수 있고, 이를 통해 병을 진단할 수 있고, 암환자의 경우 자신의 남은 수명 또한 알 수 있었습니다. 최근, Deep Learning 기술의 발전이 이 분야에 적용됨으로써 의영상 분야에 다시 한 번 새로운 가능성을 만들어나가고 있습니다.


CBInsigt에서 제시한 이 HeatMap을 보시면 Medical Image분야에 대한 투자가 2015년에 정점을 찍고 계속해서 높은 관심을 받고 있는 것을 볼 수 있습니다. 그만큼 이 분야에 많은 가능성이 있다는 것을 알 수 있습니다. IBM 연구자에 따르면 Medical Image 데이터가 전체 Medical 데이터의 90%를 차지한다고 합니다. 용량만 놓고 말하면 소위 말하는 "헬스케어 데이터" 의 대부분이 Medical Image 데이터 인 것입니다. 데이터의 양만 보더라도 이 분야가 헬스케어 산업에서 차지하는 비중이 매우 높다는 것을 알 수 있습니다. 영상의학 전문의들은 병원에서 하루에 수많은 영상 데이터를 본다고 합니다. 그러므로 그러한 의사들이 마주치는 데이터로부터 어떤 특징을 추출해서 정보를 효율적으로 보여주는 방식이 진단의 속도와 정확성을 높이고 병원이 더 많은 환자를 처리할 수 있게 되어 사회적 문제 해결에도 도움이 될 수 있는 것이죠.


현재 Medical Image 분야에서 Machine Learning, Deep Learning이 응용되는 부분


Tumor Detection


미국에서는 년간 500만건의 피부암의 발생이 보고된다합니다. 피부암은 미국에서 가장 흔하게 진단되는 암이며, 미국의 헬스케어 시스템에서 80억달러가 매년 피부암 치료에 사용된다고 합니다. 이중에서 악성흑색종(Melanoma)의 경우 치명적인 종양인데, 빠른 진단과 치료가 이루어진다면 높은 확률로 이를 치료할 수 있습니다. 피부암은 언제 진단되느냐에 따라 생존률이 15%~65%로 달라지며, 빠른 진단과 치료가 이루어진다면 5년 생존률은 무려 98%에 달한다고 합니다. 피부암을 진단하기 위해서는 피부암을 영상이미지에서 찾아내는 것(Detection)이 중요합니다. Deep Learning을 통해 피부암과 관련된 특징들을 학습하고 이를 통해 피부암을 찾아내는 것이 응용되는 부분 중 하나입니다.


피부 병변의 양성/악성 분류하는 CNN (출처 - https://web.stanford.edu/~kalouche/cs229.html)


다음으로 폐암(Lung Cancer) Detection에도 DeepLearning이 많이 사용됩니다. 주로 폐의 CT scan 데이터를 통해 암을 Detection 하는 알고리즘이 많이 사용되고 있습니다. (Enlitic 이라는 Medical Image 관련 호주 회사) 이 회사에 보고에 따르면 이미지로부터 폐암의 특성을 찾아내는 정확도가 영상의학 전문의보다 높다고합니다.


Medical Image 분야에서는 데이터를 어떻게 획득하냐는 문제가 있습니다. 데이터가 있어야 이를 통해 학습하는 알고리즘을 만들 수 있기 때문입니다. IBM은 2015년 8월 Merge Health Care라는 의영상업체를 인수함으로써 이러한 문제를 해결하고자 하였습니다. Merge의 홈페이지에 가보면 이제 IBM Watson HealthCare라는 이름이 붙어있습니다. IBM은 Merge의 약 300억개의 Medical 이미지 데이터를 통해 Watson을 학습시켜 의사의 진단을 보조할 수 있도록 하는 방법을 꾸준히 연구해나가고 있습니다.



간암 Segmentation하는 논문의 Groud Truth 데이터 Deep Learning은 이러한 CT 데이터를 학습하여 테스트 데이터가 들어왔을 때,

간의 위치와 종양의 위치를 Segmentation 할 수 있다.


암 전이 Tracking


Medical Image는 non-invasive로 질병을 모니터링함으로써 의학적인 중재에 활용할 수 있습니다. Deep Learning은 시간의 흐름에 따른 영상 데이터를 통해 암의 전이 과정을 추적하는데 활용되기도 합니다. 이 논문은 유방암의 Historical 데이터를 통해 암 전이 과정을 평가한 논문입니다. Fraunhofer Institute for Medical Image Computing 은 2013년도에 딥러닝을 통해 암 이미지의 변화를 추적하는 새로운 툴을 공개하였습니다. 이를 통해 임상의들이 암 치료를 어떻게 할지를 결정할 수 있습니다. 이러한 기술들이 더욱 발전된다면 암의 Progress 모니터링을 자동화할 수 있는 가능성이 있습니다.



Tumor Detection & Classification 사례


병변이 의심되는 지점을 찾더라도 그것이 양성인지 악성인지 분류하는 것이 필요한데 삼성은 초음파 이미지에 딥러닝을 활용하여 유방의 병변을 분석하는데 활용하고 있습니다. 삼성의 시스템은 수많은 유방의 케이스를 학습함으로써, 해당 병변의 특성과 그것이 양성인지 악성인지를 분류해 냅니다. 특히 의영상 분야에서는 한국 스타트업의 활약이 두드러지는데 대표적으로 LunitVuno가 있습니다. Lunit은 유방암 Detection 대회에서 마이크로소프트와 IBM을 제치고 1위에 올라 CB Insight 선정 100대 AI 스타트업에 그 이름을 올린 것으로 유명합니다. 삼성 연구원들이 퇴사후 2014년에 설립한 Vuno의 경우 Medical Image Interpretation분야에서 의사를 보조하는 기술을 개발하고 있습니다. 여기에 머신러닝/딥러닝 기술이 들어가며, 이를 통해 의사의 진단 과정을 더욱 빠르고 정확하게 보조하는 역할을 합니다. 

Vuno의 데모영상(https://youtu.be/i7CS05WvOLE)을 보면 Medical Image 데이터를 통해 DILD(Diffuse Interstitial Lung Disease)를 Detection하는 시스템의 데모를 볼 수 있습니다.



참고

https://www.techemergence.com/deep-learning-applications-in-medical-imaging/


반응형
반응형

Python - 폴더 파일 리스트 가져오기


python에서 운영체제 폴더 아래의 파일들을 불러올 때는 os 패키지를 이용한다. 아래 코드에서 filepath 부분에 운영체제 상에 폴더 path를 적으면 폴더 내부의 파일 이름을 가져올 수 있다.

from os import listdir
from os.path import isfile, join
files = [f for f in listdir('filepath') if isfile(join('filepath', f))]
['Info.txt',
 'Licence.txt',
 'mdb001.pgm',
 'mdb002.pgm',
 'mdb003.pgm',
 'mdb004.pgm',
 'mdb005.pgm',
 'mdb006.pgm',
 'mdb007.pgm',
 'mdb008.pgm',


코드를 실행하면 폴더 내부의 파일들의 이름이 files 리스트에 저장된다. 만약 여기서 특정 문자열을 포함한 파일들만 남기고 싶으면 아래와 같이 문자열의 기본함수인 find함수를 이용한다. -1을 리턴하면 해당 문자열이 없는 것이기 때문에 아래의 if문은 해당 문자열을 포함한 원소만 가져오게 한다.

files = [x for x in files if x.find("mdb") != -1] files

['mdb001.pgm',
 'mdb002.pgm',
 'mdb003.pgm',
 'mdb004.pgm',
 'mdb005.pgm',
 'mdb006.pgm',
 'mdb007.pgm',
 'mdb008.pgm'


반응형
반응형

Keras - CNN ImageDataGenerator 활용하기


keras에서는 이미지데이터 학습을 쉽게하도록 하기위해 다양한 패키지를 제공한다. 그 중 하나가 ImageDataGenerator 클래스이다. ImageDataGenerator 클래스를 통해 객체를 생성할 때 파라미터를 전달해주는 것을 통해 데이터의 전처리를 쉽게할 수 있고, 또 이 객체의 flow_from_directory 메소드를 활용하면 폴더 형태로된 데이터 구조를 바로 가져와서 사용할 수 있다. 이 과정은 매우 직관적이고 코드도 ImageDataGenerator를 사용하지 않는 방법에 비해 상당히 짧아진다. 환경은 keras tensorflow backend를 이용하였다.



1. 라이브러리 임포트

# Part 1 - Building the CNN # Importing the Keras libraries and packages from keras.models import Sequential from keras.layers import Conv2D from keras.layers import MaxPooling2D from keras.layers import Flatten from keras.layers import Dense

2. 모델 작성


ImageDataGenerator 클래스를 이용하는 것과 독립적으로 CNN 네트워크를 만들어준다. Input Image의 크기는 64x64이며, Conv-Pool-Conv-Pool-Fully Connected Layer로 이어지는 아주 간단한 구조의 CNN 모델이다. 데이터는 binary 데이터이기 때문에 activation function은 sigmoid함수 이며 손실 함수로 binary_crossentropy, 최적화 함수로는 adam을 사용한다.

# Initialising the CNN
classifier = Sequential()

# Step 1 - Convolution
classifier.add(Conv2D(32, (3, 3), input_shape = (64, 64, 3), activation = 'relu'))

# Step 2 - Pooling
classifier.add(MaxPooling2D(pool_size = (2, 2)))

# Adding a second convolutional layer
classifier.add(Conv2D(32, (3, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))

# Step 3 - Flattening
classifier.add(Flatten())

# Step 4 - Full connection
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 1, activation = 'sigmoid'))

# Compiling the CNN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])

3. ImageDataGenerator를 통한 트레이닝, 테스트 데이터 만들기


ImageDataGenerator를 만들 때 아래와 같이 rescale, shear_range, zoom_range, horizontal_flip을 설정해줌으로써 해당 데이터의 전처리를 어떻게 할지를 정해준다. 이 때 파라미터가 무엇을 뜻하는지를 정리하면 아래와 같다. (https://keras.io/preprocessing/image/)

  • shear_range: Float. Shear Intensity (Shear angle in counter-clockwise direction as radians)
  • zoom_range: Float or [lower, upper]. Range for random zoom. If a float,
  • horizontal_flip: Boolean. Randomly flip inputs horizontally.
  • rescale: rescaling factor. Defaults to None. If None or 0, no rescaling is applied, otherwise we multiply the data by the value provided (before applying any other transformation).
# Part 2 - Fitting the CNN to the images
from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(rescale = 1./255,
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True)

test_datagen = ImageDataGenerator(rescale = 1./255)

training_set = train_datagen.flow_from_directory('dataset/training_set',
                                                 target_size = (64, 64),
                                                 batch_size = 32,
                                                 class_mode = 'binary')

test_set = test_datagen.flow_from_directory('dataset/test_set',
                                            target_size = (64, 64),
                                            batch_size = 32,
                                            class_mode = 'binary')

classifier.fit_generator(training_set,
                         steps_per_epoch = 300,
                         epochs = 25,
                         validation_data = test_set,
                         validation_steps = 2000)

또한 flow_from_directory 메소드를 사용하면 폴더구조를 그대로 가져와서 ImageDataGenerator 객체의 실제 데이터를 채워준다. 이 데이터를 불러올 때 앞서 정의한 파라미터로 전처리를 한다. 마지막으로 fit_generator 함수를 실행함으로써 fitting이 이루어진다. 이 예제의 경우 ImageDataGenerator 객체를 사용하였기 때문에 fit_generator 함수를 통해 fitting한다. steps_per_epoch은 한 번 epoch 돌 때, 데이터를 몇 번 볼 것인가를 정해준다. [트레이닝데이터수/배치사이즈]를 사용하면 되는듯하다. validation_steps는 한 번 epoch 돌 고난 후, validation set을 통해 validation accuracy를 측정할 때 validation set을 몇 번 볼 것인지를 정해준다. 이 때도 마찬가지로 [validation data수/배치사이즈]를 사용하면 된다. 즉 ImageDataGenerator를 쓴 경우, fit_generator를 사용하면 된다고 기억하면 된다. 폴더 구조는 아래와 같이 하면 된다. flow_from_directory에 넣어준 경로(dataset/training_set) 밑에 이런식으로 class(cats, dogs) 별로 폴더를 만들고 폴더 밑에 이미지들을 넣어준다. 그러면 알아서 labeling을 하게 된다.





4. 테스트셋 예측하기


output = classifier.predict_generator(test_set, steps=5)
print(test_set.class_indices)
print(output)
{'cats': 0, 'dogs': 1}
[[ 0.58327454]
 [ 0.08756679]
 [ 0.44407782]
 [ 0.66460747]
 [ 0.38810217]
 [ 0.52190965]
 [ 0.67696238]
 [ 0.67470866]
 [ 0.77020335]
 [ 0.68121213]
 [ 0.66256768]
 [ 0.82018822]
...


반응형
반응형

Spatial Transformation Network


CNN을 통해 이미지 분류를 할 때, 특정 부분을 떼어내서 집중적으로 학습시키는 것은 Spatial Transformation Network라고 한다. 이미지 분류 문제에서는 spatial invariance(이미지가 변환되어도 그 이미지로 인식하는 것. 고양이를 90도 회전시켜놓아도 고양이로 인식하는 능력)가 중요한데 일반적인 CNN에서는 이를 해결하기 위해 max pooling layer가 필요하다. Spartial Transformation은 max pooling layer보다 더 좋은 spatial invariance 능력을 갖게 하기 위해 이미지의 특정 부분을 자르고 변환해서 그 부분만 떼어서 트레이닝을 시킨다. 이 변환하는 과정을 affine transformation이라고 하는데 아래 그림을 보면 이해할 수 있다. 



CNN 안에 하나의 layer로 spartial transformation module이 들어가는데 이 layer는 위의 affine transformation을 하는데 필요한 parameter을 배운다. 이는 일반적인 regression 과정이다. 정교하게 하기 위해서는 많은 트레이닝 데이터가 필요하다.



위 그림은 DeepMind에서 Spartial Transformation Network 관한 논문을 낼때 들어간 그림인데 일부러 지저분하게 변경한 MNIST 데이터에 이 spatial transformation을 적용해서 원하는 부분을 잘라내서 변환하는 것을 보여주고 있다. MNIST 같은 simple한 데이터셋에서는 큰 효과가 없을지 몰라도 원하는 데이터에 여러가지 잡음이 있는 경우 spartial transformation이 좋은 성능을 보여줄 것으로 기대된다.


참고

https://adeshpande3.github.io/adeshpande3.github.io/The-9-Deep-Learning-Papers-You-Need-To-Know-About.html

https://www.slideshare.net/xavigiro/spatial-transformer-networks?from_action=save

https://github.com/oarriaga/spatial_transformer_networks/blob/master/src/mnist_cluttered_example.ipynb

반응형
반응형

Pandas 변수 정렬하기


Python에서 데이터 핸들링시 가장 많이 이용하는 Pandas 패키지를 이용하여 변수를 정렬하는 예제입니다. 예를 들어 아래와 같은 데이터셋이 있다고 합시다.


cluster  org      time
   1      a       8
   1      a       6
   2      h       34
   1      c       23
   2      d       74
   3      w       6 
cluster org time 1 a 8 1 a 6 2 h 34 1 c 23 2 d 74 3 w 6

출처: http://3months.tistory.com/195 [Deep Play]
import pandas as pd
data = pd.DataFrame({"cluster" : [1,1,2,1,2,3], "org":['a','a','h','c','d','w'], "time":[8,6,34,23, 74,6]})


출처: http://3months.tistory.com/195 [Deep Play]
import pandas as pd
data = pd.DataFrame({"cluster" : [1,1,2,1,2,3], "org":['a','a','h','c','d','w'], "time":[8,6,34,23, 74,6]})


출처: http://3months.tistory.com/195 [Deep Play]


이를 pandas DataFrame 객체로 읽기 위해서는 아래와 같은 구문으로 읽으면 됩니다.

import pandas as pd
data = pd.DataFrame({"cluster" : [1,1,2,1,2,3], "org":['a','a','h','c','d','w'], "time":[8,6,34,23, 74,6]})


이후에는 DataFrame 객체에 있는 sort_values를 호출하면 해당 변수에 대해 정렬을 할 수 있습니다. ascending 파라미터는 오름차순으로 정렬할지 여부를 결정합니다. 또한 여러개의 변수에 대해서 정렬하고 싶으면 list 자료구조에 변수를 넣어주기만 하면 됩니다.

data = data.sort_values(["time"], ascending=[False])

cluster org time
4 2 d 74
2 2 h 34
3 1 c 23
0 1 a 8
1 1 a 6
5 3 w 6


그러면 이와같이 결과가 나오는데 인덱스가 뒤죽박죽이 되어있다는 것을 알 수 있습니다. 기존 데이터셋의 인덱스를 그대로 갖고 있는 것입니다. 이로인해 plot을 할 때 문제가 생길 수 있으므로 인덱스를 초기화 하는 작업을 해줍니다. default는 drop=False인데 이렇게 하게 되면 기존의 인덱스가 하나의 컬럼으로 남게 됩니다. 많은 경우 기존의 인덱스는 필요없으므로 drop=True로 설정해줍니다.


data = data.reset_index(drop=True)

cluster org time
0 2 d 74
1 2 h 34
2 1 c 23
3 1 a 8
4 1 a 6
5 3 w 6


반응형
반응형

PANDAS 그룹별 평균 구하기



통계분석에서 전체 평균을 구하는 것뿐만 아니라, 그룹간의 평균을 구하고 이를 비교하는 것은 매우 중요한 주제중 하나라고 할 수 있습니다. sas에서는 proc means by 구문을 통해 구할 수 있고, R에서는 aggregates 함수 등을 이용해 구할 수 있는데요. 파이썬에서는 R의 Data.Frame 과 비슷한 형태로 자료를 핸들링 할 수 있는 pandas라는 패키지가 있습니다. 이 패키지 함수를 통해 그룹별 평균을 구하는 방법을 알아보겠습니다.


cluster  org      time
   1      a       8
   1      a       6
   2      h       34
   1      c       23
   2      d       74
   3      w       6 


예를 들어, 위와 같은 데이터가 있다고 가정합시다. 참고로 이걸 파이썬에서 읽어오는 방법은 아래와 같이 하시면 됩니다.


import pandas as pd
data = pd.DataFrame({"cluster" : [1,1,2,1,2,3], "org":['a','a','h','c','d','w'], "time":[8,6,34,23, 74,6]})


아래 구문은 'cluster' 변수를 그룹으로 하여 모든 숫자형 변수의 평균을 계산해 줍니다. as_index=False 구문은 이 그룹을 인덱스로 지정할 것인지 여부인데, 인덱스로 지정하면 두 번째 테이블처럼 그룹이 인덱스로 들어가게됩니다. 


data.groupby(['cluster'], as_index=False).mean()


cluster time
0 1 12.333333
1 2 54.000000
2 3 6.000000



time
cluster
1 12.333333
2 54.000000
3 6.000000

아래 구문은 cluster와 org를 그룹으로 하여 평균을 계산해줍니다. 예를 들어, cluster가 지역, org가 성별이라고 생각해볼 수 있습니다. 그러면 이 구문은 지역과 성별 별로 변수들의 평균을 구하는 구문이 됩니다.

data.groupby(['cluster', 'org'], as_index=False).mean()

cluster org time
0 1 a 7
1 1 c 23
2 2 d 74
3 2 h 34
4 3 w 6


반응형
반응형

Python으로 빈도표 만들기 (Pandas Crosstab)



파이썬에서 빈도표(Frequency Table)를 만드는 방법은 여러가지가 있지만, 그 중 하나가 pandas의 crosstab 함수를 이용하는 방법이다. 아래처럼 dataframe의 컬럼(Series 데이터타입)을 파라미터로 넘겨주면 빈도표를 만들어준다.

import pandas as pd

raw_data = {'regiment': ['Nighthawks', 'Nighthawks', 'Nighthawks', 'Nighthawks', 'Dragoons', 'Dragoons', 'Dragoons', 'Dragoons', 'Scouts', 'Scouts', 'Scouts', 'Scouts'], 'company': ['infantry', 'infantry', 'cavalry', 'cavalry', 'infantry', 'infantry', 'cavalry', 'cavalry','infantry', 'infantry', 'cavalry', 'cavalry'], 'experience': ['veteran', 'rookie', 'veteran', 'rookie', 'veteran', 'rookie', 'veteran', 'rookie','veteran', 'rookie', 'veteran', 'rookie'], 'name': ['Miller', 'Jacobson', 'Ali', 'Milner', 'Cooze', 'Jacon', 'Ryaner', 'Sone', 'Sloan', 'Piger', 'Riani', 'Ali'], 'preTestScore': [4, 24, 31, 2, 3, 4, 24, 31, 2, 3, 2, 3], 'postTestScore': [25, 94, 57, 62, 70, 25, 94, 57, 62, 70, 62, 70]} df = pd.DataFrame(raw_data, columns = ['regiment', 'company', 'experience', 'name', 'preTestScore', 'postTestScore']) df


2x2 테이블


regiment를 기준으로 하여 company의 빈도를 구한다.

pd.crosstab(df.regiment, df.company, margins=True)


company cavalry infantry All
regiment


Dragoons 2 2 4
Nighthawks 2 2 4
Scouts 2 2 4
All 6 6 12



변수 3개 테이블


company, experience를 기준으로하여 regiment의 빈도를 구한다.

pd.crosstab([df.company, df.experience], df.regiment,  margins=True)



regiment Dragoons Nighthawks Scouts All
company experience



cavalry rookie 1 1 1 3
veteran 1 1 1 3
infantry rookie 1 1 1 3
veteran 1 1 1 3
All
4 4 4 12



만들어진 crosstab에 접근하는법


crosstab을 통해 생성한 객체는 dataframe 타입이고, regiment를 제외한 company와 experience는 multi index로 지정되어있다. 따라서 인덱스 값으로 해당 인덱스의 원소값을 얻는 loc 함수를 통해 crosstab 원소에 접근할 수 있다.


cross_tab = pd.crosstab([df.company, df.experience], df.regiment, margins=True)
cross_tab.loc[[('cavalry', 'rookie')]]


참고

https://chrisalbon.com/python/pandas_crosstabs.html

반응형
반응형

데이터베이스 정규화 1NF, 2NF, 3NF, BCNF



데이터베이스 정규화란 데이터베이스의 설계를 재구성하는 테크닉입니다. 정규화를 통해 불필요한 데이터(redundancy)를 없앨 수 있고, 삽입/갱신/삭제 시 발생할 수 있는 각종 이상현상(Anamolies)들을 방지할 수 있습니다. 



데이터베이스 정규화의 목적은 주로 두 가지입니다.


1. 불필요한 데이터(data redundancy)를 제거한다.

2. 데이터 저장을 "논리적으로" 한다.


여기서 2번 데이터 저장을 논리적으로 한다는 것은 데이터 테이블의 구성이 논리적이고 직관적이어야한다는 것입니다.


우선 정규화를 안 했을 때의 문제점에 대해서 알아보겠습니다.




위와 같이 정규화가 되지 않은 구조의 테이블(Adam이라는 학생이 두 번 들어가 있습니다.)의 경우, 데이터 핸들링시 다양한 이상현상이 발생하게 됩니다.


1. Update : Adam의 Address가 변경되었을 때, 여러줄의 데이터를 갱신해야합니다. 이로인해 데이터의 불일치(inconsistency)가 발생할 수 있습니다.


2. Insert : 만약 학생이 아무 과목도 수강하지 않는다고 하면, Subject_opted 컬럼에는 NULL이 들어갈 것입니다.


3. Deletion : 만약 Alex 학생이 과목 수강을 취소한다면 Alex의 레코드가 아예 테이블에서 지워져버립니다.


위와 같이 정규화가 제대로 되지 않은 테이블의 경우 갱신/삽입/삭제 시 다양한 문제점이 발생할 수 있습니다. 이를 테이블의 구성을 논리적으로 변경하여 해결하고자 하는 것이 바로 정규화입니다.


정규화의 법칙(Normalization Rule)은 1차정규화, 2차정규화, 3차정규화, BCNF, 4차정규화, 5차정규화로 나눌 수 있는데, 실무적으로 4차, 5차 정규화까지 하는 경우는 많지 않다고 합니다. 따라서 이 포스팅에서도 BCNF까지만 알아보겠습니다.



1. 1차 정규화


1차 정규형은 각 로우마다 컬럼의 값이 1개씩만 있어야 합니다. 이를 컬럼이 원자값(Atomic Value)를 갖는다고 합니다. 예를 들어, 아래와 같은 경우 Adam의 Subject가 Biology와 Maths 두 개 이기 때문에 1차 정규형을 만족하지 못합니다.



위의 정보를 표현하고 싶은 경우 이렇게 한 개의 로우를 더 만들게 됩니다. 결과적으로 1차 정규화를 함으로써 데이터 redundancy는 더 증가하였습니다. 데이터의 논리적 구성을 위해 이 부분을 희생하는 것으로 볼 수 있습니다.



2. 2차 정규화


2차 정규화부터가 본격적인 정규화의 시작이라고 볼 수 있습니다. 2차 정규형은 테이블의 모든 컬럼이 완전 함수적 종속을 만족하는 것입니다. 이게 무슨 말이냐면 기본키중에 특정 컬럼에만 종속된 컬럼(부분적 종속)이 없어야 한다는 것입니다. 위 테이블의 경우 기본키는 (Student, Subject) 두 개로 볼 수 있습니다. 이 두 개가 합쳐져야 한 로우를 구분할 수가 있습니다. 근데 Age의 경우 이 기본키중에 Student에만 종속되어 있습니다. 즉, Student 컬럼의 값을 알면 Age의 값을 알 수 있습니다. 따라서 Age가 두 번 들어가는 것은 불필요한 것으로 볼 수 있습니다.


Student Table



Subject Table


이를 해결하기 위한 방법은 위처럼 테이블을 쪼개는 것입니다. 그러면 두 테이블 모두 2차 정규형을 만족하게 됩니다. 위 테이블의 경우 삽입/갱신/삭제 이상을 겪지 않게됩니다. 하지만 조금 더 복잡한 테이블의 경우, 갱신 이상을 겪기도하는데 이를 해결하는 것이 바로 3차 정규화입니다.


3. 3차 정규화



이와 같은 데이터 구성을 생각해봅시다. Student_id가 기본키이고, 기본키가 하나이므로 2차 정규형은 만족하는 것으로 볼 수 있습니다. 하지만 이 데이터의 Zip컬럼을 알면 Street, City, State를 결정할 수 있습니다. 또한 여러명의 학생들이 같은 Zip코드를 갖는 경우에 Zip코드만 알면 Street, City, State가 결정되기 때문이 이 컬럼들에는 중복된 데이터가 생길 가능성이 있습니다. 정리하면 3차 정규형은 기본키를 제외한 속성들 간의 이행적 함수 종속이 없는 것 입니다. 풀어서 말하자면, 기본키 이외의 다른 컬럼이 그외 다른 컬럼을 결정할 수 없는 것입니다.


3차 정규화는 2차정규화와 마찬가지로 테이블을 분리함으로써 해결할 수 있는데, 이렇게 두 개의 테이블로 나눔으로써 3차 정규형을 만족할 수 있습니다. 이를 통해 데이터가 논리적인 단위(학생, 주소)로 분리될 수 있고, 데이터의 redundancy도 줄었음을 알 수 있습니다.




4. BCNF


BCNF는 (Boyce and Codd Normal Form) 3차 정규형을 조금 더 강화한 버전으로 볼 수 있습니다. 이는 3차 정규형으로 해결할 수 없는 이상현상을 해결할 수 있습니다. BCNF란 3차정규형을 만족하면서 모든 결정자가 후보키 집합에 속한 정규형입니다. 아래와 같은 경우를 생각해보면, 후보키는 수퍼키중에서 최소성을 만족하는 건데, 이 경우 (학생, 과목) 입니다. (학생, 과목)은 그 로우를 유일하게 구분할 수 있습니다. 근데 이 테이블의 경우 교수가 결정자 입니다. (교수가 한 과목만 강의할 수 있다고 가정) 즉, 교수가 정해지면 과목이 결정됩니다. 근데 교수는 후보키가 아닙니다. 따라서 이 경우에 BCNF를 만족하지 못한다고 합니다. 3차 정규형을 만족하면서 BCNF는 만족하지 않는 경우는 언제일까요? 바로 일반 컬럼이 후보키를 결정하는 경우입니다.


학생

과목

교수

학점

 1

AB123

 김인영

 A

 2

 CS123

 Mr.Sim

 A

 3

 CS123

 Mr.Sim

 A


 위와 같이 테이블이 구성된 경우에 데이터가 중복되고, 갱신 이상이 발생합니다. 예를 들어 Mr.Sim이 강의하는 과목명이 바뀌었다면 두 개의 로우를 갱신해야합니다. 이를 해결하기 위해서는 마찬가지로 테이블을 분리합니다.


교수 테이블


교수

과목

 김인영

AB123

 Mr.Sim

CS123


수강 테이블


학생

과목 

학점

 1

 AB123 

 A

 2

 CS123 

 A

 3

 CS123 

 A




참고

http://www.studytonight.com/dbms/database-normalization.php

http://pronician.tistory.com/922

반응형
반응형

Stacking을 위한 패키지 vecstack


stacking을 쉽게 할 수 있는 패키지가 있을까 해서 찾아보았는데 역시 이미 여러개가 있었다.. 여러가지 패키지중에 vecstack이 사용하기 쉬워보였는데, 매우 간단한 코드로 stacking을 구현할 수 있었다. vectstack은 아래와 같이 선택된 모델마다 "K-fold  averaging prediction" (이 명명법이 맞는지 모르겠지만, K-fold로 K번 prediction을 한 후 이 예측치들의 평균을 결과 예측치로 내놓는 방법을 뜻한다.) 을 한 후 이 결과를 앙상블하여 최종 예측 결과를 내놓게 된다. 결론적으로 stacking에 5개의 모델이 쓰이고 3-fold라면 총 15번 fitting을 하고 5개의 모델에 대한 5번의 예측결과가 나오고 다시 이것을 최종 classifier에 통과시켜 최종 prediction을 만들게 된다. 이러한 과정을 실제 코드로 구현하기는 어렵지는 않지만 코드의 양이 많아질 수도 있다.




이러한 stacking을 vecstack은 간단하게 구현한다. 단순히 모델을 정의하고, 모델들의 리스트와 train_x, train_x, test_x만 넣어주면 된다. 그러면 그 안에서 모델들에 대해 k-fold averaging prediction을 수행하며, 이를 통해 트레이닝셋과 테스트셋에 대해 각각 예측 결과 4개씩을 내놓는다. 그게 S_train, S_test이며 다시 이를 최종 classifier로 학습시켜 최종 예측 결과를 내놓게 된다. 하지만 sklearn 형식의 모델만 stacking에 활용할 수 있는 것 같다. 그것이 단점이지만 sklearn의 패키지만으로도 충분히 좋은 예측 결과를 내놓을 수 있기 때문에 stacking을 간단하게 적용해보기에 좋은 패키지인 것 같다.

from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.ensemble import ExtraTreesClassifier from sklearn.ensemble import RandomForestClassifier from xgboost import XGBClassifier from vecstack import stacking # Load demo data iris = load_iris() X, y = iris.data, iris.target # Make train/test split # As usual in machine learning task we have X_train, y_train, and X_test X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0) # Caution! All models and parameter values are just # demonstrational and shouldn't be considered as recommended. # Initialize 1-st level models. models = [ ExtraTreesClassifier(random_state = 0, n_jobs = -1, n_estimators = 100, max_depth = 3), RandomForestClassifier(random_state = 0, n_jobs = -1, n_estimators = 100, max_depth = 3), XGBClassifier(seed = 0, n_jobs = -1, learning_rate = 0.1, n_estimators = 100, max_depth = 3)] # Compute stacking features S_train, S_test = stacking(models, X_train, y_train, X_test, regression = False, metric = accuracy_score, n_folds = 4, stratified = True, shuffle = True, random_state = 0, verbose = 2) # Initialize 2-nd level model model = XGBClassifier(seed = 0, n_jobs = -1, learning_rate = 0.1, n_estimators = 100, max_depth = 3) # Fit 2-nd level model model = model.fit(S_train, y_train) # Predict y_pred = model.predict(S_test) # Final prediction score print('Final prediction score: [%.8f]' % accuracy_score(y_test, y_pred))

코드 출처

https://github.com/vecxoz/vecstack



실행결과

task:   [classification]
metric: [accuracy_score]

model 0: [ExtraTreesClassifier]
    fold 0: [0.93548387]
    fold 1: [0.96666667]
    fold 2: [1.00000000]
    fold 3: [0.89655172]
    ----
    MEAN:   [0.95000000]

model 1: [RandomForestClassifier]
    fold 0: [0.87096774]
    fold 1: [0.96666667]
    fold 2: [1.00000000]
    fold 3: [0.93103448]
    ----
    MEAN:   [0.94166667]

model 2: [XGBClassifier]
    fold 0: [0.83870968]
    fold 1: [0.93333333]
    fold 2: [1.00000000]
    fold 3: [0.93103448]
    ----
    MEAN:   [0.92500000]
    
Final prediction score: [0.96666667]



반응형

'Domains > Kaggle' 카테고리의 다른 글

Stacking 사용할 때 가이드  (0) 2017.10.15