keras 基礎小記

model.add

model = Sequential()
model.add(Dense(output_dim=1, input_dim=1))

每次model.add就是添加一層,不用寫入權重這些參數。
W, b = model.layers[0].get_weights()是第一層的參數。

特徵標準化

不同特徵所佔比重不同,把特徵們的所佔比重都設置爲差不多,都在(0,1)之間

keras classifier分類 教程

https://morvanzhou.github.io/tutorials/machine-learning/keras/2-2-classifier/

下載mnist數據集

from keras.datasets import mnist  #就開始下載了

(x_train, y_train), (x_test, y_test) = mnist.load_data()

把標籤y變成one-hot形式

mnist數據集的y是對應的某一個數字(0-9),要把它變成1*10的向量,1的話是0100000000的形式,屬於哪個數字,就在哪個位置爲 1,其他位置都是 0的形式,叫做one hot獨熱。

要用到 Keras 改造的 numpy 的一個函數 np_utils.to_categorical

from keras.utils import np_utils

y_train = np_utils.to_categorical(y_train, num_classes=10)

建立神經網絡

1.Sequential,稱爲序貫模型,也就是單輸入單輸出,一條路通到底,層與層之間只有相鄰關係,跨層連接統統沒有
from keras.layers import Dense, Activation
from keras.models import Sequential

model = Sequential([
    Dense(32, input_dim=784),
    Activation('relu'),
    Dense(10),
    Activation('softmax'),
])

或者寫成:

model = Sequential
model.add(Dense(32, input_dim=784))
model.add(Activation('relu'))
model.add(Dense(10))
model.add(Activation('softmax'))

第一層Dense(輸出維度,輸入維度),之後Dense就不用寫輸入維度了,只需要寫輸出維度,默認輸入維度就是上一層的輸出。

model.add 一層一層添加神經層

Dense是2D層,支持通過指定其輸入維度input_dim來隱含的指定輸入數據shape,是一個Int類型的數據
model.add(Dense(32, input_dim=784)) == model.add(Dense(32, input_shape=(784,)))

2.Graph,即圖模型,這個模型支持多輸入多輸出,層與層之間想怎麼連怎麼連,但是編譯速度慢。在Keras1和Keras2中,圖模型被移除,而增加了了“functional model API”,

激活模型

model.compile 激勵神經網絡。

優化器,可以是默認的,也可以是我們在上一步rmsprop = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0)定義的。 損失函數,分類和迴歸問題的不一樣,用的是交叉熵。 metrics,裏面可以放入需要計算的 cost,accuracy,score 等。

# We add metrics to get more results you want to see
model.compile(optimizer=rmsprop,
              loss='categorical_crossentropy',
              metrics=['accuracy'])

這裏若optimizer='rmsproc'加了引號,說明用的是默認的rmsproc優化器,而不是我們上面定義的。

訓練網絡

法一. model.fit函數。

這裏用到的是 fit 函數,把訓練集的 x 和 y 傳入之後,nb_epoch 表示把整個數據訓練多少次,batch_size 每批處理32個。

model.fit(X_train, y_train, epoch=2, batch_size=32)

法二. model.train_on_batch
model.train_on_batch 一批一批的訓練 X_train, Y_train。默認的返回值是 cost

for step in range(301):
cost = model.train_on_batch(X_train, Y_train)
if step % 100 == 0:
    print('train cost: ', cost)
    
   
result = model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

測試模型

用到的函數是 model.evaluate,輸入測試集的x和y, 輸出 costweightsbiases
這裏 weights 和 biases 取的是模型的第一層 model.layers[0] 學習到的參數。

loss, accuracy = model.evaluate(X_test, y_test)
或者cost = model.evaluate(X_test, Y_test, batch_size=40)
print('test loss: ', loss)
print('test accuracy: ', accuracy)
W, b = model.layers[0].get_weights()
print('Weights=', W, '\nbiases=', b)

基礎知識

batch

