2019年6月8日 星期六

[影像辨識] 解決樣本空間太少的圖像辨識問題

import os, shutil
original_dataset_dir=r'dogs-vs-cats/train'
base_dir=r'cats_and_dogs_small'
if not os.path.isdir(base_dir): os.mkdir(base_dir)
train_dir=os.path.join(base_dir,'train_dir')
if not os.path.isdir(train_dir):os.mkdir(train_dir)  #建立訓練的檔案夾

validation_dir=os.path.join(base_dir,'validation_dir')
if not os.path.isdir(validation_dir):os.mkdir(validation_dir)  #建立驗證的檔案夾

test_dir=os.path.join(base_dir,'test_dir')
if not os.path.isdir(test_dir):os.mkdir(test_dir) #建立測試的檔案夾

train_cat_dir=os.path.join(train_dir,'train_cat_dir')
if not os.path.isdir(train_cat_dir):os.mkdir(train_cat_dir)  #建立貓訓練的檔案的夾

train_dog_dir=os.path.join(train_dir,'train_dog_dir')
if not os.path.isdir(train_dog_dir):os.mkdir(train_dog_dir)  #建立狗訓練的檔案夾

validation_cat_dir=os.path.join(validation_dir,'validation_cat_dir')
if not os.path.isdir(validation_cat_dir):os.mkdir(validation_cat_dir)  #建立貓驗證的檔案夾

validation_dog_dir=os.path.join(validation_dir,'validation_dog_dir')
if not os.path.isdir(validation_dog_dir):os.mkdir(validation_dog_dir)  #建立狗驗證的檔案夾

test_cat_dir=os.path.join(test_dir,'test_cat_dir')
if not os.path.isdir(test_cat_dir):os.mkdir(test_cat_dir)  #建立貓測試的檔案夾

test_dog_dir=os.path.join(test_dir,'test_dog_dir')
                                                                                                                                                                                            uif not os.path.isdir(test_dog_dir):os.mkdir(test_dog_dir)  #建立狗測試的檔案夾

#複製前面1000張圖片到train_cat_dir訓練目錄下
fname=['cat.{}.jpg'.format(i) for i in range(1000)]
for fname in fname:
    src=os.path.join(original_dataset_dir,fname)
    dst=os.path.join(train_cat_dir,fname)
    shutil.copyfile(src,dst)

#複製下500張圖片到validation_cat_dir訓練目錄下
fname=['cat.{}.jpg'.format(i) for i in range(1000,1500)]
for fname in fname:
    src=os.path.join(original_dataset_dir,fname)
    dst=os.path.join(validation_cat_dir,fname)
    shutil.copyfile(src,dst)
#複製下500張圖片到test_cat_dir訓練目錄下 fname=['cat.{}.jpg'.format(i) for i in range(1500,2000)] for fname in fname: src=os.path.join(original_dataset_dir,fname) dst=os.path.join(test_cat_dir,fname) shutil.copyfile(src,dst)
#複製前面1000張圖片到train_dog_dir訓練目錄下
fname=['dog.{}.jpg'.format(i) for i in range(1000)]
for fname in fname:
    src=os.path.join(original_dataset_dir,fname)
    dst=os.path.join(train_dog_dir,fname)
    shutil.copyfile(src,dst)
#複製下500張圖片到validation_dog_dir訓練目錄下
fname=['dog.{}.jpg'.format(i) for i in range(1000,1500)]
for fname in fname:
    src=os.path.join(original_dataset_dir,fname)
    dst=os.path.join(validation_dog_dir,fname)
    shutil.copyfile(src,dst)
#複製下500張圖片到test_dog_dir訓練目錄下
fname=['dog.{}.jpg'.format(i) for i in range(1500,2000)]
for fname in fname:
    src=os.path.join(original_dataset_dir,fname)
    dst=os.path.join(test_dog_dir,fname)
    shutil.copyfile(src,dst)
print('訓練用的貓圖片數',len(os.listdir(train_cat_dir)))
print('驗證用的貓圖片數',len(os.listdir(validation_cat_dir)))
print('測試用的貓圖片數',len(os.listdir(test_cat_dir)))
print('訓練用的狗圖片數',len(os.listdir(train_dog_dir)))
print('驗證用的狗圖片數',len(os.listdir(validation_dog_dir)))
print('測試用的狗圖片數',len(os.listdir(test_dog_dir)))

#建立神經網路
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.Flatten())
model.add(layers.Dense(512,activation='relu'))
model.add(layers.Dense(1,activation='sigmoid'))
model.summary()

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

#資料預處理
#1. 讀取檔案 2. 將JPEG內容解碼成RGB像素 3. 將RGB像素轉換成福點數張量 4.將像素(0-255)轉換成(0-1)區間
#可以利用keras.preprocessing.image的ImageDataGenerator快速設定Python產生器,自動將影像擋轉換成批次張量
from keras.preprocessing.image import ImageDataGenerator
train_datagen=ImageDataGenerator(rescale=1./255)
test_datagen=ImageDataGenerator(rescale=1./255)
train_generator=train_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')

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

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

model.save('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(1,len(acc)+1)
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()

因為訓練影像數目少,容易造成overdfit問題,overfit問題解法 1. 使用資料擴增法訓練的樣本空間變大 2. 使用regularization #使用keras不需要設定 3. 使用dropout將神經網路的變數減少 以下使用資料擴增法
#可以利用keras.preprocessing.image的ImageDataGenerator擴增資料
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_cat_dir,fname) for fname in os.listdir(train_cat_dir)]
#用image.load_img()讀取第三張照片
img=image.load_img(fnames[3],target_size=(150,150))
img

#將影像轉換成矩陣
x=image.img_to_array(img) #影像轉換成(150,150,3)的矩陣
x=x.reshape((1,)+x.shape)  #影像轉換成(1,150,150,3)的矩陣
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%3==0:
        break
plt.show()

以上我們知道了如何將有限的樣本空間用keras.preprocessing.image的ImageDataGenerator擴增資料 使用資料擴增法訓練的樣本空間變大 使用dropout將神經網路的變數減少 以下我們要用這兩個方法來解決overfit問題
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.Flatten())
model.add(layers.Dropout(0.5))  #加入dropout層丟棄50%資料
model.add(layers.Dense(512,activation='relu'))
model.add(layers.Dense(1,activation='sigmoid'))
from keras import optimizers
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,
                                                  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=10,
                            epochs=50, 
                            validation_data=validation_generator,
                            validation_steps=50)
model.save('cats_and-dogs_small_2.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(1,len(acc)+1)
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()

model.save('cats_and-dogs_small_2.h5')

三倍槓桿和一倍槓桿的長期定期定額報酬率分析

  以下是中國,美國股票債卷的三倍槓桿和一倍槓桿ETF分析.可以發現,三倍槓桿在下跌時期的跌幅遠比一倍槓桿的多 .且從時間軸來看,三倍槓桿由於下跌力道較強,因此會把之前的漲幅都吃掉,所以對於長期上身的市場,例如美國科技股,由於上升時間遠比下跌時間長,所以持有TQQQ的長期回報率會...