今天主要来看一看代码。
1.5 鸢尾花数据集
之前我们讲过鸢尾花判断0-狗尾鸢尾、1-杂色鸢尾和2-弗吉尼亚鸢尾的主要方法是测量花萼长、花萼宽、花瓣长以及花瓣宽并加以比较。在python第三方库sklearn包datasets中可以*载下**数据
fromsklearn import datasets
x_data=datasets.load_iris().data
y_data=datasets.load_iris().target
我们打印一下特征组以及标签:
print("x_data from datasets: \n", x_data)
print("y_data from datasets: \n", y_data)


根据上两张图我们可以看见数据集给我们提供了150个样本。为了观察方便我们用DataFrame把刚才的数据变成表格的形式,注意要先应用pandas包。
from pandas import DataFrame
import pandas as pd
将表格左侧添加索引,并在上方设置列标签,设置列名对齐。
x_data = DataFrame(x_data, columns=['花萼长度', '花萼宽度', '花瓣长度', '花瓣宽度'])
pd.set_option('display.unicode.east_asian_width', True)
print("x_data add index: \n", x_data)

为了清晰的体现特征组与标签的对应关系,我们把类别补在特征之后加入表格
x_data['类别'] = y_data
print("x_data add a column: \n", x_data)

回想起之前符号主义的判断方法:花萼长>花萼宽并且花瓣长/花瓣宽>2即为0-狗尾鸢尾,证明数据集没有出错。完整代码如下:
from sklearn import datasets
from pandas import DataFrame
import pandas as pd
x_data = datasets.load_iris().data
y_data = datasets.load_iris().target
print("x_data from datasets: \n", x_data)
print("y_data from datasets: \n", y_data)
x_data = DataFrame(x_data, columns=['花萼长度', '花萼宽度', '花瓣长度', '花瓣宽度'])
pd.set_option('display.unicode.east_asian_width', True)
print("x_data add index: \n", x_data)
x_data['类别'] = y_data
print("x_data add a column: \n", x_data)
1.6神经网络实现鸢尾花分类
根据前几次介绍,我们把实现分类分为以下步骤:
训练阶段:
1、准备数据:需要准备数据集并将其乱序排列,生成永不相见的训练集和测试集(x_train/y_train,x_test/y_test),配成(特征,标签)对,每一读入一小撮数据集(batch)
2、搭建神经网络:定义神经网络中所有的可训练参数
3、优化参数:嵌套循环迭代,with结构更新参数,显示当前的loss
测试阶段:
4、测试效果:计算当前参数向前传播的准确率,显示当前acc
5、acc/loss 可视化
首先我们先导入训练集和测试集
x_data = datasets.load_iris().data
y_data = datasets.load_iris().target
再将整个数据集乱序,使用相同的随机数种子保证标签与特征组还是对应的。
np.random.seed(116)
np.random.shuffle(x_data)
np.random.seed(116)
np.random.shuffle(y_data)
tf.random.set_seed(116)
将整个数据集分为永不相见的训练集和测试集,前120个训练集,后三十个为测试集,为了证明测试的准确性,要严格保证没有交集。
x_train = x_data[:-30]
y_train = y_data[:-30]
x_test = x_data[-30:]
y_test = y_data[-30:]
数据类型转换,否则在矩阵相乘时会因为数据类型不一致而报错。
x_train = tf.cast(x_train, tf.float32)
x_test = tf.cast(x_test, tf.float32)
将每32组数据打包为一个batch生成输入特征/标签对。
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
生成神经网络所需要的参数,在之前的介绍中,我依稀还记得需要一个w和b,标记为可训练。
w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))
b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))
定义超参数和两个画图用的空列表,学习率设置为0.1
lr=0.1
train_loss_results=[]
test_acc = []
epoch=500
loss_all=0
嵌套循环loss对w和b求偏导,每个step更新参数w和b
for epoch in range(epoch):
for step, (x_train, y_train) in enumerate(train_db):
with tf.GradientTape() as tape:
y = tf.matmul(x_train, w1) + b1
y = tf.nn.softmax(y)
y_ = tf.one_hot(y_train, depth=3)
loss = tf.reduce_mean(tf.square(y_ - y))
loss_all += loss.numpy()
grads = tape.gradient(loss, [w1, b1])
w1.assign_sub(lr * grads[0])
b1.assign_sub(lr * grads[1])
打印每一个epoch内的loss信息
print("Epoch {}, loss: {}".format(epoch, loss_all/4))
train_loss_results.append(loss_all / 4)
loss_all=0
测试时会遍历测试集中的所有数据,前向传播计算出预测值,转换为独热码,返回最大值的索引即为预测的分类,并将分类转化为test的数据类型。
total_correct, total_number = 0, 0
forx_test,y_testintest_db:
y = tf.matmul(x_test, w1) + b1
y = tf.nn.softmax(y)
pred=tf.argmax(y,axis=1)
pred = tf.cast(pred, dtype=y_test.dtype)
如果分类正确,也就是pred与y_test相同,将布尔值转化为整形,为了后序的自加处理,将batch中所有的正确数加起来
correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)
correct = tf.reduce_sum(correct)
total_number += x_test.shape[0]
计算正确率并且加入到test_acc数组内,并打印。
acc = total_correct / total_number
test_acc.append(acc)
print("Test_acc:", acc)
print("--------------------------")
绘制loss曲线和Accuracy曲线
plt.title('Loss Function Curve')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.plot(train_loss_results, label="$Loss#34;)
plt.legend()
plt.show()
plt.title('Acc Curve')
plt.xlabel('Epoch')
plt.ylabel('Acc')
plt.plot(test_acc, label="$Accuracy#34;)
plt.legend()
plt.show()

在刚开始的前几次学习中损失函数很大和准确率很低,说明并不能准确地给鸢尾花分类

随着学习次数的增加已经能够基本判断,但不一定准确,如图损失率不为0而正确率先到0。

一直到500次学习结束loss还没有归0,但是在后315次的学习中已经能100%的判断鸢尾花的种类,完成了搭建的目的


如图像可以验证刚才的结果

微信搜索:做梦当院士的李子哥
如需源码请添加微信输入鸢尾花领取