windows10(64位)Anaconda3+Python3.6搭建Tensorflow(cpu版本)及keras+用Jupyter notebook運行Kaggle狗貓數據集+提高模分類模型精度

windows10(64位)Anaconda3+Python3.6搭建Tensorflow(cpu版本)及keras

一、安裝TensorFlow

1.打開Anaconda Prompt

conda  --version  //檢查Anaconda是否成功安裝(如果成功會顯示版本號)
conda create -n tensorflow pip python=3.6  //創建一個名爲tensorflow的conda環境
activate tensorflow  //激活TensorFlow 

激活後前端會有一個(tensorflow)的標誌:

在這裏插入圖片描述

2.要安裝TensorFlow的純CPU版本,輸入以下命令:(激活下)

pip install --ignore-installed --upgrade tensorflow

若這報錯E:\MyDownloads\Anaconda3\Anaconda3\envs\tensorflow\Scripts\pip-script.py”, line 6, in from pip._internal.cli.main import mainModuleNotFoundError: No module named ‘pip._internal.cli.main’

解決辦法:

easy_install pip
pip install --ignore-installed --upgrade tensorflow

3.查看目前安裝了哪些環境,確保名叫tensorflow的環境已經被成功添加:

deactivate #退出TensorFlow環境
conda info --envs 

在這裏插入圖片描述

二、安裝keras

在激活tensorflow環境下

pip install keras

在這裏插入圖片描述在這裏插入圖片描述

三、用Jupyter notebook運行Kaggle狗貓數據集

1.圖形管理界面,選擇TensorFlow環境,打開Jupyter notebook,進行編輯,第一次打開需要下載

在這裏插入圖片描述

2.創建.ipynb

在這裏插入圖片描述

3.下載數據集

貓狗數據集鏈接 提取碼:dmp4
在這裏插入圖片描述

4.根據命名對圖片分類結果展示:

分類前目錄:

在這裏插入圖片描述

分類後目錄如下:

在這裏插入圖片描述
生成的的cats_and_dogs_small具體內容如下:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
很好的將貓和狗分類了出來。

5.圖片分類

①導入Keras庫並查看版本

import keras
keras.__version__

運行結果:
在這裏插入圖片描述

②圖片分類

import os, shutil #複製文件
# 原始目錄所在的路徑
# 數據集未壓縮
original_dataset_dir = 'D:\\Study\\人工智能與機器學習\\project\\train'

# 我們將在其中的目錄存儲較小的數據集
base_dir = 'D:\\Study\\人工智能與機器學習\\project\\cats_and_dogs_small'
os.mkdir(base_dir)

# # 訓練、驗證、測試數據集的目錄
train_dir = os.path.join(base_dir, 'train')
os.mkdir(train_dir)
validation_dir = os.path.join(base_dir, 'validation')
os.mkdir(validation_dir)
test_dir = os.path.join(base_dir, 'test')
os.mkdir(test_dir)

# 貓訓練圖片所在目錄
train_cats_dir = os.path.join(train_dir, 'cats')
os.mkdir(train_cats_dir)

# 狗訓練圖片所在目錄
train_dogs_dir = os.path.join(train_dir, 'dogs')
os.mkdir(train_dogs_dir)

# 貓驗證圖片所在目錄
validation_cats_dir = os.path.join(validation_dir, 'cats')
os.mkdir(validation_cats_dir)

# 狗驗證數據集所在目錄
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
os.mkdir(validation_dogs_dir)

# 貓測試數據集所在目錄
test_cats_dir = os.path.join(test_dir, 'cats')
os.mkdir(test_cats_dir)

# 狗測試數據集所在目錄
test_dogs_dir = os.path.join(test_dir, 'dogs')
os.mkdir(test_dogs_dir)

