예를 위해 위 Github에서 0과 1로 이루이진 이진 클래스 데이터 셋이 있다. 이 글은 데이터를 라벨에 맞게 골고루 분리하는 것이므로 데이터 분석은 따로 하지 않는다.
csv 파일은 7개이며, 총 데이터의 개수는 42000개이다.
sklearn 라이브러리에서 train_test_split을 사용하면 간단히 데이터를 분할할 수 있다. 아래 코드에서 간단히 데이터셋을 불러올 수 있다. 이 데이터셋의 경우 nlos가 클래스(혹은 정답 데이터)이다. 아래의 그림을 보게 되면 0, 1, 0, 1, 1...로 무작위로 정렬돼었다. 각 클래스의 개수를 출력하면, 21000개를 확인할 수 있다.
import uwb_dataset
import pandas as pd
columns, data = uwb_dataset.import_from_files()
for item in data:
item[15:] = item[15:]/float(item[2])
print("\nColumns :", columns.shape, sep=" ")
print("Data :", data.shape, sep=" ")
print(type(data))
df_uwb = pd.DataFrame(data=data, columns=columns)
print(df_uwb.head(10))
los_count = df_uwb.query("NLOS == 0")["NLOS"].count()
nlos_count = df_uwb.query("NLOS == 1")["NLOS"].count()
print("Line of Sight Count :", los_count)
print("Non Line of Sight Count :", nlos_count)
"""
결과
./dataset/uwb_dataset_part5.csv
./dataset/uwb_dataset_part7.csv
./dataset/uwb_dataset_part2.csv
./dataset/uwb_dataset_part3.csv
./dataset/uwb_dataset_part4.csv
./dataset/uwb_dataset_part1.csv
./dataset/uwb_dataset_part6.csv
Columns : (1031,)
Data : (42000, 1031)
<class 'numpy.ndarray'>
Line of Sight Count : 21000
Non Line of Sight Count : 21000
"""
파이썬으로 개발을 하면서 느낀 것은 최대한 반복문을 지양하고 라이브러리를 사용하는 것이다. 파이썬은 빠르게 데모 프로그램 구현에 많이 사용하는데 라이브러리가 이를 가능케 한다. 그리고 가장 큰 이유는 내가 만든 코드는 절대 라이브러리를 이길 수 없다는 것이다. 이번에 사용하고자 하는 train_test_split은 sklearn 라이브러리의 함수이다. sklearn는 머신러닝 대표 라이브러리이지만 딥러닝 사용에 있어 문제가 없다.
train_test_split : 배열 또는 행렬을 무작위 학습 및 테스트 하위 집합으로 분할.
-test_size : 0~1 사이의 값으로, 기본 test size는 0.25로 자동으로 train size는 0.75이다. 아래의 그림처럼 데이터를 분할.
- random_state : shuffle 제어하는 인자이다. 모델의 성능을 향상시키기 위해 다양한 방법으로 모델을 디자인한다. 하지만 공정한 검증을 위해 똑같은 데이터셋을 필요로 한다. 그 때 사용하는 인자이다.
왜 CUDA 최신 버전을 사용하지 않고, CUDA 10.2로 사용하는지 의문이 들 수 있습니다.
CUDA 11.1을 사용하기 위해서 CUDA TOOLKIT이 필요합니다. CUDA TOOLKIT을 설치하고 경로 설정하는 것이 굉장히 귀찮은 일이기 때문에, CUDA 10.2를 사용하면 TOOLKIT을 설치하지 않고 바로 사용할 수 있습니다.
import torch
# torch version
torch.__version__
# 1.9
# Returns a bool indicating if CUDA is currently available.
torch.cuda.is_available()
# True
# Returns the index of a currently selected device.
torch.cuda.current_device()
# 0
# Returns the number of GPUs available.
torch.cuda.device_count()
# 1
# Gets the name of a device.
torch.cuda.get_device_name(0)
# NVIDIA GeForce RTX 2060 SUPER
# Context-manager that changes the selected device.
# device (torch.device or int) – device index to select.
torch.cuda.device(0)
Pytorch GPU가 준비 되었으니, 전에 만들어 둔 Se-ResNet을 이용하여 CIFAR-10 데이터 셋을 분류했습니다.
간단히 epoch 200번 정도 돌려 봤는데 괜찮은 결과가 나온 것 같습니다.
이제 야외에서도 딥러닝을 돌려야할 때, 바로 사용할 수 있습니다. ( 해커톤 같은 경우 ...? )
이번 글은 주피터 노트북을 좀 더 유용하고 보기 좋게 만들기 위한 편입니다. 굳이 안 하시고 넘어가셔도 무방합니다.
~ 1. 주피터 노트북 테마 ~
저는 주피터 노트북 기본 테마를 별로 좋아하지 않습니다. 현재 제가 다니고 있는 연구실은 정부에서 지원하는 딥러닝 서버를 주피터 노트북으로 이용하고 있습니다. 저만 사용하는 것이 아니기 때문에, 기본 테마로 뒀습니다.
하지만 이 딥러닝 서버는 오로지 저만을 위한 서버이기 때문에 테마를 바꾸겠습니다.
anaconda prompt를 들어가 pip install jupyterthemes 를 입력해 테마 패키지를 설치합니다.
pip install jupyterthemes # 주피터 노트북 테마 패키지 설치
jt -l # 테마 목록 출력
"""
Available Themes:
chesterish
grade3
gruvboxd
gruvboxl
monokai
oceans16
onedork
solarizedd
solarizedl
"""
저는 테마 grade3이 제일 좋아합니다.
jt -t grade3 -T -N
-T : 툴바 보이게 설정 -N : 제목 보이게 설정
툴바는 무조건 있는게 편합니다. 제목은 내가 현재 어떤 파일을 편집하는지 알기 편하고, 제목을 누르면 수정할 수 있어 편합니다. 이 정도 설정하시면 문제없습니다. 폰트 사이즈나 다양한 설정이 있지만 그건 구글에 치면 많은 블로그가 있습니다.
~ 2. 주피터 노트북 확장 프로그램 ~
확장프로그램은 사람들이 추천하는 것을 사용하면 편합니다. 아래 블로그 분께서 추천하시는 것들을 하시면 편합니다.
Plain Network(단순히 Layer을 깊게 쌓음)에서 발생하는 Vanishing Gradient(기울기 소실), Overfitting(과적합) 등의 문제를 해결하기 위해 ReLU, Batch Nomalization 등 많은 기법이 있습니다.
ILSVRC 대회에서 2015년, 처음으로 Human Recognition보다 높은 성능을 보인 것이 ResNet입니다.
그 위용은 무지막지한 논문 인용 수로 확인할 수 있습니다.
그렇기 때문에 ResNet은 딥러닝 이미지 분야에서 바이블로 통하고 있습니다.
Plain Network는 단순히 Convolution 연산을 단순히 쌓는다면, ResNet은 Block단위로 Parameter을 전달하기 전에 이전의 값을 더하는 방식입니다.
F(x) : weight layer => relu => weight layer
x : identity
weight layer들을 통과한 F(x)와 weight layer들을 통과하지 않은 x의 합을 논문에서는 Residual Mapping 이라 하고, 그림의 구조를 Residual Block이라 하고, Residual Block이 쌓이면 Residual Network(ResNet)이라고 합니다.
Residual Mapping은 간단하지만, Overfitting, Vanishing Gradient 문제가 해결되어 성능이 향상됐습니다.
그리고 다양한 네트워크 구조에서 사용되며, 2017년 ILSVRC을 우승한 SeNet에서 사용됩니다. ( 이 글을 쓴 이유이기도 합니다. )
class Residual_Block(nn.Module):
def __init__(self, in_dim, mid_dim, out_dim):
super(Residual_Block,self).__init__()
# Residual Block
self.residual_block = nn.Sequential(
nn.Conv2d(in_dim, mid_dim, kernel_size=3, padding=1),
nn.ReLU,
nn.Conv2d(mid_dim, out_dim, kernel_size=3, padding=1),
)
self.relu = nn.ReLU()
def forward(self, x):
out = self. residual_block(x) # F(x)
out = out + x # F(x) + x
out = self.relu(out)
return out
그리고 Residual Block 소개 후 BottleNeck이 나옵니다. 아래 글을 참고하시면 좋을 것 같습니다.