패스트캠퍼스 챌린지 43일차
12강 ~ 13강
도착시간을 빠름, 보통, 늦음 등급 데이터로 만들기(3가지 군집 데이터로 분류)
[Routine Code]
1. Mount Drive(Google Drive 연결)
from google.colab import drive
drive.mount('/gdrive')
2. Korean Encoding
!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf
** Runtime Restart → 필요한 코드 재시작
3. Matplotlib
# Import pyplot as a alias 'plt'
import matplotlib.pyplot as plt
# 폰트를 Nanum폰트로 지정
plt.rc('font', family='NanumBarunGothic')
4. Load Data
# Load a file under "data" folder
file = "/gdrive/My Drive/data/data_2021_1_12.csv"
import pandas as pd
data = pd.read_csv(file)
5. 서울 기준 각 영업소까지 거리
#101 서울, 105 기흥, 110 목천, 115 대전, 120 황간, 125 남구미, 130 동김천, 135 경주, 140 부산
#101 서울(406.94), 105 기흥(387.19), 110 목천(329.91), 115 대전(271.94), 120 황간(222.38), 125 남구미(167.25), 130 동김천(192.00), 135 경주(68.26), 140 부산(0)
- 실제 거리(실수)
#Distance from Seoul : 0, 19.75, 77.03, 135, 184.56, 214.94, 239.69, 338.68, 406.94
- 정수(올림)
# Distance from Seoul : 0, 20, 77, 135, 185, 240, 215, 339, 407
** map() : 값을 치환하는 함수
data['도착영업소코드'] = data['도착영업소코드'].map({105: 20, 110: 77, 115: 135, 120: 185, 125: 240, 130: 215, 135: 339, 140: 407})
6. 데이터 프레임 작성
- 도착영업소코드 컬럼명을 ‘거리’로 변경
data.rename(columns={'도착영업소코드': '거리'}, inplace=True)
- 거리가 부산(407)인 데이터만 추출
data_destination = data[data['거리'].isin([407])]
- 3개의 요인('집계시', '요일', '거리')로 groupby를 하고, '통행시간'의 평균값을 낸 데이터 프레임 생성
data_time = data_destination.groupby(['집계시','요일','거리'])['통행시간'].mean()
- 거리(407)값이 있는 축의 위치 변경
data_distance = data_time.unstack(level=-1)
- Null 값 제거 처리
data_distance.dropna()
- 1차원 도표로 변형
data_out = data_distance.reset_index()
- describe() : 통계치 계산
stat = data_out.describe()
print(stat)
** 25%, 75% 값을 사용할 예정이다.
- 25%, 75%의 통행시간 데이터를 추출
value_25 = stat[407][4]
value_75 = stat[407][6]
print(value_25, value_75)
** stat 또한 객체이다.
- Grade라는 컬럼을 새로 만들어서, 초기값 0을 삽입
data_out['Grade'] = 0
- Grade 계산용 함수 작성
def get_grade(input):
if input > value_25:
if input > value_75: output = 2
else: output = 1
else: output = 0
return output
** 25% 보다 적은 값은 0, 25%보다 크고 75%보다 적으면 1, 75%보다 크면 2
- data_grade라는 새로운 데이터 프레임 생성(time, day, grade라는 컬럼을 가지고 있음)
data_grade = pd.DataFrame(columns=['time', 'day', 'grade'])
- data_out의 수만큼 Loop를 돌면서 data_grade 데이터 프레임에 값을 삽입한다.
** grade컬럼 입력 값은 get_grade함수를 통해 계산된 값이 입력된다.
** iterrows() : 인덱스 한 개씩 루프를 돌 때 사용한다.
for index, item in data_out.iterrows():
print(index, item['집계시'], item['요일'])
data_grade = data_grade.append({
'time': item['집계시'],
'day': item['요일'],
'grade': get_grade(item[407])
}, ignore_index=True)
** ignore_index=True : 인덱스는 참조하지 않음.
** Grade 컬럼의 값은 0~2 사이의 값이다.
- 데이터 프레임을 (Tensorflow에서 사용하기 위해서)리스트로 변경
# Dataframe to List
data_list = data_grade.values.tolist()
- 모델 학습
# Generate Train dataset
x_train = [ r[:2] for r in data_list ]
y_train = [ int(r[-1]) for r in data_list ]
- 필요한 라이브러리 import
import tensorflow as tf
import numpy as np
# One hot encode [0, 1, 2] to [[1,0,0], [0,1,0], [0,0,1]]
# 2진법으로 변경 : 0은 1,0,0
y_one_hot = tf.keras.utils.to_categorical(y_train)
- 상수 설정 : 미분 계수, 학습 횟수
learning_rate = 1e-2
learning_epochs = 1000
- 모델링
# Stochastic gradient descent (SGD) Optimizer
sgd = tf.keras.optimizers.SGD(learning_rate=learning_rate)
** 모델 종류 Sequential
** Layer(Output)종류 Dense, 개수 3개, Input이 2개임.
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(3, input_shape=(2,), activation='softmax'))
** activation='softmax' : multinomial classification이기 때문에 softmax사용
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
** loss='categorical_crossentropy' : 최저값 계산 방법
- 모델 구조 확인
model.summary()
- 학습
# Train the model
history = model.fit(np.array(x_train), np.array(y_one_hot), epochs=learning_epochs)
** one hot구조는 numpy를 사용하지 않으면 에러가 발생한다.
** 학습 데이터 양이 적어서 정확도가 57%정도 밖에 되지 않는다.
- 학습 결과 그래프 생성
plt.figure(figsize=(10,10))
plt.plot(history.history['loss'])
plt.show()
- 100번 단위로 학습 결과 출력
print("%20s %20s %20s" % ('학습량', '비용', '정확도')+'\n')
for step in range(learning_epochs):
if step % 100 == 0:
cost_val = history.history['loss'][step]
acc_val = history.history['accuracy'][step]
print("%20i %20.5f %20.5f" % (step, cost_val, acc_val))
** 정확도가 70~80%정도인 것이 좋음.
- input format생성 (목요일 14시)
Time = 14 #@param {type:"slider", min:0, max:23, step:1}
Day = 3 #@param {type:"slider", min:0, max:6, step:1}
- 선택한 시간과 요일 조건에 해당하는 데이터 생성
time_condition = data_out['집계시'] == Time
day_condition = data_out['요일'] == Day
selected_data = data_out[time_condition & day_condition]
- 예상 Prediction
input = [Time, Day]
result = model.predict(np.array([input]))
grade_list = ['빠름', '보통', '느림']
grade_index = np.argmax(result[0])
grade = grade_list[grade_index]
print("%30s" % ('속도 등급')+'\n')
print("%30s" % (grade)+'\n')
print(result[0], grade_index)
** result[0]는 probability의 리스트이다.
** Probability가 가장 큰 것을 취득.
** 1번째가 3개 중에 가장 큰 값이므로 grade가 1이 나온다.
기재: 본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
패스트캠퍼스 [직장인 실무교육]
프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.
fastcampus.co.kr