비트교육센터/AI

[비트교육센터][AI] 7일차 이미지분석

달의요정루나 2023. 8. 10. 01:28

1. 이미지 인식 원리

- MINST 데이터셋: 미국 국립표준기술원이 고등학생과 인구조사국 직원 등이 쓴 손글씨를 이용해 만든 데이터로 구성되어 있다.

- 7만 개의 글자 이미지에 각각 0과 9까지 이름표를 붙인 데이터셋이다.

1. 모듈 임포트, 학습셋과 테스트셋 생성하기

from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical

import matplotlib.pyplot as plt
import sys

import os
os.environ['KMP_DUPLICATE_LIB_OK']="TRUE"
#라이브러리 충돌로 dead kernel이 뜨는 경우가 있다.
#이를 막아준다.
(X_train, y_train),(X_test, y_test)=mnist.load_data()
#mnist데이터를 훈련데이터와 테스트데이터에 넣는다.

--> 결과

Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11490434/11490434 [==============================] - 2s 0us/step

2. 데이터셋

[1] 훈련데이터 개수

print(X_train.shape[0])

--> 결과

60000

[2] 테스트데이터 개수

print(X_test.shape[0])

--> 결과

10000

[3] 훈련데이터 이미지수

X_train.shape#28*28크기의 그림이 60000장

--> 결과

(28, 28)

3. 손글씨 데이터 이미지

plt.imshow(X_train[0], cmap='Greys')
plt.show()

--> 결과

4. 그림의 각 좌표를 숫자표 표현하기

for x in X_train[0]:
    for i in x:
        sys.stdout.write("%-3s"%i)
    sys.stdout.write('\n')#포맷 형식으로 출력

--> 결과

0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  3  18 18 18 12613617526 1662552471270  0  0  0  
0  0  0  0  0  0  0  0  30 36 94 15417025325325325325322517225324219564 0  0  0  0  
0  0  0  0  0  0  0  49 23825325325325325325325325325193 82 82 56 39 0  0  0  0  0  
0  0  0  0  0  0  0  18 2192532532532532531981822472410  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  80 15610725325320511 0  43 1540  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  14 1  15425390 0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  1392531902  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  11 19025370 0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  35 2412251601081  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  81 24025325311925 0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  45 18625325315027 0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  16 93 2522531870  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  24925324964 0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  46 1301832532532072  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  39 1482292532532532501820  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  24 11422125325325325320178 0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  23 66 21325325325325319881 2  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  18 17121925325325325319580 9  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  55 17222625325325325324413311 0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  13625325325321213513216 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

5. 1차원 속성 개수

X_train = X_train.reshape(X_train.shape[0],28*28)
X_train = X_train.astype(float) / 255.

X_test = X_test.reshape(X_test.shape[0],28*28).astype(float) / 255.

6. 데이터셋

[1] 레이블 값

print(y_train[0])

--> 결과

5

[2] 원 핫 인코딩

- 원 핫 인코딩: 단어 집합의 크기를 벡터의 차원으로 하고, 표현하고 싶은 단어의 인덱스에 1의 값을 부여하고, 다른 인덱스에는 0을 부여하는 단어의 벡터 표현 방식이다.

y_train = to_categorical(y_train)#10개를 인식해 10차원의 원핫인코딩을 전개
y_test = to_categorical(y_test)

[3] 원핫 인코딩 이후

print(y_train[0])

--> 결과

[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]

2. 이미지 인식 원리

1. 모듈 임포트

from tensorflow.keras import models, layers
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
import matplotlib.pyplot as plt
import numpy as np

2. 딥러닝 프레임 만들기

model=models.Sequential()
model.add(layers.Dense(512, input_dim=28*28,activation='relu'))
#입력값(input_dim)이 784개, 은닉층이 512개이고 은닉층의 확성화 함수는 relu를 사용

model.add(layers.Dense(10,activation='softmax'))
#출력은 10개이고 출력층에서는 softmax를 사용했다.

model.summary()

--> 결과

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 512)               401920    
                                                                 
 dense_1 (Dense)             (None, 10)                5130      
                                                                 
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________

3. 모델 실행하기

[1] 모델 컴파일

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

