Tensorflow 用自己图片制作数据集 仿cifar10(二)


本系列文章由  @yhl_leo  出品,转载请注明出处。 
文章链接:  http://blog.csdn.net/yhl_leo/article/details/50801226 


前一篇博客:C/C++ 图像二进制存储与读取中,已经讲解了如何利用C/C++的方法存储与读取二进制图像文件,本文继续讲述如何根据CIFAR-10的格式制作自己的数据集。

所述博文与代码均已同步至GitHub:yhlleo/imageBinaryDataset

主要代码文件有三个:

  • BinaryDataset.h
  • BinaryDataset.cpp
  • main.cpp

main.cpp给出的一个小demo为例,首先指定一个原数据图片所在的文件夹:

</pre><p style="margin-top:0px; margin-bottom:1.1em; padding-top:0px; padding-bottom:0px; color:rgb(85,85,85); font-family:"microsoft yahei"; font-size:14px">然后,自动获得该文件下的所有图片文件名:</p><pre class="prettyprint" name="code" style="white-space: nowrap; word-wrap: break-word; box-sizing: border-box; position: relative; overflow-y: hidden; overflow-x: auto; margin-top: 0px; margin-bottom: 1.1em; font-family: "Source Code Pro", monospace; padding: 5px 5px 5px 60px; font-size: 14px; line-height: 1.45; word-break: break-all; color: rgb(51, 51, 51); background-color: rgba(128, 128, 128, 0.0470588); border: 1px solid rgba(128, 128, 128, 0.0745098); border-radius: 0px;"><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">这里有一点需要说明一下,</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">getFileLists()</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">是按照文件名升序顺序读取(大家都知道,文件名为字符串,comparable),文件命名最好不要以</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">1, 2, ..., 11, ...</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">这种方式存储,因为这么存,你就会发现</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">1</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">之后的文件可能不是你想的</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">2, 3, 4, ...</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">,而是</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">11, 12, 13, ...</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">。</span>

如果你想按照顺序的某一堆数据是一种类别(我是这么做的,因为便于产生对应的labels),建议使用等宽零位补齐的方式命名,例如:00001, 0002, ..., 0011, ...,那么文件读取的顺序就会如我们所设定。

总结一下实现方法(仅供参考):

  • 采集样本的时候可以先类别存于不同的文件夹,命名就随意吧,如果是使用一些抠图软件,也不用纠结一个一个手工修改成自己想要的命名(这么做工作量很大,真的很蛋疼。。。);
  • 每一类数据整理好后,依次将每一类的数据,用程序读取并另存一份(读取使用getFileLists(),反正是一类的,也无所谓先后顺序):
<span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">后面的其他类别也可以这样,为了按照顺序区分,依次进行其他类别的时候,只需要在改动文件夹后,将</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">sprintf(curfile, "C:\\Samples\\class-1\\%04d.jpg", i);</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">中的第三个参数</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">i</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">改为</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">i+k</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">,这里</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">k</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">是前面一类或几类的样本总数。</span>
  • 最后,将重新命名的文件,存在一个文件夹里,记清楚类别对应的区间范围,以便生成labels

读取上述最终文件内的所有文件,接下来,生成labelslabels一般用[0, 9]组成的整数字):

<span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">当然,你也可以用</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">image_labels.push_back()</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">把所有的</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">labels</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">设置,但是熟悉</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">vector</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">的话,就会明白使用初始化长度,比那种做法更加高效(可以阅读本人的博客: </span><a target=_blank target="_blank" href="http://blog.csdn.net/yhl_leo/article/details/47759729" style="font-family: "microsoft yahei"; background-color: rgb(255, 255, 255); text-decoration: none; color: rgb(12, 137, 207);">C++ 容器(一):顺序容器简介</a><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">)。然后就相应地修改某些索引区间内的</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">label</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">值:</span>
<span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">都准备好后,就可以开始生成想要的二进制文件了:</span>
<span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">到这里,已经制作好了二进制数据集,我很懒,想直接基于</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">tensorflow/models/image/cifar10</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">模块的源码跑我定义的数据集,想想只要跟</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">cifar10</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">数据集类似,那肯定没什么问题,下面是官网上下载的</span><code style="background-color: rgb(255, 255, 255); font-family: "Source Code Pro", monospace; padding: 2px 4px; font-size: 12.6px; color: rgb(63, 63, 63);">cifar-10-binary.tar</code><span style="color: rgb(85, 85, 85); font-family: "microsoft yahei"; background-color: rgb(255, 255, 255);">解压后内容:</span>

cifar.rar

这份数据集比较大,训练样本有50000,测试样本10000(我的数据集并没有这么大,但是又有什么关系呢!)。

看,这是我的数据集:

cifar2

是不是很迷你~

然后,将tensorflow/models/image/cifar10模块的拷贝中的部分参数修改成为适合自己数据集的,就OK了~

献上运行截图(训练测试集有5196张样本,所以5196*0.4 = 2078):

run

 
训练了两天,跑完后,评估精度为:0.896。

好的,这是一个技术问题,我会尽力回答。下面提供一个基于TensorFlow和Keras对CIFAR-10数据集进行分类的代码示例: ```python import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers # 加载CIFAR-10数据集 (x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data() # 数据预处理,将像素值归一化到0到1之间 x_train = x_train.astype("float32") / 255.0 x_test = x_test.astype("float32") / 255.0 # 定义模型 model = keras.Sequential( [ keras.Input(shape=(32, 32, 3)), layers.Conv2D(32, kernel_size=(3, 3), activation="relu"), layers.MaxPooling2D(pool_size=(2, 2)), layers.Conv2D(64, kernel_size=(3, 3), activation="relu"), layers.MaxPooling2D(pool_size=(2, 2)), layers.Flatten(), layers.Dropout(0.5), layers.Dense(10, activation="softmax"), ] ) # 编译模型 model.compile(loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"]) # 训练模型 model.fit(x_train, y_train, batch_size=64, epochs=10, validation_split=0.1) # 评估模型 test_loss, test_acc = model.evaluate(x_test, y_test) print("Test accuracy:", test_acc) ``` 上述代码中,我们使用了两个卷积层和两个池化层,以提取图像中的特征。最后使用Flatten将卷积层的输出展平,并使用一个Dropout层来降低过拟合风险。最终使用全连接层输出10个类别的概率分布,并使用softmax函数将输出归一化成概率。 希望这个代码示例能够帮到你!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值