# 將前1000張貓圖像複製到train_cats_dir
fnames = ['cat.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_cats_dir, fname)
    shutil.copyfile(src, dst)

# 將下500張貓圖像複製到validation_cats_dir
fnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_cats_dir, fname)
    shutil.copyfile(src, dst)
    
# 將下500張貓圖像複製到test_cats_dir
fnames = ['cat.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_cats_dir, fname)
    shutil.copyfile(src, dst)
    
# 將前1000張狗圖像複製到train_dogs_dir
fnames = ['dog.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_dogs_dir, fname)
    shutil.copyfile(src, dst)
    
# 將下500張狗圖像複製到validation_dogs_dir
fnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_dogs_dir, fname)
    shutil.copyfile(src, dst)
    
# 將下500張狗圖像複製到test_dogs_dir
fnames = ['dog.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_dogs_dir, fname)
    shutil.copyfile(src, dst)

③作爲健全性檢查,讓我們計算一下在每個訓練分割中我們有多少圖片(訓練/驗證/測試):

print('total training cat images:', len(os.listdir(train_cats_dir)))
print('total training dog images:', len(os.listdir(train_dogs_dir)))
print('total validation cat images:', len(os.listdir(validation_cats_dir)))
print('total validation dog images:', len(os.listdir(validation_dogs_dir)))
print('total test cat images:', len(os.listdir(test_cats_dir)))
print('total test dog images:', len(os.listdir(test_dogs_dir)))

在這裏插入圖片描述

6.卷積神經網絡CNN

簡介:快速開發基準模型:面對一個任務,通常需要快速驗證想法,並不斷迭代。因此開發基準模型通常需要快速,模型能跑起來,效果比隨機猜測好一些就行,不用太在意細節。至於正則化、圖像增強、參數選取等操作,後續會根據需要來進行。

①網絡模型搭建

model.summary()輸出模型各層的參數狀況

from keras import layers
from keras import models

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.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

**model.summary()輸出模型各層的參數狀況,讓我們來看看要素地圖的尺寸是如何隨每個連續圖層而變化的:

model.summary()

在這裏插入圖片描述

②圖像生成器讀取文件中數據,進行數據預處理。

from keras import optimizers

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['acc'])
from keras.preprocessing.image import ImageDataGenerator

# 所有圖像將按1/255重新縮放
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # 這是目標目錄
        train_dir,
        # 所有圖像將調整爲150x150
        target_size=(150, 150),
        batch_size=20,
        # 因爲我們使用二元交叉熵損失,我們需要二元標籤
        class_mode='binary')

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

在這裏插入圖片描述

讓我們看一下其中一個生成器的輸出:它生成150x150rgb圖像(shape(20,150,150,3))和二進制標籤(shape(20,))。20是每批樣品的數量(批量大小)。注意,生成器無限期地生成這些批:它只是在目標文件夾中的圖像上無休止地循環。因此,我們需要在某個點上中斷迭代循環。

for data_batch, labels_batch in train_generator:
    print('data batch shape:', data_batch.shape)
    print('labels batch shape:', labels_batch.shape)
    break

在這裏插入圖片描述

③開始訓練

讓我們使用生成器將模型與數據擬合。我們使用fit_generator方法來實現它,這相當於我們這樣的數據生成器的fit。它希望第一個參數是Python生成器,它將無限期地生成一批輸入和目標,就像我們的一樣。由於數據是無休止地生成的,生成器需要知道在聲明一個紀元結束之前要從生成器中抽取多少樣本。這是steps_per_epoch參數的作用:從生成器中繪製steps_per_epoch批後,即在運行steps_per_epoch梯度下降步驟後,擬合過程將轉到下一個epoch。在我們的例子中,批次是20個大樣本,因此它將需要100個批次,直到我們看到2000個樣本的目標。當使用fit_生成器時,可以傳遞一個validation_數據參數,這與fit方法非常相似。重要的是,這個參數可以是數據生成器本身,但也可以是Numpy數組的元組。如果將生成器作爲驗證數據傳遞,則此生成器將無休止地生成多批驗證數據,因此還應指定validation_steps參數,該參數告訴進程要從驗證生成器中提取多少批進行計算。

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,
      epochs=30,
      validation_data=validation_generator,
      validation_steps=50)