深度學習的優化算法,說白了就是梯度下降。每次的參數更新有兩種方式。

  1. BGD : 遍歷全部數據集算一次損失函數,然後算函數對各個參數的梯度,更新梯度。這種方法每更新一次參數都要把數據集裏的所有樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲Batch gradient descent,批梯度下降。

  2. SGD : 另一種,每看一個數據就算一下損失函數,然後求梯度更新參數,這個稱爲隨機梯度下降,stochastic gradient descent。這個方法速度比較快,但是收斂性能不太好,可能在最優點附近晃來晃去,hit不到最優點。兩次參數的更新也有可能互相抵消掉,造成目標函數震盪的比較劇烈。

  3. mini-batch : 爲了克服兩種方法的缺點,現在一般採用的是一種折中手段,mini-batch gradient decent,小批的梯度下降,這種方法把數據分爲若干個批,按批來更新參數,這樣,一個批中的一組數據共同決定了本次梯度的方向,下降起來就不容易跑偏,減少了隨機性。另一方面因爲批的樣本數與整個數據集相比小了很多,計算量也不是很大。

基本上現在的梯度下降都是基於mini-batch的,所以Keras的模塊中經常會出現batch_size,就是指這個。

順便說一句,Keras中用的優化器SGD是stochastic gradient descent的縮寫,但不代表是一個樣本就更新一回,還是基於mini-batch的。

epochs

epochs指的就是訓練過程中數據將被“輪”多少次.

驗證集

驗證集的作用是當通過訓練集訓練出多個模型後,爲了能找出效果最佳的模型,使用各個模型對驗證集數據進行預測,並記錄模型準確率。選出效果最佳的模型所對應的參數,即用來調整模型參數。如svm中的參數c和核函數等。

因爲參數是超參數。

keras CNN

參考 https://morvanzhou.github.io/tutorials/machine-learning/keras/2-3-CNN/

數據處理

X_train = X_train.reshape(-1, 1,28, 28)/255.        #(sample, channels(RGB), height, width)

這裏-1代表sample個數, 以後不想特地去知道具體數字,就直接用-1表示即可。

卷積層

model.add(Convolution2D(
    batch_input_shape=(None, 1, 28, 28),
    filters=32,
    kernel_size=5,
    strides=1,
    padding='same',     # Padding method
    data_format='channels_first',
))

filters=32:32個濾波器;

Padding方法是same即不改變數據的長度和寬度

data_format: tensorflow是data_format=‘channels_last’,格式是(-1,28,28,3);而channels_first是(-1,3,28,28)這種形式

全連接層

需要將數據抹平成一維,再添加全連接層FC:

model.add(Flatten())

數據集datesets路徑

自帶的腳本里的地址,下載數據集太慢。可以本地下好,拷貝到~/.keras/datasets/路徑下(隱藏文件夾)

其中:cifar10需要改文件名爲cifar-10-batches-py.tar.gz ,cifar100改爲 cifar-100-python.tar.gz , mnist改爲 mnist.npz

預訓練models放到 ~/.keras/models/ 路徑下面即可。

顯示圖片

from keras.datasets import mnist
import matplotlib.pyplot as plt
(X_train, y_train), (X_test, y_test) = mnist.load_data()

#y_train:0-9的數字 one-hot之前
#來自knn.ipynb
classes = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
num_classes = len(classes)
samples_per_class = 7
for y, cls in enumerate(classes):
    idxs = np.flatnonzero(y_train == y)     # 返回y_train==y時,對應的y_train的下標
    idxs = np.random.choice(idxs, samples_per_class, replace=False) #從這些滿足條件y_train==y的樣本中 隨機選出samples_per_class個
    for i, idx in enumerate(idxs):
        plt_idx = i * num_classes + y + 1
        plt.subplot(samples_per_class, num_classes, plt_idx) #窗口被分爲samples_per_class行,num_classes列
        plt.imshow(X_train[idx].astype('uint8'))
        plt.axis('off')
        if i == 0:
            plt.title(cls)
plt.show()

(1000, )寫法

變量寫成(1000, ),打開看是一列,但其實仍是一行[7,2,1…4,5],不要被騙了。

錯誤集

ValueError: Error when checking target: expected activation_48 to have 2 dimensions, but got array with shape (50000, 1, 10)