# 모델 최적화를 위한 설정구간입니다.
MODEL_DIR = 'model/'
if not os.path.exists(MODEL_DIR):
    os.mkdir(MODEL_DIR)

modelpath = "model/MNIST_MLP.h5"
checkpointer = ModelCheckpoint(filepath=modelpath, monitor='val_loss', verbose=1, save_best_only=True)
early_stopping = EarlyStopping(monitor='val_loss', patience=10)

[2] 모델 실행하기

h = model.fit(X_train, y_train, validation_split=0.25, epochs=30,
              batch_size=200, verbose=0, callbacks=[early_stopping,checkpointer])

--> 결과

Epoch 1: val_loss improved from inf to 0.18637, saving model to model\MNIST_MLP.h5

Epoch 2: val_loss improved from 0.18637 to 0.13461, saving model to model\MNIST_MLP.h5

Epoch 3: val_loss improved from 0.13461 to 0.11268, saving model to model\MNIST_MLP.h5

Epoch 4: val_loss improved from 0.11268 to 0.10050, saving model to model\MNIST_MLP.h5

Epoch 5: val_loss improved from 0.10050 to 0.09596, saving model to model\MNIST_MLP.h5

Epoch 6: val_loss improved from 0.09596 to 0.09317, saving model to model\MNIST_MLP.h5

Epoch 7: val_loss improved from 0.09317 to 0.08675, saving model to model\MNIST_MLP.h5

Epoch 8: val_loss improved from 0.08675 to 0.08568, saving model to model\MNIST_MLP.h5

Epoch 9: val_loss did not improve from 0.08568

Epoch 10: val_loss improved from 0.08568 to 0.08421, saving model to model\MNIST_MLP.h5

Epoch 11: val_loss improved from 0.08421 to 0.08210, saving model to model\MNIST_MLP.h5

Epoch 12: val_loss did not improve from 0.08210

Epoch 13: val_loss did not improve from 0.08210

Epoch 14: val_loss did not improve from 0.08210

Epoch 15: val_loss did not improve from 0.08210

Epoch 16: val_loss did not improve from 0.08210

Epoch 17: val_loss did not improve from 0.08210

Epoch 18: val_loss did not improve from 0.08210

Epoch 19: val_loss did not improve from 0.08210

Epoch 20: val_loss did not improve from 0.08210

Epoch 21: val_loss did not improve from 0.08210

- 에포크 11 이후로 더이상 오차가 떨어지지 않는다. 즉, 에포크 11이 베스트 모델임을 알 수 있다.

[3] 정확도 출력하기

print("\n Test Accuracy: %.4f" % (model.evaluate(X_test, y_test)[1]))

--> 결과

313/313 [==============================] - 1s 1ms/step - loss: 0.0729 - accuracy: 0.9811

 Test Accuracy: 0.9811

4. 학습셋과 테스트셋의 오차변화

y_vloss = h.history['val_loss']
y_loss = h.history['loss']

# 그래프로 표현해 봅니다.
x_len = np.arange(len(y_loss))
plt.plot(x_len, y_vloss, marker='.', c="red", label='Testset_loss')
plt.plot(x_len, y_loss, marker='.', c="blue", label='Trainset_loss')

# 그래프에 그리드를 주고 레이블을 표시해 보겠습니다.
plt.legend(loc='upper right')
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

--> 결과

5. Convolution

Convolution

  • 공간 영역 기반 처리
  • mask 내의 원소값과 공간영역에 있는 입력영상의 화소값들을 대응되게 곱해 출력화소값을 계산
  • 이 과정을 모든 출력화소값에 대해 이동하며 수행하는 방법
  • 이때 곱해지는 mask를 kernel, window 또는 filter라고도 함
  • 옆으로 한칸씩가는 것을 stride라고함
 

Convolution > Blurring

  • 영상을 밝게 수정하며 약간 흐리게 처리하는 기법(뽀샵)
  • 영상에서 화소값이 급격하게 변하는 부분들을 감소시켜 점진적으로 변하게함
  • 전체적으로 부드러운 느낌이 나게 만듦

Edge: 화소값이 급격히 변하는 부분

 

3. 컨볼루션 신경망(CNN)

1. 모듈 임포트하기

from tensorflow.keras import models, layers
from tensorflow.keras.callbacks import ModelCheckpoint,EarlyStopping
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical

import matplotlib.pyplot as plt
import numpy as np
import os
os.environ['KMP_DUPLICATE_LIB_OK']="TRUE"

2. 데이터 설계, 모덜구조 설정

[1] MNIST데이터 불러오고 테스트셋과 학습셋으로 나누기

(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(X_train.shape[0], 28, 28, 1).astype(float) / 255 #4차원
X_test = X_test.reshape(X_test.shape[0], 28, 28, 1).astype(float) / 255
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

[2] 모델구조 설계하기

model=models.Sequential()
model.add(layers.Conv2D(32, kernel_size=(3,3), input_shape=(28,28,1),#스트라이드 할때마다 한줄씩 사라진다.
                       activation='relu'))#3*3*32+32=320
# 1번째 layer 설계
# 순서 = 출력채널 개수(32) / kernel 사이즈(3,3) / 입력(28,28,1) = (width(28), height(28), channel(1)) / 활성화함수
# 커널을 여러개 둠으로서 이미지의 특성을 잡아낸다
# Stride 전에 편향값을 더함.
# Conv2D 함수 공식 : (input_channel_size * kernel_size) * output + bias = parameter 의 개수
# 1번째 layer : (1*9) * 32 + 32 = 320

model.add(layers.Conv2D(64, kernel_size=(3,3), activation='relu'))
# Stride 되면서 각 size 2가 감소 = input_shape=(26,26,32) 
#즉, 이미지 사이즈가 줄면서 channel 값이 output 값 (32)으로 바뀐다.
# 중간 layer : (32*9) * 64 + 64 = 18496  => (32*9)의 의미 = kernel_size=(3,3) 가 32개가 input 으로 들어왔다는 것
# 마찬가지로 Stride 되면서 각 size 2가 감소 = input_shape=(24,24,64) 
#즉, 사이즈가 줄면서 channel 값이 output 값 (64)으로 바뀐다.

model.add(layers.MaxPooling2D(pool_size=(2,2)))#맥스 풀링
# MaxPooling2D : 이미지의 특성만 유지한채 사이즈만 낮춤.
# 2*2 사이즈로 맥스풀링 진행 (결국은 각 나누기 2가 됨)
# 즉 MaxPooling이 되면 input_shape=(24,24,64) => input_shape=(12,12,64)

model.add(layers.Dropout(0.25))
# 드롭아웃 기법 : 역전파 시 무작위로 25퍼센트(0.25)를 추려서 학습을 안시킴 => 과적합 방지

model.add(layers.Flatten())
# Flatten : 1차원 배열로 전환하여 Dense 층의 활성화 함수를 사용 가능하게 함.

model.add(layers.Dense(128, activation='relu'))
#Dense함수 계산
# 9216 * 128 + 128 = 1179776

model.add(layers.Dropout(0.5))
# 드롭아웃 기법 : 역전파 시 무작위로 50퍼센트(0.5)를 추려서 학습을 안시킴 => 과적합 방지

model.add(layers.Dense(10, activation='softmax'))
# 128 * 10 + 10 = 1290

model.summary()

- 맥스풀링: 이미지의 특성만 유지한채 사이즈만 낮추어서 복잡성을 줄이는 방법이다.

- 드롭아웃: 은닉층에 배치된 노드 중 일부를 잠시 꺼서 과적합을 방지한다.

- 플래튼: 1차원 배열로 전환하여 Dense 층의 활성화 함수를 사용 가능하게 하는 방법이다.

--> 결과

Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d_3 (Conv2D)           (None, 26, 26, 32)        320       
                                                                 
 conv2d_4 (Conv2D)           (None, 24, 24, 64)        18496     
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 12, 12, 64)       0         
 2D)                                                             
                                                                 
 dropout_2 (Dropout)         (None, 12, 12, 64)        0         
                                                                 
 flatten_1 (Flatten)         (None, 9216)              0         
                                                                 
 dense_2 (Dense)             (None, 128)               1179776   
                                                                 
 dropout_3 (Dropout)         (None, 128)               0         
                                                                 
 dense_3 (Dense)             (None, 10)                1290      
                                                                 
=================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0
_________________________________________________________________

 

 

cnn_param.xlsx
0.01MB

3. 모델 설정