在這裏插入圖片描述

④保存訓練模型

model.save('D:\\Study\\人工智能與機器學習\\project\\cats_and_dogs_small_1.h5')

⑤在培訓和驗證數據上繪製模型的損失和準確性(可視化界面)

import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

運行結果
在這裏插入圖片描述
分析:這些曲線圖具有過度擬合的特點。隨着時間的推移,我們的訓練準確率呈線性增長,直到接近100%,而我們的驗證準確率則停滯在70-72%。我們的驗證損失在五個階段後達到最小,然後停止,而訓練損失保持線性下降,直到接近0。

7.根據基準模型進行調整

爲了解決過擬合問題,可以減小模型複雜度,也可以用一系列手段去對沖,比如增加數據(圖像增強、人工合成或者多蒐集真實數據)、L1/L2正則化、dropout正則化等。這裏主要介紹CV中最常用的圖像增強。

①使用數據擴充

數據增強採用的方法是從現有的訓練樣本中生成更多的訓練數據,通過一個數字“增強”樣本產生可信的圖像的隨機變換。我們的目標是在訓練的時候,我們的模型永遠不會看到完全一樣的結果想象兩次。這有助於模型暴露於數據的更多方面,並更好地進行泛化。

datagen = ImageDataGenerator(
      rotation_range=40,
      width_shift_range=0.2,
      height_shift_range=0.2,
      shear_range=0.2,
      zoom_range=0.2,
      horizontal_flip=True,
      fill_mode='nearest')
# 這是帶有圖像預處理實用程序的模塊
from keras.preprocessing import image

fnames = [os.path.join(train_cats_dir, fname) for fname in os.listdir(train_cats_dir)]

# 我們選擇一個圖像來“增強”
img_path = fnames[3]

# 讀取圖像並調整其大小
img = image.load_img(img_path, target_size=(150, 150))

# 將其轉換爲具有形狀的Numpy數組(150、150、3)
x = image.img_to_array(img)

# 把它改成(1150150,3)
x = x.reshape((1,) + x.shape)

# 下面的.flow()命令生成一批隨機轉換的圖像。
# 它將無限循環,所以我們需要在某個時刻“打破”循環!
i = 0
for batch in datagen.flow(x, batch_size=1):
    plt.figure(i)
    imgplot = plt.imshow(image.array_to_img(batch[0]))
    i += 1
    if i % 4 == 0:
        break

plt.show()

運行結果
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

如果我們使用這種數據增強配置訓練一個新網絡,我們的網絡將永遠不會看到兩次相同的輸入。但是,輸入它所看到的仍然是高度相關的,因爲它們來自於少量的原始圖像——我們無法產生新的信息,我們只能重新混合現有的信息。因此,這可能還不足以完全擺脫過度裝修。繼續戰鬥過度擬合,我們還將在密連接分類器之前向模型添加一個退出層:

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.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['acc'])

②使用數據擴充和退出來訓練我們的網絡

train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,)

# 請注意,不應增加驗證數據!
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # 這是目標目錄
        train_dir,
        # 所有圖像將調整爲150x150
        target_size=(150, 150),
        batch_size=32,
        # 因爲我們使用二元交叉熵損失,我們需要二元標籤
        class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,
      epochs=100,
      validation_data=validation_generator,
      validation_steps=50)

運行時間較長本人花了一個小時左右,儘量關門其他佔用CPU軟件
在這裏插入圖片描述
直到運行100%
在這裏插入圖片描述

③保存模型

model.save('D:\\Study\\人工智能與機器學習\\project\\cats_and_dogs_small_2.h5')

④在培訓和驗證數據上繪製模型的損失和準確性(可視化界面)

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

