Anaconda Prompt 에서 jupyter notebook --generate-config 설정을 했음에도 사용자 지정 주피터 노트북 경로가 작동 안 될 때 아래 방법으로 간단 해결
1. Jupyter Notebook 아이콘에서 속성 열기
2. 대상(T)에서 %USERPROFILE% 삭제 후, 원하는 폴더 경로 입력.
3. 시작 위치(S) %HOMEPATH% 경로 제거
거의 연구 논문 수준의 기사라서 추천합니다.
산림파괴하는 태양광 과연 탄소제로 가능한가?
탄소흡수체를 없애고 다시 탄소저감 시설을 설치하고 있는 환경 정책.
환경을 빌미로 새로운 토건 마피아를 양산하는 것은 아닐까요?
우리나라 모든 문제는 행정 편의주의에 있습니다. 그것은 내거티브 규제 정책과 맞물려 있습니다.
언제쯤이면 해방이후 덕지덕지 뗌빵으로 혼란한 우리나라 정책들이 엣지있고 정교한 정책으로 바뀌어 국민들이 선진국 수준으로 누릴 수 있을까요?
1. 네트워크(또는 모델)를 구성하는 층
2. 입력 데이터와 그에 대응하는 타깃
3. 손실함수: 예측과 타깃을 비교하여 모델의 예측이 기대값에 얼마나 잘 맞는지 측정하는 손실값을 만듬
4. 학습 진행방식을 결정하는 옵티마이저
층의 네트워크
딱 맞는 네트워크 구조를 찾는 것은 과학보다 예술. 연습 필요.
>>> from keras import models
>>> from keras import layers
>>> model = model.Sequential()
Sequential() 모델의 경우, 단일 입력, 단일 출력인 경우 사용
다중입력 데이터 + 여러 딥러닝 모듈 인 경우 함수형 API 사용
입력층, 은닉층, 출력층 등의 딥러닝의 구성 단위
하나 이상의 텐서를 입력받아 하나 이상의 텐서를 출력하는 데이터 처리 모듈
가중치: 대부분의 층은 가중치를 가짐. 네트워크(모델)가 학습한 지식이 가중치에 담겨 있음.
>>> model.add(layers.Dense(32, input_shape=(784,)) activation = 'relu')
첫번째 차원이 784인 2D텐서만 입력으로 받는 층을 만듬.
배치 차원인 0번째 축은 지정하지 않았기 때문에 어떤 배치 크기도 입력받을 수 있음
이 층은 첫번째 차원 크기가 32로 변환된 텐서를 출력함
즉, 이 다음 하위층은 32차원의 벡터를 입력으로 받는 하위 층으로 연결되어야 함.
(Kerase에서는 자동으로 층 호환성을 맞춤)
>>> model.add(layers.Dense(10), activation='softmax')
input_shape을 지정하지 않아도 Kerase에서는 자동으로 앞선 층의 출력크기로 맞춰줌.
>>> from keras import optimizers
>>>model.comopile(optimizer = optimizers.RMSprop(r=0.001),
... loss='mse'
... metrics=['accuracy'])
모델의 최적 매개변수(가중치, 편향) 학습에 필요한 에러 측정 함수
네트워크(망)이 예측한 결과와 데이터 세트에 명시된 실제 결과의 차이를 측정
훈련하는 동안 최소화될 값. 주어진 문제에 대한 성공 지표
분류문제: 데이터 세트의 데이터 중 잘못 분류한 비율을 계산하고, 그 비율을 에러 발생 확률로 사용
회귀문제: 입력 데이터로 예측한 결과와 실제 결과 간의 차이를 계산하여 평균을 구함.
손실 함수를 기반으로 네트워크가 어떻게 업그레이드 될 지 결정. 확률적 경사 하강법 사용해서 구함.
여러개의 출력을 만드는 신경망은 또한 여러 개(vector or tensor)의 손실함수를 가질 수 있음 (출력당 하나씩).
경사 하강법은 하나의 손실값(scalar)을 이용하기 때문에, 모든 네트워크에서 출력된 손실의 평균값을 계산.
신경망은 단지 손실함수를 최소화하기만 한다. 따라서, 목적 함수를 올바로 선택하지 않으면 원치않는 side effects가 커질 수 있다.
1. binary_crossentropy (이항 교차 엔트로피 또는 이진 크로스엔트로피): 이진 분류 문제. 참/거짓 2개의 클래스를 분류할 때
2. categorical_crossentropy 범주형 크로스엔트로피: 여러개의 클래스 분류할 때
3. mean_squared_error 평균 제곱 오차: 회귀문제
4. mean_absolute_error 평균 절대 오차: 회귀문제
5. mean_absolute_percentage_error: 평균 절대 백분율 오차: 회귀문제
6. CTC(Connection Temporal Classification): 시퀀스 학습 문제
>>> model.fit(X, Y, epochs=100, batch_size=10)
일반적인 데이터 셋 csv 파일의 경우, 가로행(속성 또는 피쳐 feature), 세로열(샘플 또는 인스턴스instance 또는 example))로 구성됨.
학습 프로세서가 모든 샘플 에 대해 한 번 실행되는 것을 1epoch
epochs=100 이면, 각 샘플이 처음부터 끝까지 100번 재사용될 때가지 실행을 반복하라는 뜻.
샘플을 한번에 몇개씩 처리할지 정하는 부분
batch_size=10 이면 전체 샘플 중 10개씩 끊어저 집어넣으라는 뜻.
너무 크면 학습도 저하, 너무 작으면 편차가 높아져 결과값이 불안정해 짐
따라서, 현재 시스템의 메모리가 감당할 만큼의 batch_size를 찾아 설정해 주는 게 관권.
학습/테스트 세트로 구분하여 평가
과소적합/과적합
GPU가 2개인데, CPU 에서도 작업을 수행하게 해서 3개 작업을 동시에 분업시키는 방법
1. 듀얼 GPU 설정하는 방법은 아래 링크 참고.
2. 기본적으로 케라스가 GPU를 인식에서 이용하기 때문에, 아래 명령어를 추가해 주면 CPU를 사용한다.
import os
os.environ["CUDA_VISIBLE_DEVICES"] = ""
from keras import backend as K
with K.tf.device('/cpu:0'):
classifier = Sequential()
classifier.add(Dense(units = 13, activation = 'relu'))
classifier.add(Dense(units = 1, activation = 'sigmoid'))
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
따라서, GPU 2개 CPUs 1개 돌려서 총 3개의 작업을 동시에 할 수 있다.
>>> import tensorflow as tf
>>> from kerase.datasets import mnist
>>> mnist = tf.keras.datasets.mnist
>>> (x_train, y_train), (x_test, y_test) = mnist.load_data() # train / test set을 알아서 나눔
# mnist 데이터는 0~255 범위의 데이터
# 이를 0~1 사이로 맞춰주기 위해서 255로 나눔.
# 딥러닝은 0~1 사이로 input 데이터의 범위를 해줘야.
>>> x_train, x_test = x_train / 255.0, x_test / 255.0
>>> x_train.shape
Layer(층):
데이터 처리 필터
어떤 데이터가 들어가면 더 유용한 형태로 출력됨.
즉, 주어진 문제에 더 의미 있는 표현을 입력 데이터로 부터 추출함
여러 층을 통과하면서 점진적으로 데이터를 정제함.
데이터 정체 필터(층)가 연속되어 있는 데이터 프로세싱을 위한 여과기 같다고 생각할 수 있음.
>>> model = tf.keras.models.Sequential([
... tf.keras.layers.Reshape((28, 28, 1)),
... tf.keras.layers.Conv2D(16, 3, activation='relu'),
... tf.keras.layers.Flatten(),
... tf.keras.layers.Dense(128),
... tf.keras.layers.Dense(10, activation='softmax')
... ])
손실함수 (loss function):
신경망의 성능을 측정하는 방법
모델(네트워크)이 옳은 방향으로 학습될 수 있도록 해줌.
옵티마이저(optimizer):
입력 데이터와 손실 함수를 기반으로 네트워크를 업데이트하는 메커니즘
모니터링 지표
정확도 등
>>> model.compile(optimizer='adam',
... loss='sparse_categorical_crossentropy',
... metrics=['accuracy'])
>>> model.fit(x_train, y_train, epochs=5)
>>> test_loss, test_acc = model.evaluate(x_test, y_test)
>>> print('테스트 정확도:', test_acc)
구글 플레이그라운드에 접속
https://playground.tensorflow.org
파이썬 리스트는 활용도가 높지만, 빅데이터 처리에는 충분하지 않다.
파이썬의 리스트에서는 데이터가 비연속적인 위치에 저당되므로 대량의 데이터 처라에 불리함.
C언어 스타일의 2차원 배열은 데이터들이 연속적인 위치에 저장되어 효율적으로 처리할 수 있음. 왜냐하면 연속적으로 데이터가 저장되어 있어야 다음 데이터를 찾기 쉽기 때문.
과학/공학 분야에서 사용되는 파이썬 라이브러리
넘파이 API는 Pandas, SciPy, Matplotbli, scikit-learn 등의ㅐ 패키지에서 사용됨.
훈련샘플은 2차원, 3차원 다차원 행렬안에 저장됨.
행렬에서 삭제, 분리, 추가 등의 조작은 반드시 넘파이를 사용
>>> import numpy as np
배열은 넘파이의 핵심 데이터 구조
배열의 요소는 모두 동일한 타입
배열의 랭크(rank)는 차원 수
배열의 형상(shape)은 각 차원 및 항목 수
** 1차원 배열은 하나의 축만 가지고 있고, 2차원 배열은 2개의 축을 가진다.
배열생성은 array 함수 사용
a = np.array([1,2,3]) ## 1차원
# a: 배열 객체
# np.arry: 생성자 함수
# ([1,2,3]) : 파이썬 리스트
>>> a
array([1,2,3])
>>> a[0]
1
>>> b = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> b
arrary([[1,2,3],
[4,5,6],
[7,8,9]])
>>> b[0][2]
3
넘파이 클래스 ndarray의 속성들
ndim : 축의 갯수, 2차원이면 ndim=2
shape: 배열의 형상, 정수 튜플로 나나냄. n행, m열의 경 (n,m)
size: 배열 내 요소들의 총 갯수
dtype: 배열 요소의 자료형,. numpy.int32, numpy.int16, numpy.float64 등
itemsize: 배열을 이루는 요소의 크기. 단위는 바이트. float64는 itemsize=8
data: 실제 데이터가 저장되는 메모리 블럭 주소
>>> dtype = np.int32 또는 dtype="np.int32"
>>> a=np.array([[0,1,2],
[3,4,5],
[6,7,8]])
>>> a.shape # 배열의 형상
(3,3)
>>> a.ndim # 배열의 차원 수
2
>>> a.dtype # 요소의 자료형
dtype('int32')
>>> a.itemsize # 요소 한개의 크기
8
>>> a.size # 전체 요소 수
9
>>> np.zeros((3,4))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>> np.ones((3,4))
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
>>> np.ones((3,4), dtype=np.int32)
array([[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]])
>>> np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
>>> x = np.ones(5, dtype=np.int64)
>>> x
array([1, 1, 1, 1, 1], dtype=int64)
>>> x = np.ones(5, dtype=np.int64)
>>> x
array([1, 1, 1, 1, 1], dtype=int64)
>>> np.arrange(5)
AttributeError: module 'numpy' has no attribute 'arrange'
>>> np.arange(5)
array([0, 1, 2, 3, 4])
>>> np.arange(1,6)
array([1, 2, 3, 4, 5])
>>> np.arange(1,6)
array([1, 2, 3, 4, 5])
>>> np.arange(1,10,2)
array([1, 3, 5, 7, 9])
start: 시작값
stop: 종료값
num: 갯수
>>> np.linspace(0,10,100)
array([ 0. , 0.1010101 , 0.2020202 , 0.3030303 , 0.4040404 ,
0.50505051, 0.60606061, 0.70707071, 0.80808081, 0.90909091,
1.01010101, 1.11111111, 1.21212121, 1.31313131, 1.41414141,
1.51515152, 1.61616162, 1.71717172, 1.81818182, 1.91919192,
2.02020202, 2.12121212, 2.22222222, 2.32323232, 2.42424242,
2.52525253, 2.62626263, 2.72727273, 2.82828283, 2.92929293,
3.03030303, 3.13131313, 3.23232323, 3.33333333, 3.43434343,
3.53535354, 3.63636364, 3.73737374, 3.83838384, 3.93939394,
4.04040404, 4.14141414, 4.24242424, 4.34343434, 4.44444444,
4.54545455, 4.64646465, 4.74747475, 4.84848485, 4.94949495,
5.05050505, 5.15151515, 5.25252525, 5.35353535, 5.45454545,
5.55555556, 5.65656566, 5.75757576, 5.85858586, 5.95959596,
6.06060606, 6.16161616, 6.26262626, 6.36363636, 6.46464646,
6.56565657, 6.66666667, 6.76767677, 6.86868687, 6.96969697,
7.07070707, 7.17171717, 7.27272727, 7.37373737, 7.47474747,
7.57575758, 7.67676768, 7.77777778, 7.87878788, 7.97979798,
8.08080808, 8.18181818, 8.28282828, 8.38383838, 8.48484848,
8.58585859, 8.68686869, 8.78787879, 8.88888889, 8.98989899,
9.09090909, 9.19191919, 9.29292929, 9.39393939, 9.49494949,
9.5959596 , 9.6969697 , 9.7979798 , 9.8989899 , 10. ])
>>> arr = np.array([2,1,5,3,7,4,6,8])
>>> np.sort(arr)
array([1, 2, 3, 4, 5, 6, 7, 8])
>>> x=np.array([[1,2],[3,4]])
>>> y=np.array([[5,6],[7,8]])
>>> np.concatenate((x,y), axis=1)
array([[1, 2, 5, 6],
[3, 4, 7, 8]])
np.concatenate(), vstack(), hstack() 사용해도 됨.
>>> np.vstack((x,y))
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
>>> np.vstack(x,y)
TypeError: _vhstack_dispatcher() takes 1 positional argument but 2 were given
>>> np.hstack((x,y))
array([[1, 2, 5, 6],
[3, 4, 7, 8]])
일반적으로 딥러닝은 2차원 입력이어야 한다.
따라서, 1차원 자료를 2차원으로 변환해야
reshape(): 행렬 데이터 갯수는 그대로, 차원만 변경함.
new_array: 새로운 배열
old_array: 원래 배열
(2,3): 새 배열 형상
>>> a = np.arange(12)
>>> a.shape
(12,)
>>> a.reshape(3,4) # 3x4 행렬로 변환
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a.reshape(6,-1) #인수가 -1 인 경우, 데이터 갯수에 맞춰서 자동으로 배열형태 결정함.
array([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11]])
다차원 배열 --> 1차원으로
flatten() 사용 (ravel() 사용하면 view 만 변경되므로 주의.)
>>> y = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
>>> y.flatten()
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
>>> a = y.flatten()
>>> a[0]= 99
>>> print(a)
[99 2 3 4 5 6 7 8 9 10 11 12]
>>> print(y)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
넘파이 배열을 자르는 메소드는 split()
세로로 자르려면 axis=1,가로면 axis=0
>>> array= np.arange(30).reshape(-1,10)
>>> array
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]])
>>> array= np.arange(30).reshape(-1,10)
>>> array
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]])
>>> arr1,arr2 = np.split(array, [3], axis=1)
>>> arr1
array([[ 0, 1, 2],
[10, 11, 12],
[20, 21, 22]])
>>> arr2
array([[ 3, 4, 5, 6, 7, 8, 9],
[13, 14, 15, 16, 17, 18, 19],
[23, 24, 25, 26, 27, 28, 29]])
np.newaxis, np.expand_dims를 사용하여 기존 배열의 크기를 증가시킬 수 있음
np.newaxis를 사용할 때 마다 차원이 1차원 증가
>>> a = np.array([1,2,3,4,5,6])
>>> a.shape
(6,)
>>> a1=a[np.newaxis, :]
>>> a1.shape
(1, 6)
>>> a2=a[:, np.newaxis]
array([[1],
[2],
[3],
[4],
[5],
[6]])
>>> a2.shape
(6, 1)
np.expand_dims() 를 사용하여 지정된 위치에 새 축을 삽입하여 배열 확장 가능
>>> b = np.expand_dims(a, axis=1)
>>> b
array([[1],
[2],
[3],
[4],
[5],
[6]])
>>> b.shape
(6, 1)
>>> ages = np.array([18,19, 25, 30, 28])
>>> ages[1:3] # index 1~2
array([19, 25])
>>> ages[:2] # index 0~1
array([18, 19])
>>> y = ages > 20 # 논리 인덱싱
>>> y
array([False, False, True, True, True])
>>> ages[ages > 20] ## 20 이상을 뽑아낼 때
array([25,30,28])
2차원 배열 인덱싱/슬라이싱은 가장 많이 사용됨. 연습 필요.
>>> a = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a[0,2]
3
>>> a[0][2]
3
>>>
>>> a[0,0] = 12
>>> a
array([[12, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]])
>>> a[0:2, 1:3]
array([[2, 3],
[5, 6]])
>>> a[0]
array([1,2,3])
>> a[1,1:3]
array([5,6])
넘파이 함수, 인덱싱, 슬라이싱 연산자는 데이터 복사 필요없이 view 만 변환
view에서 데이터 수정하면 원본 배열도 수정됨.
얕은 복사 예 ... b가 변하면 원본 a도 변한다.
>>> a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
>>> b = a[0,:]
>>> b
array([1, 2, 3, 4])
>>> b[0] = 99
>>> b
array([99, 2, 3, 4])
>>> a
array([[99, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
깊은 복사 예 ... b2는 변해도 원본 a는 변하지 않는다.
>>> b2 = a.copy()
>>> b2
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> b2[0] = 88
>>> b2
array([[88, 88, 88, 88],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> a
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> arr1 = np.array([[1,2],[3,4],[5,6]])
>>> arr2 = np.array([[1,1],[1,1],[1,1]])
>>> results = arr1 + arr2
>>> results
array([[2, 3],
[4, 5],
[6, 7]])
>>> arr1**2
array([[ 1, 4],
[ 9, 16],
[25, 36]], dtype=int32)
>>> arr1.sum()
21
>>> arr1.min()
1
>>> arr1.max()
6
>>> arr1.mean(axis=0) # 특정 열에서의 모든 행의 값을 사용해서 계산
array([3., 4.,])
>>> arr1.mean(axis=1) # 특정 열에서의 모든 열의 값을 사용해서 계산
array([1.5, 3.5, 5.5]
>>> print(arr1.T) # 전치행렬
>>> arr1*arr2
array([[1, 2],
[3, 4],
[5, 6]])
>>> arr1 = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> arr2 = np.array([[2,2],[2,2],[2,2]])
>>> arr1 @ arr2 ## 내적 (1번째 열, 2번째 행 갯수 일치해야)
array([[12, 12],
[30, 30],
[48, 48]])
>>> np.random.seed(100) # 이후 아래 명령어 수행해야
>>>np.radom.rand(5)
>>> np.radom.rand(5,3)
>>> np.radom.randit(1,7,size=10)
>> > np.random.randn(5) ## 정규분포 난수 생성
a = np.random.normal(loc=0.0, scale=1.0, size=None)
loc: 평균
scale: 표준편차
size: 배열의 차원
>> mu, sigma = 0, 0.1
>> np.random.normal(mu, sigma, 5)
array([-0.17497655, 0.03426804, 0.11530358, -0.0252436 , 0.09813208])
>>> a = np.array([11,11,12,14,13, 15, 16, 17, 12, 13, 11, 14, 18, 19, 20])
>>> unique_values = np.unique(a)
>>> unique_values
array([11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
>>> uniuqe_values, indices_list = np.unique(a, return_index=True)
>>> print(indices_list)
[ 0 2 3 4 5 6 7 8 12 13 14]
>>> unique_values, occurrence_count = np.unique(a, return_counts=True)
>>> print(occurrence_count)
[3 2 2 2 1 1 1 1 1 1]
Pandas 를 사용
read_csv()를 호출하면 반환되는 객체의 values에 넘파이배열로 저장됨.
>>> import numpy as np
>>> import pandas as pd
>>> x= pd.read_csv('example.csv', header=0).values
>>> print(x)
>>> x= pd.read_csv('example.csv', usecols=['col1','col2']).values
>>> print(x)
>>> df = pd.DataFrame(a)
>>> print(df)
>> df.to_csv('out.csv')
여기서는 gpu_0와 gpu_1 두 개의 가상환경을 만든다.
각 가상환경(gpu_0, gpu_1)에서 아래 명령어 실행
python -m ipykernel install --user --name [가상환경 이름] --display-name "[커널이름]"
아래 그림 처럼,Kernal > Change kernel 에서 GPU_0, GPU_1 생성된 것을 확인
(gpu_0) jupyter kernerlspec uninstall gpu_0
각 가상 커널에서 GPU 사용할 GPU 번호를 지정해 준다.
아래 그림과 같이, 현재 GPU 전용 메모리는 둘 다 사용되지 않고 있음.
딥러닝 코드 실행
아래 그림 처럼, 각 GPU가 따로 돌아가는 것을 볼 수 있음.
본 예제에서는 아래 그림처럼 각자 4초 정도 시간이 소요되었다.
각각의 가상환경으로 설정하지 않거나 설정이 잘 못 된 경우, 계산 도중 예전 데이터를 Disk에 Overwrite 할 것인지 Reload 할 것인지 계속 묻는다. 이는 하나의 가상환경에서 두개의 GPU를 따로 지정해서는 분업이 이루어지지 않는 상태라는 말임.
딥러닝 TensorFlow-GPU 설정 방법은 아래 링크를 참조
epochs=5
batch_size=5
np.random.seed(1)
epochs=5
batch_size=5
np.random.seed(7820)
gap-filling with mean values.
epochs=20
batch_size=5
np.random.seed(7820)
from keras.models import Sequential
from keras.layers import Dense
classifier = Sequential()
classifier.add(Dense(units = 13, activation = 'relu'))
classifier.add(Dense(units = 1, activation = 'sigmoid'))
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])