기본 설정
- 필수 모듈 불러오기
- 그래프 출력 관련 기본 설정 지정
# 파이썬 ≥3.5 필수
import sys
assert sys.version_info >= (3, 5)
# 사이킷런 ≥0.20 필수
import sklearn
assert sklearn.__version__ >= "0.20"
# 공통 모듈 임포트
import numpy as np
import os
# 노트북 실행 결과를 동일하게 유지하기 위해
np.random.seed(42)
# 깔끔한 그래프 출력을 위해
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)
# 그림을 저장할 위치
PROJECT_ROOT_DIR = "."
CHAPTER_ID = "training_linear_models"
IMAGES_PATH = os.path.join(PROJECT_ROOT_DIR, "images", CHAPTER_ID)
os.makedirs(IMAGES_PATH, exist_ok=True)
def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
print("그림 저장:", fig_id)
if tight_layout:
plt.tight_layout()
plt.savefig(path, format=fig_extension, dpi=resolution)
# 어레이 데이터를 csv 파일로 저장하기
def save_data(fileName, arrayName, header=''):
np.savetxt(fileName, arrayName, delimiter=',', header=header, comments='')
목표
A. 사진을 낮과 밤으로 분류하는 로지스틱 회귀 모델을 구현.
B. 사진을 낮과 밤, 실내와 실외로 분류하는 다중 레이블 분류 모델을 두 개의 로지스틱 회귀 모델을 이용하여 구현.
!git clone https://github.com/hyoungteak/Assignment.git
fatal: destination path 'Assignment' already exists and is not an empty directory.
원래는 구글드라이브에서 나만 사용할 수 있도록 가져왔지만, 깃허브를 만들고 이미지 100개를 넣어놨었다.
깃허브에서 제대로 가져왔는지 "inside_day1.jpg"를 출력해서 확인해보자.
from IPython.display import Image
Image('/content/Assignment/Machine Learning Assignment 4/Daynight picture/inside_day1.jpg')

잘 가져온 것 같다. 하지만 사진이 너무 크니 데이터를 전처리해보자. 우선 하나만 100X100으로 만들어보자
from PIL import Image
import numpy as np
import sys
import os
import csv
import matplotlib.pyplot as plt
import cv2
fname = '/content/Assignment/Machine Learning Assignment 4/Daynight picture/inside_day1.jpg'
original = cv2.imread(fname, cv2.IMREAD_COLOR)
original = cv2.resize(original, (100, 100)).flatten()
gray = cv2.imread(fname, cv2.IMREAD_GRAYSCALE)
gray = cv2.resize(gray, (100, 100)).flatten()
np_ori = np.asarray(original)
np_gray = np.asarray(gray)
plt.figure(figsize=(10,10))
plt.subplot(1, 2, 1)
plt.imshow(np_ori.reshape(100, 100, 3))
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(np_gray.reshape(100, 100))
plt.axis('off')
(-0.5, 99.5, 99.5, -0.5)