[1] 모델 실행 환경 설정, 최적화를 위한 설정 구간 정하기

model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
modelpath="./model/MNIST_CNN.hdf5"
checkpointer = ModelCheckpoint(filepath=modelpath, monitor='val_loss', verbose=1, 
                               save_best_only=True)
early_stopping = EarlyStopping(monitor='val_loss', patience=10)

[2] 모델 실행

history = model.fit(X_train, y_train, validation_split=0.25, epochs=30, batch_size=200, verbose=0, 
                    callbacks=[early_stopping,checkpointer])

--> 결과

Epoch 1: val_loss improved from inf to 0.08021, saving model to ./model\MNIST_CNN.hdf5

Epoch 2: val_loss improved from 0.08021 to 0.06165, saving model to ./model\MNIST_CNN.hdf5

Epoch 3: val_loss improved from 0.06165 to 0.05123, saving model to ./model\MNIST_CNN.hdf5

Epoch 4: val_loss improved from 0.05123 to 0.04632, saving model to ./model\MNIST_CNN.hdf5

Epoch 5: val_loss improved from 0.04632 to 0.04070, saving model to ./model\MNIST_CNN.hdf5

Epoch 6: val_loss did not improve from 0.04070

Epoch 7: val_loss did not improve from 0.04070

Epoch 8: val_loss improved from 0.04070 to 0.04058, saving model to ./model\MNIST_CNN.hdf5

Epoch 9: val_loss improved from 0.04058 to 0.03803, saving model to ./model\MNIST_CNN.hdf5

Epoch 10: val_loss did not improve from 0.03803

Epoch 11: val_loss did not improve from 0.03803

Epoch 12: val_loss did not improve from 0.03803

Epoch 13: val_loss did not improve from 0.03803

Epoch 14: val_loss did not improve from 0.03803

Epoch 15: val_loss did not improve from 0.03803

Epoch 16: val_loss did not improve from 0.03803

Epoch 17: val_loss did not improve from 0.03803

Epoch 18: val_loss did not improve from 0.03803

Epoch 19: val_loss did not improve from 0.03803

[3] 테스트 정확도 출력

print("\n Test Accuracy: %.4f" % (model.evaluate(X_test, y_test)[1]))

--> 결과

313/313 [==============================] - 2s 4ms/step - loss: 0.0318 - accuracy: 0.9915

 Test Accuracy: 0.9915

4. 오차저장, 그래프 표현

y_vloss = history.history['val_loss']
y_loss = history.history['loss']

# 그래프로 표현해 봅니다.
x_len = np.arange(len(y_loss))
plt.plot(x_len, y_vloss, marker='.', c="red", label='Testset_loss')
plt.plot(x_len, y_loss, marker='.', c="blue", label='Trainset_loss')

# 그래프에 그리드를 주고 레이블을 표시해 보겠습니다.
plt.legend(loc='upper right')
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

--> 결과

 

4. 개와 고양이 분류

1. 고양이와 개 사진 받기

https://www.kaggle.com/

 

Kaggle: Your Machine Learning and Data Science Community

Kaggle is the world’s largest data science community with powerful tools and resources to help you achieve your data science goals.

www.kaggle.com

2. 고양이와 개 사진 경로에 넣기

- 데이터 폴더에 dogs_vs_cats폴더를 만들고 안에 train과 test폴더를 만든다.(경로는 아래와 같다.)

data─dogs_vs_cats ─train─cats

                              │       └─dogs

                              └─test─cats

                                      └─dogs

- train.zip파일에서 고양이와 개 사진을 압출풀기한다.

- train폴더에 먼저 cats,dogs사진을 총 1만장을 넣는다.(zip파일에 있는 사진을 보면 각 고양이와 개 사진에 번호가 있다. 여기서 0번~9999번을 넣으면 된다.)

- test폴더에는 남은 cats, dogs사진을 2500장을 넣으면 된다. 2500장은 train폴더에 넣고 난 후의 나머지 사진들이다.

3. 디렉토리 경로, 모듈 임포트

[1] 디렉토리 경로 설정

train_dir = 'data/dogs_vs_cats/train'
test_dir = 'data/dogs_vs_cats/test'

[2] 모듈 임포트

