# 1. 鸢尾花数据分类
## 1.1 加载数据
```python
from sklearn.datasets import load_iris
```
```python
x_data = load_iris().data # 数据特征
y_data = load_iris().target # 数据标签
```
```python
x_data.shape
```
(150, 4)
```python
y_data.shape
```
(150,)
```python
type(x_data)
```
numpy.ndarray
```python
x_data[0]
```
array([5.1, 3.5, 1.4, 0.2])
```python
y_data
```
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
## 1.2 数据集划分
```python
import tensorflow as tf
```
### 1.2.1 首先将数据集中的数据乱序
```python
import numpy as np
# 使用一样的随机数种子,确保输入特征和标签配对
np.random.seed(19)
np.random.shuffle(x_data)
np.random.seed(19)
np.random.shuffle(y_data)
```
### 1.2.2 划分训练集和验证集
将数据集,简单按照2:8的比例划分为验证集和训练集合。
由于数据量大小为150,故而为前120条和后30条。
```python
x_train = x_data[:-30]
x_test = x_data[-30:]
y_train = y_data[:-30]
y_test = y_data[-30:]
```
数据类型转换
```python
x_train = tf.cast(x_train, tf.float32)
x_test = tf.cast(x_test, tf.float32)
```
将输入的数据特征和标签进行配对,每32个作为一个batch,进行输入打包
```python
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)
```
## 1.3 定义神经网络
### 1.3.1 定义可训练的参数
```python
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))
```
### 1.3.2 计算梯度和更新
```python
# 超参数
lr = 0.02
epoch = 500
for e in range(epoch):
loss_all = 0
for step, (x_train, y_train) in enumerate(train_db):
with tf.GradientTape() as tape: # 记录梯度信息
# 前向传播计算y
y = tf.matmul(x_train, w1) + b1
y = tf.nn.softmax(y)
# 训练集真实标签,也变为三维的
real_y = tf.one_hot(y_train, depth=3)
# 计算总loss
loss = tf.reduce_mean(tf.square(real_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(e, loss_all/4))
# 测试
total_correct, total_number = 0, 0
for x_test, y_test in test_db:
# 使用w1和b1进行预测
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)
# 如果分类正确,值为1
correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)
# 加起来
correct = tf.reduce_sum(correct)
# 所有batch中的correct
total_correct += int(correct)
# 总样本数
total_number += x_test.shape[0]
# 总准确率
acc = total_correct / total_number
print("测试准确率:{}".format(acc))
```
结果:
```
Epoch: 0, loss: 0.18507226184010506
测试准确率:0.5
Epoch: 1, loss: 0.18281254917383194
测试准确率:0.5
...
Epoch: 499, loss: 0.06610946264117956
测试准确率:0.9666666666666667
```
## 1.4 使用Dense来定义神经网络
注意到上面的部分使用自己计算梯度的方式来进行,因为数据为:
120x4,而最终分类为3分类问题,故而上面使用功能了一层神经网络,也即是:
120x4 x 4x3 => 120x3的矩阵。
```python
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(3, input_shape=(4, ), activation="softmax"))
model.summary()
```
统计结果:
```
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_2 (Dense) (None, 3) 15
=================================================================
Total params: 15
Trainable params: 15
Non-trainable params: 0
_________________________________________________________________
```
指定优化器,损失函数和度量。值得注意的是,这里使用交叉熵损失函数:
```python
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy', # 分类的结果是数字编码的结果,用该交叉熵
metrics=['accuracy']
)
```
拟合:
```python
model.fit(x_data, y_data, epochs=500, batch_size=32)
```
结果:
```
Epoch 1/500
5/5 [==============================] - 0s 1ms/step - loss: 1.1094 - accuracy: 0.2400
...
Epoch 500/500
5/5 [==============================] - 0s 1ms/step - loss: 0.3297 - accuracy: 0.9667
<tensorflow.python.keras.callbacks.History at 0x207e5b65438>
```