三层神经网络鸢尾花数据分析 (如何搭建一个简单的神经网络)

今天主要来看一看代码。

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)

搭建神经网络和创建api,神经网络分类的基础方法

搭建神经网络和创建api,神经网络分类的基础方法

根据上两张图我们可以看见数据集给我们提供了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)

搭建神经网络和创建api,神经网络分类的基础方法

为了清晰的体现特征组与标签的对应关系,我们把类别补在特征之后加入表格

x_data['类别'] = y_data
print("x_data add a column: \n", x_data)

搭建神经网络和创建api,神经网络分类的基础方法

回想起之前符号主义的判断方法:花萼长>花萼宽并且花瓣长/花瓣宽>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()

搭建神经网络和创建api,神经网络分类的基础方法

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

搭建神经网络和创建api,神经网络分类的基础方法

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

搭建神经网络和创建api,神经网络分类的基础方法

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

搭建神经网络和创建api,神经网络分类的基础方法

搭建神经网络和创建api,神经网络分类的基础方法

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

搭建神经网络和创建api,神经网络分类的基础方法

微信搜索:做梦当院士的李子哥

如需源码请添加微信输入鸢尾花领取