上篇
TensorFlow学习笔记(二)手写体数字的识别——环境安装
关于代码运行平台
博主示范使用的平台是 PyCharm Community 2019.3 x64 ,仅仅出于个人习惯。
读者也可以在 JupterNotebook 等其他平台上使用。
所用库的引入
import random
import os
from PIL import Image, ImageDraw, ImageFont
import numpy as np
random 和 os 是 python 内置的库,不需要引入。
PIL 是一个生成和处理图片的库。
numpy 将图片转化为张量,方便神经网络进行数据分析。
1. 依次打开 :File --> Settings --> Project: practice -->Project Interpreter
2. 按下 右侧的小齿轮,点击 Add…
3. 在 Location 右侧点击📂选择环境安装位置
4. 在Base interpreter 右侧点击浏览(···)选择 Anaconda 安装路径\envs\tensorflow\python3.exe 如图二所示,图一不正确。
可以勾选下面的两个小方框方便以后寻找环境。
5. 点击 OK 完成配置,等待一会,可以看到 PyCharm 列出了所有已经安装的库。
如果没有,点击右侧小眼睛图标显示即可
6. 点击右侧➕,以添加库。
7. 等待一会,出现如下界面,在搜索栏输入你想要的库的名称。
8.选中你需要的库,按 Install Package 下载,等待下载完成。
9. 如果没能下载成功,尝试打开 Terminal,即命令提示符窗口进行手动下载。
注:必须打开正确的环境,即 (tensorflow) C:\Users\用户名\pythonwork>
输入如下代码:
注:如果使用 Anaconda 环境,可以不安装 numpy ,因为我们之前安装 tensorflow 环境时已经默认安装好了相应的 numpy 包,如果没有,就输
入代码手动安装。
pip install PIL
pip install numpy # 选做
10. 使用JupyterNotebook 的朋友们按照第9步的做法在 tensorflow 环境中安装好了需要的库后就可以愉快的在 JupyterNotebook 里运行代码啦!
生成用来存放数字的文件夹
random.seed(3)
path_data ="data_and_distribution" #文件夹路径
# 在目录下生成用来存放数字的文件夹
def mkdir_for_imgs():
if not os.path.exists(path_data):
print(path_data)
os.makedirs(path_data)
删除路径下的图片
在生成新的数据前必须要先删除之前的数据。
# 删除路径下的图片
def del_imgs():
dir_nums = os.listdir(path_data)
for file in dir_nums:
print("delete: ", path_data + "/" + file)
os.remove(path_data + "/" + file)
print("Delete finish", "\n")
生成单张扭曲的数字图像
每行代码的解释都写在了代码注释里。
# 生成单张扭曲的数字图像
def generate_single():
# 先绘制一个50*50的空图像
im_50_blank = Image.new('RGB', (50, 50), (255, 255, 255))
# 创建画笔
draw = ImageDraw.Draw(im_50_blank)
# 生成随机数1-9
num = random.randint(0, 9)
# 设置字体,这里选取字体大小25
font = ImageFont.truetype('simsun.ttc', 20)
# xy是左上角开始的位置坐标
draw.text(xy=(18, 11), font=font, text=str(num), fill=(0, 0, 0))
# 随机旋转-10-10角度
random_angle = random.randint(-10, 10)
im_50_rotated = im_50_blank.rotate(random_angle)
# 图形扭曲参数
params = [1 - float(random.randint(1, 2)) / 100,
0,
0,
0,
1 - float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500]
# 创建扭曲
im_50_transformed = im_50_rotated.transform((50, 50), Image.PERSPECTIVE, params)
# 生成新的28*28图像
im_28 = im_50_transformed.crop([11, 11, 39, 39])
return im_28, num
生成手写体数字和标签存入指定文件夹
# 生成手写体数字和标签存入指定文件夹
def generate_0to9(n,fn=""):
# 用cnt_num[0]-cnt_num[9]来计数数字1-9生成的个数,方便之后进行命名
cnt_num = [0 for i in range(10)]
#用来存储每一组image和label
lst_img=[]
lst_label=[]
for m in range(n):
# 调用生成图像文件函数
im, num = generate_single()
# 计数生成的数字1-9的个数,用来查看训练集内容
cnt_num[num]+=1
# 取灰度
im_gray = im.convert('1')
# 转成数组
array = np.array(im_gray)
lst_img.append(array)
lst_label.append(num)
# 存储图像张量和标签张量组成的元组
np.savez(path_data + "/" + "data_{}".format(fn),x=np.array(lst_img),y=np.array(lst_label))
print("图像数据的形状:",np.array(lst_img).shape,"标签数据的形状:",np.array(lst_label).shape)
print("\n")
# 输出显示0-9的分布
print("生成的0-9的分布:")
print(" "+str(n)+" in all")
for k in range(10):
print("Num", k, ":", cnt_num[k], "in all")
# 存储0-9的数据分布
np.savez(path_data + "/" + "distribution_{}".format(fn), dis=np.array(cnt_num))
主程序段执行
注:因为生成的数据集很大,需要一定的时间来运行,请耐心等待。
if __name__=="__main__":
# 生成目录
mkdir_for_imgs()
# 清除已有npy文件
del_imgs()
# 生成60000个训练数据
generate_0to9(60000,"train")
# 生成10000个检验数据
generate_0to9(10000,"test")
运行的结果
注:成功后可以在工程创建的位置找到如图所示的文件夹,里面有四个npz文件。
完整的代码
import random
import os
from PIL import Image, ImageDraw, ImageFont
import numpy as np
random.seed(3)
path_data ="data_and_distribution" #文件夹路径
# 在目录下生成用来存放数字的文件夹
def mkdir_for_imgs():
if not os.path.exists(path_data):
print(path_data)
os.makedirs(path_data)
# 删除路径下的图片
def del_imgs():
dir_nums = os.listdir(path_data)
for file in dir_nums:
print("delete: ", path_data + "/" + file)
os.remove(path_data + "/" + file)
print("Delete finish", "\n")
# 生成单张扭曲的数字图像
def generate_single():
# 先绘制一个50*50的空图像
im_50_blank = Image.new('RGB', (50, 50), (255, 255, 255))
# 创建画笔
draw = ImageDraw.Draw(im_50_blank)
# 生成随机数1-9
num = random.randint(0, 9)
# 设置字体,这里选取字体大小25
font = ImageFont.truetype('simsun.ttc', 20)
# xy是左上角开始的位置坐标
draw.text(xy=(18, 11), font=font, text=str(num), fill=(0, 0, 0))
# 随机旋转-10-10角度
random_angle = random.randint(-10, 10)
im_50_rotated = im_50_blank.rotate(random_angle)
# 图形扭曲参数
params = [1 - float(random.randint(1, 2)) / 100,
0,
0,
0,
1 - float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500]
# 创建扭曲
im_50_transformed = im_50_rotated.transform((50, 50), Image.PERSPECTIVE, params)
# 生成新的28*28图像
im_28 = im_50_transformed.crop([11, 11, 39, 39])
return im_28, num
# 生成手写体数字和标签存入指定文件夹
def generate_0to9(n,fn=""):
# 用cnt_num[0]-cnt_num[9]来计数数字1-9生成的个数,方便之后进行命名
cnt_num = [0 for i in range(10)]
#用来存储每一组image和label
lst_img=[]
lst_label=[]
for m in range(n):
# 调用生成图像文件函数
im, num = generate_single()
# 计数生成的数字1-9的个数,用来查看训练集内容
cnt_num[num]+=1
# 取灰度
im_gray = im.convert('1')
# 转成数组
array = np.array(im_gray)
lst_img.append(array)
lst_label.append(num)
# 存储图像张量和标签张量组成的元组
np.savez(path_data + "/" + "data_{}".format(fn),x=np.array(lst_img),y=np.array(lst_label))
print("图像数据的形状:",np.array(lst_img).shape,"标签数据的形状:",np.array(lst_label).shape)
print("\n")
# 输出显示0-9的分布
print("生成的0-9的分布:")
print(" "+str(n)+" in all")
for k in range(10):
print("Num", k, ":", cnt_num[k], "in all")
# 存储0-9的数据分布
np.savez(path_data + "/" + "distribution_{}".format(fn), dis=np.array(cnt_num))
if __name__=="__main__":
# 生成目录
mkdir_for_imgs()
# 清除已有npy文件
del_imgs()
# 生成60000个训练数据
generate_0to9(60000,"train")
# 生成10000个检验数据
generate_0to9(10000,"test")