暑假打算自学下tensorflow,原先是看mooc上复旦的课,但他给的练习和例题太少,后来转到b站看吴恩达的课,打开新世界,真是好太多了!
废话少说,我将在这里做学习笔记,希望可以坚持下去。文章顺序顺序是乱的,这很抱歉。
回调
回调似乎就是做一个callback类,这个类在epoch的末尾将会执行。
class myCallback(tf.keras.callbacks.Callback):
def on_epoch_end(self,epoch,logs={}):
if(logs.get('accuracy')>0.99):
print("\nReached 99%!")
self.model.stop_training=True #要记住在Callback类里面有一个model.stop_traning变量来标注是否停止你的训练
好在tf已经帮忙定义了,但我还有几个问题不是很明白,比如如果改成“def on_epoch_end(self,logs={})”,那么运行会有错误。可我们明明重载了on_epoch_end,为什么不传入一个没用到的变量会有问题呢?
言归正传,在定义重载类后,我们先把他实例化为callbacks,然后在 fit 的时候可以启用回调
model.fit(x_train, y_train, epochs=10, callbacks=[callbacks])
现在只要某个epoch训练结束时系统一看,诶,你的accuracy比99%高,就打印一句“Reached 99%!”,然后把self.model.stop_training改成True,那下一个epoch要启动时就被阻断了。这就是所谓回调。
训练需要的数据类型
大多数情况,我们写demo是直接调取数据集,所以这个其实不太重要,但还是值得注意:训练集需要是numpy.array类型。比如这样:
xs = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], dtype=float)
有时候用矩阵输入,会报错说输入了过多的数据,我原先以为是转置的问题,即行列搞反了,但转置后也没有解决。我还不知道怎么办。
优化器(Optimizer)的调用
调用优化器有好几种写法,比如我们要调用Adam,那我们可以写
optimizer=tf.optimizers.Adam()
也可以
optimizer=‘Adam’
真是很神奇。
卷积的简单例子
这里贴的是Google公开课的代码
import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images/255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
model.fit(training_images, training_labels, epochs=5)
test_loss = model.evaluate(test_images, test_labels)
前面加载数据什么的就不看了,这里提一个有意思的,reshape,大家学numpy都知道有这个函数,可以揉捏数组的规模。举个例子:
arr=np.arange(16).reshape(2,8)
arr
'''
out:
array([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13, 14, 15]])
'''
arr.reshape(4,-1) #将arr变成4行的格式,列数自动计算的(c=4, d=16/4=4)
'''
out:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
'''
arr.reshape(8,-1) #将arr变成8行的格式,列数自动计算的(c=8, d=16/8=2)
'''
out:
array([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11],
[12, 13],
[14, 15]])
'''
我们这里reshape(60000,28,28,1),是要搞成一个四维数组。其实为什么要弄成四维,我也不清楚,本来的三维结构不行吗?将来我弄明白了再补。(原来是因为图像的颜色是黑白的,颜色深度只有一个,所以我们加上这个表征颜色的维度)
我们接着下面看到卷积层和池化层在神经网络的前面:
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
这个卷积层和池化层的组合我们做了两个,先单独拿出其中一个来讨论。64,是64个卷积核;(3,3)是每次对3*3的像素进行处理,relu是对像素用的激活函数,input_shape很明显是输入的格式。在这一层后,28*28变成26*26,因为最边缘的周边不存在3*3的空间,那就处理不了了,但这是丢失数据还是什么,我不太清楚。
MaxPooling2D(2,2)是池化,在2*2的空间中找出最大的那个作为代表的像素。26*26接下来变成了13*13。
后面如此再来一遍,就变成了11*1,再变成了5*5,如此,就被压缩了。
如果内核挂掉了怎么办
我在学卷积时遇到一个问题,就是只要模型带着卷积层,JupyterNotebook就说我的内核挂掉了,换到别的IDE也是一样。这是一个好例子,我讲讲我是怎么解决它的。
鲁迅说,先看报错。我首先把代码复制到Visual Studio里面,结果它直接返回一个 0xfffffff 来告诉我内核挂了,显然这个报错是没有意义的。于是我还是用JupyterNotebook来运行,然后我在JN的命令行窗口里看到了这个报错:
Could not load library cudnn_cnn_infer64_8.dll. Error code 126
Please make sure cudnn_cnn_infer64_8.dll is in your library path!
那就上bing搜索这个报错咯,结果bing上解决方案五花八门,甚至还有建议重装anaconda的,这时就应该上StackOverflow看看。在StackOverflow,有一个回答说这是因为我没有装ZLIB,这是nvidia要装cudnn前要求先装的一个配置文件,于是我就安装ZLIB,再从nvidia官网找到cudnn装上,完美解决。
值得一提的是,如果剩余内存太少也是跑不起来的,一般碰到问题还是应该先试一试重启大法。
我把链接贴在这里:Installation Guide :: NVIDIA Deep Learning cuDNN Documentation
最近没有接着写,看来打脸了=.=,而且csnd好像吞了我一段话,我记得我明明有写过优化器实现原理和分类的,现在却找不到了。文章一直存在草稿箱也不是事,先发出来,9.2后还有空接着写。