from PIL import Image
import numpy as np
import sys
import os
import csv
import matplotlib.pyplot as plt
def createFileList(myDir, format='.jpg'):
fileList = []
print(myDir)
for root, dirs, files in os.walk(myDir, topdown=False):
for name in files:
if name.endswith(format):
fullName = os.path.join(root, name)
fileList.append(fullName)
return fileList
myFileList = createFileList('/content/Assignment/Machine Learning Assignment 4/Daynight picture/')
file_name = os.listdir('/content/Assignment/Machine Learning Assignment 4/Daynight picture/')
for file in myFileList:
img_file = Image.open(file)
img_file = img_file.resize((100,100))
img_grey = img_file.convert('L')
# Save Greyscale values
value = np.asarray(img_grey.getdata(), dtype=np.int).reshape((img_grey.size[1], img_grey.size[0]))
value = value.flatten()
with open("img_pixels_grey.csv", 'a') as f:
writer = csv.writer(f)
writer.writerow(value)
/content/Assignment/Machine Learning Assignment 4/Daynight picture/
우선 사진 100개를 100X100로 만들고 csv파일로 만들었다.
그리고 0~10000개의 요소를 가지고있는데 각 픽셀의 값이 들어가 있다.
흑백 사진과 마찬가지로 RGB값을 따로 특성으로 저장하기 위해 color 값도 진행하였다.
우선 사진을 그대로 리사이즈하고 색상을 따로 뽑아오는게 안되서 폴더를 새로 만들고 새로 사진을 저장한 후 진행하였다.
밑은 폴더가 없을 경우 새로 생성해주고 있을 경우에는 그냥 넘어가는 코드이다.
def createFolder(directory):
try:
if not os.path.exists(directory):
os.makedirs(directory)
except OSError:
print ('Error: Creating directory. ' + directory)
createFolder('/content/Assignment/Machine Learning Assignment 4/resize picture/')
import glob
for f in myFileList:
img = Image.open(f)
img_resize = img.resize((100, 100))
title, ext = os.path.split(f)
img_resize.save('/content/Assignment/Machine Learning Assignment 4/resize picture/re_' + ext)
resize picture 폴더에 re_"원래 이름".jpg로 저장하게 하는 코드이다.
myFileList = createFileList('/content/Assignment/Machine Learning Assignment 4/resize picture/')
for file in myFileList:
img_file = plt.imread(file)
blue,green,red = cv2.split(img_file)
# Save values
value1 = blue.reshape((10000, ))
with open("img_pixels_blue.csv", 'a') as f:
writer = csv.writer(f)
writer.writerow(value1)
value2 = green.reshape((10000, ))
with open("img_pixels_green.csv", 'a') as f:
writer = csv.writer(f)
writer.writerow(value2)
value3 = red.reshape((10000, ))
with open("img_pixels_red.csv", 'a') as f:
writer = csv.writer(f)
writer.writerow(value3)
/content/Assignment/Machine Learning Assignment 4/resize picture/
흑백 사진 Daynight도 그랬듯, RGB값도 csv 파일로 생성한다.
참고로 100X100으로 되어있기 때문에 (10000, )로 reshape 해주었다.
import pandas as pd
daynight = pd.read_csv('/content/img_pixels_grey.csv', header=None)
pdred = pd.read_csv('/content/img_pixels_red.csv', header=None)
pdblue = pd.read_csv('/content/img_pixels_blue.csv', header=None)
pdgreen = pd.read_csv('/content/img_pixels_green.csv', header=None)
Daynight = pd.DataFrame([daynight.sum(axis=1)/10000])
Red = pd.DataFrame([pdred.sum(axis=1)/10000])
Blue = pd.DataFrame([pdblue.sum(axis=1)/10000])
Green = pd.DataFrame([pdgreen.sum(axis=1)/10000])
Daynight = Daynight.transpose()
Red = Red.transpose()
Blue = Blue.transpose()
Green = Green.transpose()
sum 같은 경우 100X10000의 파일을 100X1로 만들어 주며
나머지는 10000으로 나누어서 평균 값을 내서 하나의 데이터프레임으로 만들었다.
행과 열이 반대로 되어있기 때문에 transpose()도 해주었다.
Daynight
175.2140 |
58.2355 |
166.9674 |
18.4557 |
132.9310 |
... |
110.9626 |
182.2209 |
173.3185 |
17.8795 |
109.0425 |
300 rows × 1 columns
Red
182.6963 |
129.9181 |
78.9987 |
76.7620 |
163.7860 |
... |
43.5304 |
164.4514 |
17.0507 |
12.3792 |
12.1525 |
300 rows × 1 columns
이제 실내 실외 낮 밤 특성을 만들고 싶어서 사진의 저장된 내용중에서 숫자와 따옴표 .jpg를 제거했다.
# inside와 outdoor 구분
a = []
for x in file_name:
a.append(x.strip("'0123456789.jpg").replace('_day', '').replace('_night', ''))
filename = pd.DataFrame([a])
# day와 night 구분
a = []
for x in file_name:
a.append(x.strip("'0123456789.jpg").replace('inside_', '').replace('outdoor_', ''))
filename2 = pd.DataFrame([a])
filename = filename.transpose()
filename2 = filename2.transpose()
filename
inside |
inside |
inside |
outdoor |
outdoor |
... |
inside |
outdoor |
outdoor |
outdoor |
inside |
100 rows × 1 columns
이제 저 위에 값에서 원핫인코딩을 해보자.
from sklearn.preprocessing import OneHotEncoder
cat_encoder = OneHotEncoder(sparse=False)
day_cat_1hot = cat_encoder.fit_transform(filename)
ins_cat_1hot = cat_encoder.fit_transform(filename2)
filename = pd.DataFrame((day_cat_1hot),
columns=['day', 'night']
)
filename2 = pd.DataFrame((ins_cat_1hot),
columns=['inside', 'outdoor']
)
잘 저장되었다. 이제 아까 사진을 나눈 값을 붙이자.
print(filename)
print(filename2)
day night
0 1.0 0.0
1 1.0 0.0
2 1.0 0.0
3 0.0 1.0
4 0.0 1.0
.. ... ...
95 1.0 0.0
96 0.0 1.0
97 0.0 1.0
98 0.0 1.0
99 1.0 0.0
[100 rows x 2 columns]
inside outdoor
0 1.0 0.0
1 0.0 1.0
2 1.0 0.0
3 0.0 1.0
4 1.0 0.0
.. ... ...
95 0.0 1.0
96 1.0 0.0
97 1.0 0.0
98 0.0 1.0
99 1.0 0.0
[100 rows x 2 columns]
result = pd.concat([filename, filename2],axis=1)
result['grey_value'] = Daynight
result['red_value'] = Red
result['blue_value'] = Blue
result['green_value'] = Green
result
1.0 | 0.0 | 1.0 | 0.0 | 175.2140 | 182.6963 | 130.5215 | 161.4120 |
1.0 | 0.0 | 0.0 | 1.0 | 58.2355 | 129.9181 | 136.2071 | 132.5114 |
1.0 | 0.0 | 1.0 | 0.0 | 166.9674 | 78.9987 | 87.5054 | 101.1256 |
0.0 | 1.0 | 0.0 | 1.0 | 18.4557 | 76.7620 | 95.6989 | 83.4178 |
0.0 | 1.0 | 1.0 | 0.0 | 132.9310 | 163.7860 | 116.2202 | 143.4958 |
... | ... | ... | ... | ... | ... | ... | ... |
1.0 | 0.0 | 0.0 | 1.0 | 110.9626 | 43.5304 | 19.1344 | 30.2640 |
0.0 | 1.0 | 1.0 | 0.0 | 182.2209 | 164.4514 | 155.2196 | 175.7053 |
0.0 | 1.0 | 1.0 | 0.0 | 173.3185 | 17.0507 | 23.3901 | 20.4376 |
0.0 | 1.0 | 0.0 | 1.0 | 17.8795 | 12.3792 | 36.8602 | 23.5785 |
1.0 | 0.0 | 1.0 | 0.0 | 109.0425 | 12.1525 | 15.5223 | 15.1234 |
100 rows × 8 columns
데이터프레임이 완성되었다. 만들어진 특성들로 로지스틱 회귀를 진행해보자.
y = result['grey_value'].copy()
X = result.drop("grey_value", axis=1)
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint
from sklearn.ensemble import RandomForestRegressor
param_distribs = {
'n_estimators': randint(low=1, high=100),
'max_features': randint(low=1, high=8),
}
forest_reg = RandomForestRegressor(random_state=42)
rnd_search = RandomizedSearchCV(forest_reg, param_distributions=param_distribs,
n_iter=10, cv=5, scoring='neg_mean_squared_error', random_state=42)
rnd_search.fit(X, y)
RandomizedSearchCV(cv=5, estimator=RandomForestRegressor(random_state=42),
param_distributions={'max_features': ,
'n_estimators': },
random_state=42, scoring='neg_mean_squared_error')
cvres = rnd_search.cv_results_
for mean_score, params in zip(cvres["mean_test_score"], cvres["params"]):
print(np.sqrt(-mean_score), params)
26.05841808897192 {'max_features': 7, 'n_estimators': 52}
27.052589404906765 {'max_features': 5, 'n_estimators': 15}
26.16327350561695 {'max_features': 3, 'n_estimators': 72}
26.756638748339206 {'max_features': 5, 'n_estimators': 21}
25.9947306772051 {'max_features': 7, 'n_estimators': 83}
26.058376561669142 {'max_features': 7, 'n_estimators': 75}
26.05429257645039 {'max_features': 3, 'n_estimators': 88}
26.585086704098014 {'max_features': 5, 'n_estimators': 24}
25.82468406737417 {'max_features': 3, 'n_estimators': 22}
29.98842297348637 {'max_features': 5, 'n_estimators': 2}
from sklearn.metrics import mean_squared_error
final_model = rnd_search.best_estimator_
final_predictions = final_model.predict(X)
# RMSE 평가
final_mse = mean_squared_error(y, final_predictions)
final_rmse = np.sqrt(final_mse)
데이터 세트를 대상으로 한 최종 성능(RMSE)은 아래와 같다.
final_rmse
11.124000090901687
얻어진 테스트 RMSE에 대한 95% 신뢰 구간을 계산하여 확률적으로 시스템의 성능을 예측할 수 있다.
- scipy의 stats 모듈 활용
- 아래 코드는 t-분포를 이용하여 신뢰구간 계산
from scipy import stats
confidence = 0.95
squared_errors = (final_predictions - y) ** 2
np.sqrt(stats.t.interval(confidence, len(squared_errors) - 1,
loc=squared_errors.mean(),
scale=stats.sem(squared_errors)))
array([ 9.02420996, 12.88605412])
요약
낮과 밤, 실내와 실외로 구분되는 100장의 사진을 분류하는 모델 구현
2021-05-03
- 우선 사진은 구글에서 가져왔으며, 학습 목표를 달성하기 위해 사용되었다.
- 구글 코랩에서 제작되었는데 사진을 가져올 때 내 드라이브에서 import 시켰기 때문에 다른 사람이 실행하면 제대로 돌아가지 않는다.
- 특성 값이 동일하게 나와야 모델을 제작할 수 있기 때문에 100X100의 값으로 사진의 크기를 조정하였고, 각 픽셀 별로 0~255의 밝기 특성 값을 받는다.
- 또한 낮, 밤, 실내, 실외를 따로 구분해서 범주형 특성을 만들었다.
과제였기 때문에 시간 안에 내는게 중요해서 특성을 이렇게 두가지 밖에 만들지 못했다. 생각해놓은 특성을 조금 나열하자면 255/2 = 127.5의 값을 이용해 낮과 밤을 구분할 수 있게 만드는 특성과 Color를 표현하는 값인 RGB의 값을 특성으로 넣어서, 갈색(Red) 계열이 높은 실내와 Blue, Green의 계열이 높은 실외를 구분할 수 있게 제작하고 싶다.
2021-05-12
- 우선 드라이브에서 import하는 방식에서 내 Github 주소에서 가져오는 형식으로 바뀌었다. 그래서 누구든 실행하면 사진을 잘 가져오게 된다.
- 우선 inside_day, inside_night, outdoor_day, outdoor_night로 나누었던 특성을 inside, outdoor, day, night로 새롭게 나누었다. 이러는 편이 더 모델에 효과적일 것이다.
- 처음에는 grey 값만 가져왔었는데, 이제는 R, G, B 값을 각각 가져왔다. 그냥 grey scale만 가져오는 것에 비해서 복잡하게 되어있어서 시간이 많이 걸렸다.
- resize picture라는 새로운 폴더를 만들어 100X100 사진을 새로 만들어서 사용하였다.
- 참고 문헌: 핸즈온 머신러닝
- Githun link: 머신러닝 실습 4