在這裏插入圖片描述
由於數據的增加和丟失,我們不再過度擬合:訓練曲線非常接近於驗證曲線。我們現在能夠達到82%的精度,比非正則模型相對提高了15%。通過進一步利用正則化技術和調整網絡參數(例如每個卷積的濾波器數量層,或者網絡中的層數),我們可以得到更好的精度,可能高達86-87%。然而,這將證明僅僅通過從頭開始訓練我們自己的convnet就很難再上一層樓,因爲我們要處理的數據太少了。作爲一個下一步,爲了提高我們在這個問題上的準確性,我們必須利用一個預先訓練過的模型。

四、使用預先訓練網絡和特徵抽取大力提升圖像識別率

1.在我們構造卷積網絡時,一開始先是好幾層卷積層和Max Pooling層,然後會調用Flatten()把他們輸出的多維向量壓扁後,傳入到普通層,下面代碼就是我們前幾節做過的卷積網絡,它的結構正如我們剛纔描述的那樣:

from keras import layers
from keras import models
from keras import optimizers

model = models.Sequential()
#輸入圖片大小是150*150 3表示圖片像素用(R,G,B)表示
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.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer=optimizers.RMSprop(lr=1e-4),
             metrics=['acc'])

model.summary()

在這裏插入圖片描述

2.我們現在要借用的的VGG16網絡,其結構與上面差不多,只不過它的Conv2D和MaxPooling層要比我們上面做的多得多而已。在我們借用別人訓練好的網絡時,往往要去掉Flatten()後面的網絡層,因爲那些網絡層與別人構造網絡時的具體應用場景相關,他們的應用場景與我們肯定不同,我們要借用的是Flatten上面那些由卷積層和Max Pooling層輸出的結果,這些結果蘊含着對訓練圖片本質的認知,這纔是我們想要的,去掉Flatten後面的神經層,換上我們自己的神經層,這個行爲就叫特徵抽取,具體流程如下圖:

在這裏插入圖片描述

3.VGG16網絡早已包含在keras框架中,我們可以方便的直接引用,我們通過如下代碼來初始化一個VGG16網絡實例:

from keras.applications import VGG16

conv_base = VGG16(weights = 'vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5', include_top = False, input_shape=(150, 150, 3))

conv_base.summary()

在這裏插入圖片描述

4.接下來我們將把自己的圖片讀進來,把圖片餵給上面網絡,讓它把圖片的隱含信息給抽取出來:

import os 
import numpy as np
from keras.preprocessing.image import ImageDataGenerator

base_dir = 'D:\\Study\\人工智能與機器學習\\project\\cats_and_dogs_small'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')
test_dir = os.path.join(base_dir, 'test')

datagen = ImageDataGenerator(rescale = 1. / 255)
batch_size = 20

def extract_features(directory, sample_count):
    features = np.zeros(shape = (sample_count, 4, 4, 512))
    labels = np.zeros(shape = (sample_count))
    generator = datagen.flow_from_directory(directory, target_size = (150, 150), 
                                            batch_size = batch_size,
                                            class_mode = 'binary')
    i = 0
    for inputs_batch, labels_batch in generator:
        #把圖片輸入VGG16卷積層,讓它把圖片信息抽取出來
        features_batch = conv_base.predict(inputs_batch)
        #feature_batch 是 4*4*512結構
        features[i * batch_size : (i + 1)*batch_size] = features_batch
        labels[i * batch_size : (i+1)*batch_size] = labels_batch
        i += 1
        if i * batch_size >= sample_count :
            #for in 在generator上的循環是無止境的,因此我們必須主動break掉
            break
        return features , labels

#extract_features 返回數據格式爲(samples, 4, 4, 512)
train_features, train_labels = extract_features(train_dir, 2000)
validation_features, validation_labels = extract_features(validation_dir, 1000)
test_features, test_labels = extract_features(test_dir, 1000)