這是因爲cifar10y_trainy_test傳進來是(10000,1)就是[[1],[2]]這種表達式,而不是一行,所以要改成(10000,)這種表達式。方法(用reshape):y_test = y_test.reshape(y_test.shape[0], )

畫loss和accuracy的圖

plt.figure
plt.plot(result.epoch,result.history['acc'],label="acc")
plt.plot(result.epoch,result.history['val_acc'],label="val_acc")
plt.scatter(result.epoch,result.history['acc'],marker='*')
plt.scatter(result.epoch,result.history['val_acc'])
plt.legend(loc='under right')
plt.show()

plt.figure
plt.plot(result.epoch,result.history['loss'],label="loss")
plt.plot(result.epoch,result.history['val_loss'],label="val_loss")
plt.scatter(result.epoch,result.history['loss'],marker='*')
plt.scatter(result.epoch,result.history['val_loss'],marker='*')
plt.legend(loc='upper right')
plt.show()

result是前面result = model.fit()

打印中間層輸出

法1.新建model,model的輸入input爲想要輸入的層,輸出output爲想要輸出的層,此mdoel非之前的model,新Model(新名稱)

from keras.models import Model
intermediate_layer_model = Model(inputs=model.input,outputs=model.get_layer('a1').output)   # 新名稱,中間層
# 這裏的get_layer('a1')是上面model.add時命名的,比如model.add(Activation('relu',name='a1'))
# model.add(Dense(num_classes,activation='softmax',name='dense_2'))等等
intermediate_layer = dense1_layer_model.predict(x_train)

print (intermediate_layer.shape)
print (intermediate_layer[0])
plt.imshow(intermediate_layer[0][:][:][0])  #根據變量shape來改
plt.show()

回掉函數callbacks

1.tensorboard
從輸入開始

with tf.name_scope('inputs'):
    xs = tf.placeholder(tf.float32, [None, 1], name='x_input')#這個名字會顯示在tensorboard上
    ys = tf.placeholder(tf.float32, [None, 1], name='y_input')

賦給變量/佔位符一個name,然後前頭的地方用with tf.name_scope('自己取一個'),下面要包含在裏頭的變量,做縮進。
activation不用寫,因爲默認會寫。

with tf.name_scope(layer_name):
        with tf.name_scope('weights'):
            Weights = tf.Variable(tf.random_normal([in_size, out_size]), name='W')
            tf.summary.histogram(layer_name + '/weights', Weights)  #保存成histogram的觀察方式 概率分佈 顏色深出現的多

write:在定義好session(sess = tf.Session())後寫的。

merged = tf.summary.merge_all() #用merge
writer = tf.train.SummaryWriter('logs/', sess.graph)`把整個框架保存,之後才能load到瀏覽器裏
init = tf.global_variables_initializer()
sess.run(init)
for i in range(1000):
    sess.run(train_step, feed_dict={xs: x_data, ys: y_data})
    if i % 50 == 0:
        result = sess.run(merged,
                          feed_dict={xs: x_data, ys: y_data})
        writer.add_summary(result, i)

在終端的log路徑下(前一路徑),先sudo chmod -R 777 logs,再運行tensorboard --logdir='logs/',得到一個網址http://xielongdeMacBook-Pro.local:6006,輸入chrome瀏覽器地址欄中,發現無法顯示,再在地址欄中輸入localhost:6006(http://localhost:6006/#graphs),就可以了。

tf.summary.histogram(layer_name + '/outputs', outputs) #這個在tensorboard網頁中對應 histogram 的記錄方式
tf.summary.scalar('loss', loss) #這個在tensorboard網頁中對應 event 的記錄方式

報錯

/Users/yelong/anaconda3/lib/python3.6/site-packages/h5py/init.py:36: FutureWarning: Conversion of the second argument of issubdtype from float to np.floating is deprecated. In future, it will be treated as np.float64 == np.dtype(float).type.
from ._conv import register_converters as _register_converters

解決方法:https://stackoverflow.com/questions/48340392/futurewarning-conversion-of-the-second-argument-of-issubdtype-from-float-to
在代碼開頭填上:

import os
os.environ["TF_CPP_MIN_LOG_LEVEL"]="3"

pip安裝

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple keras==2.1.6

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