from tensorflow.keras import models, layers
from tensorflow.keras.callbacks import ModelCheckpoint,EarlyStopping
import matplotlib.pyplot as plt
import numpy as np
import os
os.environ['KMP_DUPLICATE_LIB_OK']="TRUE"

4. 모델 신경망 정의

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.summary()

--> 결과

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 148, 148, 32)      896       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 74, 74, 32)       0         
 )                                                               
                                                                 
 conv2d_1 (Conv2D)           (None, 72, 72, 64)        18496     
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 36, 36, 64)       0         
 2D)                                                             
                                                                 
 conv2d_2 (Conv2D)           (None, 34, 34, 128)       73856     
                                                                 
 max_pooling2d_2 (MaxPooling  (None, 17, 17, 128)      0         
 2D)                                                             
                                                                 
 conv2d_3 (Conv2D)           (None, 15, 15, 128)       147584    
                                                                 
 max_pooling2d_3 (MaxPooling  (None, 7, 7, 128)        0         
 2D)                                                             
                                                                 
 flatten (Flatten)           (None, 6272)              0         
                                                                 
 dropout (Dropout)           (None, 6272)              0         
                                                                 
 dense (Dense)               (None, 512)               3211776   
                                                                 
 dense_1 (Dense)             (None, 1)                 513       
                                                                 
=================================================================
Total params: 3,453,121
Trainable params: 3,453,121
Non-trainable params: 0
_________________________________________________________________

5. 모델 컴파일

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

6. 모듈 임포트, 제너레이터 생성

[1]  모듈 임포트

from tensorflow.keras.preprocessing.image import ImageDataGenerator

[2] 제너레이터 생성

train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # 타깃 디렉터리
        train_dir,
        # 모든 이미지를 150 × 150 크기로 바꿈
        target_size=(150, 150),
        batch_size=20,
        # binary_crossentropy 손실을 사용하기 때문에 이진 레이블이 필요
        class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
        test_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='binary')

--> 결과

Found 20000 images belonging to 2 classes.
Found 5000 images belonging to 2 classes.

7. 모델 실행

[1] 모델경로 정하기, earlystopping 설정

model_path = 'model/dogs-vs-cats.hdf5'
early_stopping = EarlyStopping(monitor='val_loss', patience=5)
checkpoint = ModelCheckpoint(filepath=model_path, monitor='val_loss', 
                                       verbose=1, save_best_only=True)

[2] 모델 실행

history = model.fit(
      train_generator,
      epochs=50,
      validation_data=validation_generator,
      callbacks=[early_stopping, checkpoint])

--> 결과

