model = Sequential()
model.add(Dense(output_dim=1, input_dim=1))
每次model.add就是添加一层,不用写入权重这些参数。
W, b = model.layers[0].get_weights()
是第一层的参数。
不同特征所占比重不同,把特征们的所占比重都设置为差不多,都在(0,1)之间
https://morvanzhou.github.io/tutorials/machine-learning/keras/2-2-classifier/
from keras.datasets import mnist #就开始下载了
(x_train, y_train), (x_test, y_test) = mnist.load_data()
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)
深度学习的优化算法,说白了就是梯度下降。每次的参数更新有两种方式。
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指的就是训练过程中数据将被“轮”多少次.
验证集的作用是当通过训练集训练出多个模型后,为了能找出效果最佳的模型,使用各个模型对验证集数据进行预测,并记录模型准确率。选出效果最佳的模型所对应的参数,即用来调整模型参数。如svm中的参数c和核函数等。
因为参数是超参数。
参考 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())
自带的脚本里的地址,下载数据集太慢。可以本地下好,拷贝到~/.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, ),打开看是一列,但其实仍是一行[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], )
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()
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 install -i https://pypi.tuna.tsinghua.edu.cn/simple keras==2.1.6