本人显卡1050 2G性能不足,因此将resnet18([2,2,2,2])改为了resnet10([1,1,1,1]),并且在cirfar100数据集为50000的情况下,将batchsiz设置为了8.显卡配置过关的同学请将本程序中的这两块改回去。
解决方法:使用Google的Colab,本人将在下一篇博客中介绍利用Colab跑tf
import tensorflow as tf
from tensorflow.keras import layers, optimizers, datasets, Sequential
import os
from resnet import resnet18
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
tf.random.set_seed(2345)
# 4)设置下加载的数据集
# 4.1)预处理一下
def preprocess(x, y):
# [-1~1]
x = 2 * tf.cast(x, dtype=tf.float32)/255. - 1
y = tf.cast(y, dtype=tf.int32)
return x, y
# 4.2)数据的加载
# 此处按道理来讲tf会自动从官网上下载,但是由于数据量太大100多兆,容易出错(链接更新了),或者时间很慢
# 因此百度数据集提前下载好,放在文件夹“C:\Users\wanfuchun\.keras\datasets”无需解压,程序会自动解压
(x, y), (x_test, y_test) = datasets.cifar100.load_data()
y = tf.squeeze(y, axis=1) # axis=1,把‘1’维度挤压掉
y_test = tf.squeeze(y_test, axis=1) # axis=1,把‘1’维度挤压掉
print(x.shape, y.shape, x_test.shape, y_test.shape)
# 5)设置下dataset
train_db = tf.data.Dataset.from_tensor_slices((x, y))
train_db = train_db.shuffle(1000).map(preprocess).batch(8)
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_db = test_db.map(preprocess).batch(8)
sample = next(iter(train_db))
print('sample:', sample[0].shape, sample[1].shape,
tf.reduce_min(sample[0]), tf.reduce_max(sample[0]))
def main():
# 测试代码:
# [b, 32, 32, 3] => [b, 1, 1, 3]
model = resnet18()
model.build(input_shape=(None, 32, 32, 3))
model.summary()
# 8)优化器的更新
optimizer = optimizers.Adam(lr=1e-4)
# 6)到此为止,数据集的部分已经加载完了,接下来设置一个测试的部分。
for epoch in range(50):
for step, (x, y) in enumerate(train_db):
# [b, 32, 32, 3] => [b,100]
with tf.GradientTape() as tape:
# [b, 32, 32, 3] => [b, 100]
logits = model(x)
# [b] => [b, 100]
y_onehot = tf.one_hot(y, depth=100)
# compute loss
loss = tf.losses.categorical_crossentropy(y_onehot, logits, from_logits=True)
loss = tf.reduce_mean(loss)
grads = tape.gradient(loss, model.trainable_variables)
# 9)把定义好的优化器传过来
optimizer.apply_gradients(zip(grads, model.trainable_variables))
# 10)打印一下
if step%100 == 0:
print(epoch, step, 'loss:', float(loss))
# 11)测试代码:(1)这里是在每一次数据集迭代完成之后(2)也可以在每一个100个step完成之后。测试越多,影响效率,不做测试,又不知道效果
total_num = 0
total_correct = 0
for x, y in test_db:
logits = model(x)
prob = tf.nn.softmax(logits, axis=1)
pred = tf.argmax(prob, axis=1)
pred = tf.cast(pred, dtype=tf.int32)
correct = tf.cast(tf.equal(pred, y), dtype=tf.int32)
correct = tf.reduce_sum(correct)
total_num +=x.shape[0]
total_correct += int(correct)
acc = total_correct / total_num
print(epoch, 'acc', acc)
# 所有的函数都写在main函数里,避免全局变量的一个污染
if __name__ == '__main__':
main()
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, Sequential
# 新建BasicBlock类,继承自layers.Layer父类
class BasicBlock(layers.Layer):
# 定义两个函数
# 定义初始化函数
def __init__(self, filter_num, stride=1): # 里面有两个主要参数:filter_num是卷积核的数量,和channel一个意思;stride默认参数为1
super(BasicBlock, self).__init__() # 调用一个初始化方法
# 实现convolution层
self.conv1 = layers.Conv2D(filter_num, (3, 3), strides=stride, padding='same') # 定义第一个卷积层。一般卷积核为1*1或3*3,padding有整除功能
self.bn1 = layers.BatchNormalization()
self.relu = layers.Activation('relu')
self.conv2 = layers.Conv2D(filter_num, (3, 3), strides=1, padding='same')
self.bn2 = layers.BatchNormalization()
# 实现identity层
# self.downsample = Sequential() #设置一个容器,这是一个下采样层
# self.downsample.add(layers.Conv2D(filter_num, (1, 1), stride=stride)) # 里面添加一个1*1的卷积层
# 此处当stride=1是实际上是没有downsample,但是这样写也没问题,也可以写成if,else的形式,如下方所示:
if stride != 1:
self.downsample = Sequential() # 设置一个容器,这是一个下采样层
self.downsample.add(layers.Conv2D(filter_num, (1, 1), strides=stride))
else:
self.downsample = lambda x: x
# 调用call函数,里面有两个主要参数:inputs和training
def call(self, inputs, training=None):
# 接下来实现一个前向传播的逻辑
# 1)设置卷积层
# 1.1)前向传播首先经过第一个卷积层
# [b, h, w, c]
out = self.conv1(inputs)
out = self.bn1(out)
out = self.relu(out)
# 1.2)接下来经过第二层的一个前向传播
out = self.conv2(out)
out = self.bn2(out)
# 2)设置短路层
identity = self.downsample(inputs)
# 3)二者结合
output = layers.add([out, identity])
# 这里的self.relu()上边也使用了一次,一共使用了两次,为什么呢?因为这个函数是不用设置参数的,因此可以多次使用。但是像上方的self.conv1()这种函数只能使用一次
# output = self.relu(output) # 注意:这里的relu函数既可以写在这里,也可以写在上方的1.2)中,只要有这个思想在里面,都是resnet网络
# 此处我们先不这么做了,使用tf.nn.relu()也可以
output = tf.nn.relu(output)
return output
# 新建一个ResNet类,继承自keras.Model类
class ResNet(keras.Model):
def __init__(self, layer_dims, num_classes=100): #[2, 2, 2, 2],分类为100类
super(ResNet, self).__init__()
# 1)创建第一层
# 设置下预处理层,一个3*3的卷积
self.stem = Sequential([layers.Conv2D(64, (3, 3), strides=(1, 1)),
layers.BatchNormalization(),
layers.Activation('relu'),
layers.MaxPool2D(pool_size=(2, 2), strides=(1, 1), padding='same')
])
# 2)创建中间的几个层
self.layer1 = self.build_resblock(64, layer_dims[0])
self.layer2 = self.build_resblock(128, layer_dims[1], stride=2)
self.layer3 = self.build_resblock(256, layer_dims[2], stride=2)
self.layer4 = self.build_resblock(512, layer_dims[3], stride=2)
# 3)创建后边的全连接层
# output: [b, 512, h, w],
self.avgpool = layers.GlobalAveragePooling2D() # 使用这个层可以自适应的确定输出
self.fc = layers.Dense(num_classes) # Dense层是用来分类的,输出节点的个数就是我们分类的数量
def call(self, inputs, training=None):
x = self.stem(inputs)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
# [b, c]
x = self.avgpool(x)
# [b, 100]
x = self.fc(x)
return x
# 我们要实现resblock,因为要build
def build_resblock(self, filter_num, blocks, stride=1):
res_blocks = Sequential()
# may down sample 可能下采样。我们仅仅在这第一个basicblock有下采样的能力,接下来的块没有下采样能力
res_blocks.add(BasicBlock(filter_num, stride)) # 在resblock里面添加第一层basicblock
for _ in range(1, blocks):
res_blocks.add(BasicBlock(filter_num, stride=1))
return res_blocks
def resnet18():
return ResNet([1, 1, 1, 1])
def resnet34():
return ResNet([3, 4, 6, 3])
F:\Anaconda3\envs\gpu\python.exe H:/lesson13/resnet18_train.py
(50000, 32, 32, 3) (50000,) (10000, 32, 32, 3) (10000,)
sample: (8, 32, 32, 3) (8,) tf.Tensor(-1.0, shape=(), dtype=float32) tf.Tensor(1.0, shape=(), dtype=float32)
Model: "res_net"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
sequential (Sequential) multiple 2048
_________________________________________________________________
sequential_1 (Sequential) multiple 74368
_________________________________________________________________
sequential_2 (Sequential) multiple 230784
_________________________________________________________________
sequential_4 (Sequential) multiple 920320
_________________________________________________________________
sequential_6 (Sequential) multiple 3675648
_________________________________________________________________
global_average_pooling2d (Gl multiple 0
_________________________________________________________________
dense (Dense) multiple 51300
=================================================================
Total params: 4,954,468
Trainable params: 4,950,500
Non-trainable params: 3,968
_________________________________________________________________
0 0 loss: 4.59770393371582
0 100 loss: 4.61661434173584
0 200 loss: 4.470965385437012
0 300 loss: 4.640949249267578
0 400 loss: 5.0125932693481445
0 500 loss: 4.2307586669921875
0 600 loss: 4.270209312438965
0 700 loss: 4.250596046447754
0 800 loss: 4.430176734924316
0 900 loss: 4.932032108306885
0 1000 loss: 4.192464351654053
0 1100 loss: 4.243913650512695
0 1200 loss: 3.6868896484375
0 1300 loss: 4.216487884521484
0 1400 loss: 4.290569305419922
0 1500 loss: 3.9880409240722656
0 1600 loss: 3.522996425628662
0 1700 loss: 4.028144836425781
0 1800 loss: 3.666536808013916
0 1900 loss: 4.133691787719727
0 2000 loss: 3.7695178985595703
0 2100 loss: 3.9597365856170654
0 2200 loss: 3.87199068069458
0 2300 loss: 3.9115254878997803
0 2400 loss: 3.3812105655670166
0 2500 loss: 4.521636009216309
0 2600 loss: 3.2893247604370117
0 2700 loss: 3.590747356414795
0 2800 loss: 3.810286283493042
0 2900 loss: 4.056480884552002
0 3000 loss: 2.9913015365600586
0 3100 loss: 3.8411355018615723
0 3200 loss: 4.0060343742370605
0 3300 loss: 3.8063905239105225
0 3400 loss: 3.8354978561401367
0 3500 loss: 3.4543814659118652
0 3600 loss: 4.4650068283081055
0 3700 loss: 4.074818134307861
0 3800 loss: 3.453068256378174
0 3900 loss: 3.051651954650879
0 4000 loss: 4.744655609130859
0 4100 loss: 4.441380977630615
0 4200 loss: 2.8942787647247314
0 4300 loss: 3.677321672439575
0 4400 loss: 3.546954393386841
0 4500 loss: 4.091507911682129
0 4600 loss: 2.466554880142212
0 4700 loss: 3.465322971343994
0 4800 loss: 3.0418004989624023
0 4900 loss: 3.1135077476501465
0 5000 loss: 2.7575430870056152
0 5100 loss: 3.7100777626037598
0 5200 loss: 2.5508503913879395
0 5300 loss: 2.6023192405700684
0 5400 loss: 4.084221839904785
0 5500 loss: 3.88431715965271
0 5600 loss: 3.4921152591705322
0 5700 loss: 3.019258499145508
0 5800 loss: 2.9354591369628906
0 5900 loss: 3.878539562225342
0 6000 loss: 3.248048782348633
0 6100 loss: 2.620455741882324
0 6200 loss: 3.6914100646972656
0 acc 0.2178
1 0 loss: 2.9207634925842285
1 100 loss: 2.5969207286834717
1 200 loss: 3.3295984268188477
1 300 loss: 3.3277201652526855
1 400 loss: 3.1084656715393066
1 500 loss: 3.2926182746887207
1 600 loss: 2.900806427001953
1 700 loss: 2.9900240898132324
1 800 loss: 3.4043378829956055
1 900 loss: 3.9075586795806885
1 1000 loss: 2.2452235221862793
1 1100 loss: 3.20048451423645
1 1200 loss: 2.8694567680358887
1 1300 loss: 2.9608635902404785
1 1400 loss: 2.722925901412964
1 1500 loss: 2.105517864227295
1 1600 loss: 1.8116563558578491
1 1700 loss: 3.0940330028533936
1 1800 loss: 2.0055270195007324
1 1900 loss: 3.858921766281128
1 2000 loss: 2.5601272583007812
1 2100 loss: 3.1515355110168457
1 2200 loss: 3.4619531631469727
1 2300 loss: 3.0075836181640625
1 2400 loss: 2.8875136375427246
1 2500 loss: 3.8499221801757812
1 2600 loss: 2.366396903991699
1 2700 loss: 3.110337495803833
1 2800 loss: 2.965012550354004
1 2900 loss: 3.571072578430176
1 3000 loss: 1.9808564186096191
1 3100 loss: 3.2064971923828125
1 3200 loss: 2.96171236038208
1 3300 loss: 3.4440712928771973
1 3400 loss: 2.9811408519744873
1 3500 loss: 2.6866469383239746
1 3600 loss: 3.8789567947387695
1 3700 loss: 3.3070688247680664
1 3800 loss: 2.8753066062927246
1 3900 loss: 2.0884382724761963
1 4000 loss: 3.7398393154144287
1 4100 loss: 3.615215301513672
1 4200 loss: 2.443180561065674
1 4300 loss: 2.9981560707092285
1 4400 loss: 3.3310763835906982
1 4500 loss: 3.226996660232544
1 4600 loss: 1.9244557619094849
1 4700 loss: 2.402409076690674
1 4800 loss: 2.277308940887451
1 4900 loss: 2.6824049949645996
1 5000 loss: 2.0951504707336426
1 5100 loss: 2.4765737056732178
1 5200 loss: 1.839066505432129
1 5300 loss: 1.8925254344940186
1 5400 loss: 3.313929796218872
1 5500 loss: 3.3951973915100098
1 5600 loss: 2.841444253921509
1 5700 loss: 3.664215564727783
1 5800 loss: 2.7626407146453857
1 5900 loss: 2.9793996810913086
1 6000 loss: 2.522484064102173
1 6100 loss: 2.1771414279937744
1 6200 loss: 3.222641944885254
1 acc 0.3057
2 0 loss: 2.2999625205993652
Process finished with exit code -1