In [9]:
import os
import pandas as pd
# 파일과 csv를 포함하는 폴더 경로 지정
path = 'D:/workspaces/WinterStudy2022/pytorchPractice/practice1_scene/train-scene classification/'
# 전체 이미지 개수 출력하기
# 파일 os.listdir를 이용하여 디렉토리 내 파일을 리스트화하여 file_list에 저장한다.
file_list = os.listdir(path + 'train/')
print("file_list 확인 : ",file_list[:5])
print("file_list 타입확인 : ", type(file_list))
print('전체 이미지의 개수:', len(file_list))
file_list 확인 : ['0.jpg', '1.jpg', '10.jpg', '100.jpg', '1000.jpg'] file_list 타입확인 : <class 'list'> 전체 이미지의 개수: 24335
In [10]:
# 학습 이미지 확인하기
dataset = pd.read_csv(path + 'train.csv')
print('학습 이미지의 개수:', len(dataset))
print('학습 이미지별 클래스 정보')
dataset.head()
학습 이미지의 개수: 17034 학습 이미지별 클래스 정보
Out[10]:
image_name | label | |
---|---|---|
0 | 0.jpg | 0 |
1 | 1.jpg | 4 |
2 | 2.jpg | 5 |
3 | 4.jpg | 0 |
4 | 7.jpg | 4 |
In [11]:
# groupby를 활용한 데이터셋 확인
classifications = dataset.groupby(by = dataset['label']).count()
classifications
Out[11]:
image_name | |
---|---|
label | |
0 | 2628 |
1 | 2745 |
2 | 2957 |
3 | 3037 |
4 | 2784 |
5 | 2883 |
In [12]:
from skimage.transform import resize
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
# 경로 내 첫 번째 이미지를 호출
img = Image.open(path + 'train/' + file_list[0])
# 이미지를 array화
img = np.asarray(img)
# image를 64 * 64 * 3 형태로 변환
img = resize(img, (64, 64, 3))
print('이미지의 해상도:', img.shape)
# matplotlib을 활용하여 이미지 호출
# 이미지 출력하기
plt.imshow(img)
plt.show()
이미지의 해상도: (64, 64, 3)
In [13]:
from sklearn.model_selection import train_test_split
# 모든 데이터를 train_dataset과 val_dataset으로 분리하여 저장
train_dataset, val_dataset = train_test_split(dataset, test_size=0.2)
print('학습 데이터셋 크기:', len(train_dataset))
print('검증 데이터셋 크기:', len(val_dataset))
학습 데이터셋 크기: 13627 검증 데이터셋 크기: 3407
In [14]:
temp_list = []
temp_list2 = []
for index, row in train_dataset.iterrows():
temp_img = Image.open(path + 'train/' + train_dataset.loc[index]['image_name'])
temp_img = np.asarray(temp_img)
temp_img = resize(temp_img, (64, 64, 3))
temp_list.append(temp_img)
temp_list2.append(train_dataset.loc[index]['label'])
temp_list3 = []
temp_list4 = []
for index, row in val_dataset.iterrows():
temp_img2 = Image.open(path + 'train/' + val_dataset.loc[index]['image_name'])
temp_img2 = np.asarray(temp_img)
temp_img2 = resize(temp_img, (64, 64, 3))
temp_list3.append(temp_img)
temp_list4.append(val_dataset.loc[index]['label'])
In [20]:
X_train = np.asarray(temp_list)
X_train.shape
Out[20]:
(13627, 64, 64, 3)
In [21]:
y_train = np.asarray(temp_list2)
y_train.shape
Out[21]:
(13627,)
In [18]:
X_test = np.asarray(temp_list3)
X_test.shape
Out[18]:
(3407, 64, 64, 3)
In [19]:
y_test = np.asarray(temp_list4)
y_test.shape
Out[19]:
(3407,)
In [16]:
# 데이터셋에서 각 클래스에 따른 일부 데이터를 시각화
# classes = [label name]
classes = ['buildings', 'forests', 'glacier', 'mountains', 'sea', 'street']
# 출력할 이미지 지정 (각 분류당)
samples_per_class = 5
np.flatnonzero(조건 or data)
: ()안에 적힌 내용을 확인하여 0이 아닌 값을 return
In [22]:
# 데이터 시각화 함수 구현
def visualize_data(dataset, classes, samples_per_class):
num_classes = len(classes)
# 각 클래스를 (클래스, 클래스명) 형식으로 순회
for y, cls in enumerate(classes):
# True 값을 갖는 데이터 인덱스 계산
idxs = np.flatnonzero(y_train == y)
# 특정 개수만큼 무작위로 선택
# samples_per_class = 5이므로, 5개를 선택
idxs = np.random.choice(idxs, samples_per_class, replace=False)
# 하나씩 이미지를 확인하며
for i, idx in enumerate(idxs):
# 이미지를 출력할 위치: 각 열(column)에 차례대로 출력하도록 설정
plt_idx = i * num_classes + y + 1
plt.subplot(samples_per_class, num_classes, plt_idx)
plt.imshow(X_train[idx])
plt.axis('off')
if i == 0:
plt.title(cls)
plt.show()
visualize_data(X_train, classes, samples_per_class)
Problem 3. 학습/검증 데이터셋 전처리¶
- 선형모델(linear model)을 학습 예정이므로, 각 이미지를 벡터로 변경한다.
- 다음과 같이 X_train, y_train, X_test, y_test 변수의 shape로 구성하도록 소스코드를 변경한다.
- X_train : (13627, 12288)
- y_train : (13627,)
- X_test : (3407, 12288)
- y_test : (3407,)
- 본 실습에서는 데이터 정규화를 수행하지 않음
<해결과정>
- 12288 = 64 64 3이므로, 너비와 폭, 채널을 모두 하나로 통합하는 것으로 추측함.
- 따라서, 원본 이미지를 1차원화해야 하므로,
np.ravel()
을 사용
In [29]:
temp_list5 = []
temp_list6 = []
for index, row in train_dataset.iterrows():
temp_img = Image.open(path + 'train/' + train_dataset.loc[index]['image_name'])
temp_img = np.asarray(temp_img)
temp_img = resize(temp_img, (64, 64, 3))
# resizing된 img를 1차원 배열로 펼쳐서 저장한다.
temp_list5.append(temp_img.ravel())
temp_list6.append(train_dataset.loc[index]['label'])
temp_list7 = []
temp_list8 = []
for index, row in val_dataset.iterrows():
temp_img2 = Image.open(path + 'train/' + val_dataset.loc[index]['image_name'])
temp_img2 = np.asarray(temp_img2)
temp_img2 = resize(temp_img2, (64, 64, 3))
# resizing된 img를 1차원 배열로 펼쳐서 저장한다.
temp_list7.append(temp_img2.ravel())
temp_list8.append(val_dataset.loc[index]['label'])
In [30]:
X_train = np.asarray(temp_list5)
X_train.shape
Out[30]:
(13627, 12288)
In [31]:
y_train = np.asarray(temp_list6)
y_train.shape
Out[31]:
(13627,)
In [32]:
X_test = np.asarray(temp_list7)
X_test.shape
Out[32]:
(3407, 12288)
In [33]:
y_test = np.asarray(temp_list8)
y_test.shape
Out[33]:
(3407,)
2. 선형 분류 모델 학습¶
- sklearn.linear_model의 Logistic Regression 라이브러리 사용
- GPU 가속을 지원하지 않아 학습속도가 느림
- LogisticRegression 주요 파라미터
- penalty : 정규화 목적으로 사용할 norm 명시 (default = 'l2')
- solver: 최적화를 진행 시 사용할 알고리즘 (default = 'lbfgs')
- max_iter: 수렴을 위해 반복할 횟수 : (default = 100)
- multi_class : 클래스의 개수가 여러 개인지 확인 : (default = 'auto')
- verbose : 자세한 학습결과 표시 여부 (default = 0)
- 적은 횟수로 반복하여 수렴되지 않은 경우, 경고창이 출력될 수 있음.
- 경고창은 max_iter의 값을 증가시켜 해결할 수 있음
ex - 10번의 반복을 수행하여 학습하는 코드
In [ ]:
model = LogisticRegression(multi_class = 'multinomial', solver = 'lbfgs', max_iter = 10 )
In [34]:
from sklearn.linear_model import LogisticRegression
import time
# 코드를 시작한 당시의 시간을 저장
start_time = time.time()
model = LogisticRegression(multi_class="multinomial", solver="lbfgs", max_iter=10)
model.fit(X_train, y_train)
# 학습이 끝난 후의 시간에서 시작할 당시의 시간을 빼서 실행시간 계산
print("소요된 시간(초 단위):", time.time() - start_time) # 실행 시간
소요된 시간(초 단위): 6.989459753036499
D:\Python310\lib\site-packages\sklearn\linear_model\_logistic.py:814: ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. Increase the number of iterations (max_iter) or scale the data as shown in: https://scikit-learn.org/stable/modules/preprocessing.html Please also refer to the documentation for alternative solver options: https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression n_iter_i = _check_optimize_result(
3. 학습 모델의 정확도 계산¶
accuracy_score
method를 활용sklearn.metrics.accuracy_score
: 정확도 분류 점수y_true
: 정답 레이블y_pred
: 프로그램이 반환한 예측 레이블normalize
(boolean) : False일 경우, 정확히 분류된 샘플의 수를 반환, True이면 정확히 분류된 샘플의 비율을 반환sample_weight
: 샘플의 가중치
In [38]:
from sklearn.metrics import accuracy_score
# X_train을 이용하여 모델 훈련
y_pred = model.predict(X_train)
# 학습 데이터셋 y_train으로 모델의 정확도 확인
train_acc = accuracy_score(y_train, y_pred)
print('학습 데이터셋 정확도:', train_acc)
# X_test를 활용하여 모델 훈련
y_pred = model.predict(X_test)
# 검증데이터 y_test를 활용하여 모델 검증
val_acc = accuracy_score(y_test, y_pred)
print('검증 데이터셋 정확도:', val_acc)
# 항목 개수
print('클래스:', model.classes_)
# 모델 학습횟수
print('반복 횟수:', model.n_iter_)
# 학습 가중치 크기
print('학습된 가중치 크기:', model.coef_.shape)
학습 데이터셋 정확도: 0.49012988919057754 검증 데이터셋 정확도: 0.4781332550631054 클래스: [0 1 2 3 4 5] 반복 횟수: [10] 학습된 가중치 크기: (6, 12288)
4. 개별 이미지에 대한 판별 확인¶
- 일부 이미지에 대하여 판별을 수행한 결과를 확인할 수 있다.
In [39]:
# 최대 이미지 출력
max_cnt = 5
# 이미지들이 들어갈 수 있는 틀 생성
fig, axes = plt.subplots(1, max_cnt)
fig.set_size_inches(12, 4)
fig.tight_layout()
for ax, image, label, pred in zip(axes, X_test[:max_cnt], y_test[:max_cnt], model.predict(X_test[:max_cnt])):
# 출력할 때는 이미지 해상도에 맞게 재변형
ax.imshow(np.reshape(image, (64, 64, 3)))
ax.axis('off')
ax.set_title(f'True label: {label}\nPredicted label: {pred}')
5. 모델의 분류 정확성 확인을 위한 Seaborn 그리기¶
- 혼동 행렬을 사용하여 표현 후 heatmap으로 출력하기
In [41]:
from sklearn.metrics import confusion_matrix
import seaborn as sns
cm = confusion_matrix(y_test, y_pred)
df_cm = pd.DataFrame(cm)
df_cm.index.name = 'True label'
df_cm.columns.name = 'Predicted label'
# Seaborn heatmeap을 이용하여 화면에 출력하기
sns.heatmap(df_cm, annot=True, fmt="d", cmap='Blues')
plt.show()
Problem 4. Logistic Regression 모델 성능평가¶
- 주어진 코드를 실행하여 반복횟수가 각각 10, 30, 50, 100, 200, 300회일 때 데이터셋의 정확도를 확인하시오.
In [51]:
from sklearn.linear_model import LogisticRegression
import time
train_acc_list = []
val_acc_list = []
spend_time_list = []
for iter in [10, 30, 50, 100, 200, 300]:
start_time = time.time() # 시작 시간
model = LogisticRegression(multi_class="multinomial",solver="lbfgs", max_iter=iter)
model.fit(X_train, y_train)
print("====================================================")
print(f'[학습 완료(max_iter={iter})]')
y_pred = model.predict(X_train)
train_acc = accuracy_score(y_train, y_pred)
print('학습 데이터셋 정확도:', train_acc)
y_pred = model.predict(X_test)
val_acc = accuracy_score(y_test, y_pred)
print('검증 데이터셋 정확도:', val_acc)
spend = time.time() - start_time
print("소요된 시간(초 단위):", spend) # 실행 시간
train_acc_list.append(train_acc)
val_acc_list.append(val_acc)
spend_time_list.append(spend)
print("====================================================")
D:\Python310\lib\site-packages\sklearn\linear_model\_logistic.py:814: ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. Increase the number of iterations (max_iter) or scale the data as shown in: https://scikit-learn.org/stable/modules/preprocessing.html Please also refer to the documentation for alternative solver options: https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression n_iter_i = _check_optimize_result(
==================================================== [학습 완료(max_iter=10)] 학습 데이터셋 정확도: 0.49012988919057754 검증 데이터셋 정확도: 0.4781332550631054 소요된 시간(초 단위): 6.769888401031494 ====================================================
D:\Python310\lib\site-packages\sklearn\linear_model\_logistic.py:814: ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. Increase the number of iterations (max_iter) or scale the data as shown in: https://scikit-learn.org/stable/modules/preprocessing.html Please also refer to the documentation for alternative solver options: https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression n_iter_i = _check_optimize_result(
==================================================== [학습 완료(max_iter=30)] 학습 데이터셋 정확도: 0.5492037866001321 검증 데이터셋 정확도: 0.5218667449368947 소요된 시간(초 단위): 15.603278636932373 ====================================================
D:\Python310\lib\site-packages\sklearn\linear_model\_logistic.py:814: ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. Increase the number of iterations (max_iter) or scale the data as shown in: https://scikit-learn.org/stable/modules/preprocessing.html Please also refer to the documentation for alternative solver options: https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression n_iter_i = _check_optimize_result(
==================================================== [학습 완료(max_iter=50)] 학습 데이터셋 정확도: 0.5606516474645924 검증 데이터셋 정확도: 0.5371294393894922 소요된 시간(초 단위): 24.166350603103638 ====================================================
D:\Python310\lib\site-packages\sklearn\linear_model\_logistic.py:814: ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. Increase the number of iterations (max_iter) or scale the data as shown in: https://scikit-learn.org/stable/modules/preprocessing.html Please also refer to the documentation for alternative solver options: https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression n_iter_i = _check_optimize_result(
==================================================== [학습 완료(max_iter=100)] 학습 데이터셋 정확도: 0.6060027885814926 검증 데이터셋 정확도: 0.526562958614617 소요된 시간(초 단위): 45.75357985496521 ====================================================
D:\Python310\lib\site-packages\sklearn\linear_model\_logistic.py:814: ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. Increase the number of iterations (max_iter) or scale the data as shown in: https://scikit-learn.org/stable/modules/preprocessing.html Please also refer to the documentation for alternative solver options: https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression n_iter_i = _check_optimize_result(
==================================================== [학습 완료(max_iter=200)] 학습 데이터셋 정확도: 0.6705804652528069 검증 데이터셋 정확도: 0.4910478426768418 소요된 시간(초 단위): 86.30614113807678 ====================================================
D:\Python310\lib\site-packages\sklearn\linear_model\_logistic.py:814: ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. Increase the number of iterations (max_iter) or scale the data as shown in: https://scikit-learn.org/stable/modules/preprocessing.html Please also refer to the documentation for alternative solver options: https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression n_iter_i = _check_optimize_result(
==================================================== [학습 완료(max_iter=300)] 학습 데이터셋 정확도: 0.7201878623321347 검증 데이터셋 정확도: 0.48958027590255354 소요된 시간(초 단위): 125.89518785476685 ====================================================
In [52]:
train_acc_list
Out[52]:
[0.49012988919057754, 0.5492037866001321, 0.5606516474645924, 0.6060027885814926, 0.6705804652528069, 0.7201878623321347]
In [53]:
val_acc_list
Out[53]:
[0.4781332550631054, 0.5218667449368947, 0.5371294393894922, 0.526562958614617, 0.4910478426768418, 0.48958027590255354]
In [55]:
spend_time_list
Out[55]:
[6.769888401031494, 15.603278636932373, 24.166350603103638, 45.75357985496521, 86.30614113807678, 125.89518785476685]
In [74]:
max_iter_list = [10, 30, 50, 100, 200, 300]
original_list = [i for i in range(0, 6, 1)]
In [90]:
figure_set = plt.figure(figsize = (10, 10))
y_set1 = figure_set.add_subplot()
y_set2 = y_set1.twinx()
plt.xticks(original_list, max_iter_list)
y_set1.plot(train_acc_list, label = "train_acc")
y_set1.plot(val_acc_list, label = "val_acc")
y_set1.set_xlabel('max_iter')
y_set1.set_ylabel('Accurancy')
y_set1.tick_params(axis = 'y')
y_set1.legend()
y_set2.plot(spend_time_list, label = "spend_time", color = "r")
y_set2.set_ylabel('time')
y_set2.tick_params(axis = 'y')
y_set2.legend()
plt.show()
- 학습데이터의 정확도는 높아지는 반면, 검증데이터의 정확도는 낮아지고 있음
- 학습 시 소모되는 시간은 기하급수적으로 높아짐.
- 추측 : 사람이 하나의 데이터를 집중적으로 학습하면 이 원리를 다른 곳에 활용하는 능력이 떨어지는 것처럼, 프로그램도 하나의 데이터를 집중적으로 학습하면 해당 데이터에 대한 정확도는 높아지는 반면, 이 원리를 다른 곳에 적용하는 능력이 떨어지는 것이 아닐까 추측함.
- 검증데이터의 정확도도 떨어지며, 학습 시 소모되는 시간도 높아지므로, 학습데이터는 많이 학습시키지 않는 편이 나아보임.
6. Data augmentation : shift와 flip¶
- 데이터에 약간씩 변형을 가하여 데이터셋의 다양성을 증가시킴
- 데이터의 다양성을 증가시켜 분류확률을 높여줄 수 있음
- 이동(shift) : 이미지 이동
- 뒤집기(filp) : 이미지 상하/좌우 반전
In [92]:
from scipy.ndimage.interpolation import shift
def shift_image(image, dx, dy):
image = image.reshape((64, 64, 3))
# dy, dx는 각각 너비, 높이 기준으로 이동할 크기
shifted_image = shift(image, [dy, dx, 0])
return shifted_image.reshape([-1])
def horizontal_flip(image):
image = image.reshape((64, 64, 3))
# 수직 반전(vertical flip): axis=0, 수평 반전(horizontal flip): axis=1
flipped_image = np.flip(image, axis=1)
return flipped_image.reshape([-1])
In [93]:
# 이미지들이 들어갈 수 있는 그림(figure) 생성
fig, axes = plt.subplots(1, 4)
fig.set_size_inches(12, 4)
fig.tight_layout()
image = X_train[0]
shifted_image_up = shift_image(image, 0, -3)
shifted_image_right = shift_image(image, 3, 0)
flipped_image = horizontal_flip(image)
# 출력할 때는 이미지 해상도에 맞게 재변형
axes[0].imshow(np.reshape(image, (64, 64, 3)))
axes[0].set_title('Original')
# 이미지를 위로 이동
axes[1].imshow(np.reshape(shifted_image_up, (64, 64, 3)))
axes[1].set_title('Shifted up')
# 이미지를 오른쪽으로 이동
axes[2].imshow(np.reshape(shifted_image_right, (64, 64, 3)))
axes[2].set_title('Shifted right')
# 이미지를 좌우반전
axes[3].imshow(np.reshape(flipped_image, (64, 64, 3)))
axes[3].set_title('Flipped horizontally')
plt.show()
'전문지식 함양 > TIL' 카테고리의 다른 글
[프로그래머스 겨울방학 인공지능 과정] GAN 이론 기초2 : Image-to-Image Translation with Conditional Adversarial Networks (0) | 2022.02.08 |
---|---|
[프로그래머스 겨울방학 인공지능 과정] GAN 이론 기초 (0) | 2022.02.07 |
[프로그래머스 겨울방학 인공지능 과정] python 풍경 이미지분류 알고리즘의 구현1 (0) | 2022.01.26 |
[프로그래머스 겨울방학 인공지능 과정] pytorch 예제 살펴보기1 (0) | 2022.01.25 |
[프로그래머스 겨울방학 인공지능 과정] 딥러닝 기초이론 (0) | 2022.01.24 |