Epoch 1/50
1000/1000 [==============================] - ETA: 0s - loss: 0.6520 - accuracy: 0.6036
Epoch 1: val_loss improved from inf to 0.56948, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 211s 210ms/step - loss: 0.6520 - accuracy: 0.6036 - val_loss: 0.5695 - val_accuracy: 0.7112
Epoch 2/50
1000/1000 [==============================] - ETA: 0s - loss: 0.5464 - accuracy: 0.7230
Epoch 2: val_loss improved from 0.56948 to 0.48575, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 217s 217ms/step - loss: 0.5464 - accuracy: 0.7230 - val_loss: 0.4857 - val_accuracy: 0.7642
Epoch 3/50
1000/1000 [==============================] - ETA: 0s - loss: 0.4647 - accuracy: 0.7810
Epoch 3: val_loss improved from 0.48575 to 0.40483, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 216s 216ms/step - loss: 0.4647 - accuracy: 0.7810 - val_loss: 0.4048 - val_accuracy: 0.8228
Epoch 4/50
1000/1000 [==============================] - ETA: 0s - loss: 0.3899 - accuracy: 0.8232
Epoch 4: val_loss improved from 0.40483 to 0.34880, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 225s 225ms/step - loss: 0.3899 - accuracy: 0.8232 - val_loss: 0.3488 - val_accuracy: 0.8440
Epoch 5/50
1000/1000 [==============================] - ETA: 0s - loss: 0.3329 - accuracy: 0.8553
Epoch 5: val_loss improved from 0.34880 to 0.33199, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 213s 213ms/step - loss: 0.3329 - accuracy: 0.8553 - val_loss: 0.3320 - val_accuracy: 0.8566
Epoch 6/50
1000/1000 [==============================] - ETA: 0s - loss: 0.2812 - accuracy: 0.8788
Epoch 6: val_loss improved from 0.33199 to 0.31032, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 212s 212ms/step - loss: 0.2812 - accuracy: 0.8788 - val_loss: 0.3103 - val_accuracy: 0.8672
Epoch 7/50
1000/1000 [==============================] - ETA: 0s - loss: 0.2515 - accuracy: 0.8921
Epoch 7: val_loss improved from 0.31032 to 0.29437, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 216s 216ms/step - loss: 0.2515 - accuracy: 0.8921 - val_loss: 0.2944 - val_accuracy: 0.8786
Epoch 8/50
1000/1000 [==============================] - ETA: 0s - loss: 0.2156 - accuracy: 0.9087
Epoch 8: val_loss improved from 0.29437 to 0.27219, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 216s 216ms/step - loss: 0.2156 - accuracy: 0.9087 - val_loss: 0.2722 - val_accuracy: 0.8856
Epoch 9/50
1000/1000 [==============================] - ETA: 0s - loss: 0.1921 - accuracy: 0.9215
Epoch 9: val_loss improved from 0.27219 to 0.26132, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 207s 207ms/step - loss: 0.1921 - accuracy: 0.9215 - val_loss: 0.2613 - val_accuracy: 0.8958
Epoch 10/50
1000/1000 [==============================] - ETA: 0s - loss: 0.1699 - accuracy: 0.9312
Epoch 10: val_loss improved from 0.26132 to 0.25786, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 213s 213ms/step - loss: 0.1699 - accuracy: 0.9312 - val_loss: 0.2579 - val_accuracy: 0.8946
Epoch 11/50
1000/1000 [==============================] - ETA: 0s - loss: 0.1549 - accuracy: 0.9388
Epoch 11: val_loss did not improve from 0.25786
1000/1000 [==============================] - 204s 203ms/step - loss: 0.1549 - accuracy: 0.9388 - val_loss: 0.2703 - val_accuracy: 0.8928
Epoch 12/50
1000/1000 [==============================] - ETA: 0s - loss: 0.1421 - accuracy: 0.9431
Epoch 12: val_loss improved from 0.25786 to 0.25778, saving model to model\dogs-vs-cats.hdf5
1000/1000 [==============================] - 204s 204ms/step - loss: 0.1421 - accuracy: 0.9431 - val_loss: 0.2578 - val_accuracy: 0.8960
Epoch 13/50
1000/1000 [==============================] - ETA: 0s - loss: 0.1218 - accuracy: 0.9517
Epoch 13: val_loss did not improve from 0.25778
1000/1000 [==============================] - 204s 204ms/step - loss: 0.1218 - accuracy: 0.9517 - val_loss: 0.2797 - val_accuracy: 0.8944
Epoch 14/50
1000/1000 [==============================] - ETA: 0s - loss: 0.1128 - accuracy: 0.9564
Epoch 14: val_loss did not improve from 0.25778
1000/1000 [==============================] - 213s 213ms/step - loss: 0.1128 - accuracy: 0.9564 - val_loss: 0.2732 - val_accuracy: 0.8964
Epoch 15/50
1000/1000 [==============================] - ETA: 0s - loss: 0.0963 - accuracy: 0.9636
Epoch 15: val_loss did not improve from 0.25778
1000/1000 [==============================] - 209s 209ms/step - loss: 0.0963 - accuracy: 0.9636 - val_loss: 0.2899 - val_accuracy: 0.8940
Epoch 16/50
1000/1000 [==============================] - ETA: 0s - loss: 0.0935 - accuracy: 0.9646
Epoch 16: val_loss did not improve from 0.25778
1000/1000 [==============================] - 203s 203ms/step - loss: 0.0935 - accuracy: 0.9646 - val_loss: 0.3287 - val_accuracy: 0.8946
Epoch 17/50
1000/1000 [==============================] - ETA: 0s - loss: 0.0886 - accuracy: 0.9667
Epoch 17: val_loss did not improve from 0.25778
1000/1000 [==============================] - 207s 207ms/step - loss: 0.0886 - accuracy: 0.9667 - val_loss: 0.3126 - val_accuracy: 0.9014