在這裏插入圖片描述

5.抽取的特徵輸入到我們自己的神經層中進行分類,代碼如下:

train_features = np.reshape(train_features, (2000, 4 * 4 * 512))
validation_features = np.reshape(validation_features, (1000, 4 * 4 * 512))
test_features = np.reshape(test_features, (1000, 4 * 4* 512))

from keras import models
from keras import layers
from keras import optimizers

#構造我們自己的網絡層對輸出數據進行分類
model = models.Sequential()
model.add(layers.Dense(256, activation='relu', input_dim = 4 * 4 * 512))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1, activation = 'sigmoid'))

model.compile(optimizer=optimizers.RMSprop(lr = 2e-5), loss = 'binary_crossentropy', metrics = ['acc'])
history = model.fit(train_features, train_labels, epochs = 30, batch_size = 20, 
                    validation_data = (validation_features, validation_labels))

在這裏插入圖片描述

6.訓練結果和校驗結果可視化

import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)

plt.plot(epochs, acc, 'bo', label = 'Train_acc')
plt.plot(epochs, val_acc, 'b', label = 'Validation acc')
plt.title('Trainning and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label = 'Training loss')
plt.plot(epochs, val_loss, 'b', label = 'Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

在這裏插入圖片描述
從上面可以看出,經過一百多萬張圖片訓練的網絡,其識別效果就要比我們用4000張圖片訓練的網絡要好很多,網絡對圖片的校驗正確率達到了99%以上,同時對訓練數據和校驗數據的損失估計完全是一模一樣的。

7.參數調優

1,將我們自己的網絡層添加到VGG16的卷積層之上。
2,固定VGG16的卷積層保持不變。
3,用數據訓練我們自己添加的網絡層
4,將VGG16的卷積層最高兩層放開
5,用數據同時訓練放開的那兩層卷積層和我們自己添加的網絡層

model = models.Sequential()
#將VGG16的卷積層直接添加到我們的網絡
model.add(conv_base)
#添加我們自己的網絡層
model.add(layers.Flatten())
model.add(layers.Dense(256, activation = 'relu'))
model.add(layers.Dense(1, activation = 'sigmoid'))
model.summary()

在這裏插入圖片描述
從上面輸出結果看,VGG16的卷積層已經有一千多萬個參數了!用個人電腦單個CPU是不可能對這個模型進行訓練的!但我們可以訓練它的其中一部分,我們把它最高三層與我們自己的網絡層結合在一起訓練,同時凍結最低四層。

8.把卷積層進行部分凍結

conv_base.trainable = True
set_trainable = False
#一旦讀取到'block5_conv1'時,意味着來到卷積網絡的最高三層
#可以使用conv_base.summary()來查看卷積層的信息
for layer in conv_base.layers:
    if layer.name == 'block5_conv1':
        set_trainable = True
    if set_trainable:
        #當trainable == True 意味着該網絡層可以更改,要不然該網絡層會被凍結,不能修改
        layer.trainable = True
    else:
        layer.trainable = False

9.然後我們把數據傳入網絡,訓練給定的卷積層和我們自己的網絡層

#把圖片數據讀取進來
test_datagen = ImageDataGenerator(rescale = 1. / 255)
train_generator = test_datagen.flow_from_directory(train_dir, target_size = (150, 150), batch_size = 20,
                                                   class_mode = 'binary')
validation_generator = test_datagen.flow_from_directory(validation_dir, target_size = (150,150),
                                                       batch_size = 20,
                                                       class_mode = 'binary')
model.compile(loss = 'binary_crossentropy', optimizer = optimizers.RMSprop(2e-5),
             metrics = ['acc'])

history = model.fit_generator(train_generator, steps_per_epoch = 100, epochs = 30, 
                              validation_data = validation_generator,
                              validation_steps = 50)

在這裏插入圖片描述
跑的太慢了 就終止了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章