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, 輸出 cost,weights 和 biases。
這裏 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
深度學習的優化算法,說白了就是梯度下降。每次的參數更新有兩種方式。
-
BGD : 遍歷全部數據集算一次損失函數,然後算函數對各個參數的梯度,更新梯度。這種方法每更新一次參數都要把數據集裏的所有樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲Batch gradient descent,批梯度下降。
-
SGD : 另一種,每看一個數據就算一下損失函數,然後求梯度更新參數,這個稱爲隨機梯度下降,stochastic gradient descent。這個方法速度比較快,但是收斂性能不太好,可能在最優點附近晃來晃去,hit不到最優點。兩次參數的更新也有可能互相抵消掉,造成目標函數震盪的比較劇烈。
-
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)
這是因爲cifar10
的y_train
和y_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