Tensorflow笔记(一):常用函数、张量操作、神经网络模型实现(鸢尾花分类)

import pandas as pd
import tensorflow as tf
import numpy as np


# ----------------------------- tensor张量 -----------------------------------
# 创建张量
a = tf.constant([1, 5], dtype=tf.int64)
print(a)
# > tf.Tensor([1 5], shape=(2,), dtype=int64)
# 结果说明:shape中逗号的个数其实就是张量的维数,即:一个逗号就是一维张量,两个逗号就是二维张量
print(f"a:{a}, a.shape:{a.shape}, a.dtype:{a.dtype}")
a = np.arange(0, 5)
b = tf.convert_to_tensor(a, dtype=tf.int64)  # 将numpy数组转为张量
print(b)

# 特定张量生成
a = tf.zeros(10)  # 创建全为0的一维张量, 元素个数为10
b = tf.ones(10)  # 创建全为1的一维张量
c = tf.fill([2, 3], 1)  # 创建全为1的二维张量,元素个数分别为2,3

# 随机张量生成
a2 = tf.random.truncated_normal([2, 2], mean=0.5, stddev=1)  # 正态分布随机数
print(a2)
b2 = tf.random.uniform([2, 3], minval=0, maxval=1)  # 均匀分布随机数
print(b2)

# ----------------------------- tensorflow常用函数 -----------------------------------
# 注意:做四则运算时需要保证数据类型一致
a1 = tf.cast(a, dtype=tf.float64)  # 张量数据类型强制转换为float64
a_min = tf.reduce_min(a)  # 计算张量所有元素的最小值
a_mean = tf.reduce_mean(a)  # 不指定axis,计算所有元素的平均值
a_sum = tf.reduce_sum(a, axis=1)  # 指定axis=1,按行计算元素的和

c2 = tf.cast(tf.fill([2, 3], 3), dtype=tf.float32)
tf.subtract(b2, c2)  # 张量相减,b-c,备注:要求维度相同
tf.multiply(b2, c2)  # 张量相乘
tf.sqrt(c2)  # 张量c开根号,备注:要先做数据类型转换,否则会报数据类型错误

d = tf.cast(tf.fill([3, 2], 3), dtype=tf.float32)
tf.matmul(d, c2)  # 矩阵相乘,备注:要先做数据类型转换,否则会报数据类型错误

# 切分传入张量跌的第一维度,生成输入特征/标签对,构建数据集
features = tf.constant([12, 23, 10, 17])
labels = tf.constant([0, 1, 1, 0])
dataset = tf.data.Dataset.from_tensor_slices((features, labels))  # Numpy和Tensor都支持读入
print(dataset)
for element in dataset:
    print(element)
seq = ['one', 'two', 'three']
for i, element in enumerate(seq):  # 遍历每个元素,组合为(索引 元素)
    print(i, element)

# 转换为one-hot形式的数据输出(独热编码)
classes = 3  # 分类数
labels = tf.constant([1, 0, 2])
output = tf.one_hot(labels, depth=classes)
print(output)

# 概率转换函数softmax
y = tf.constant([1.01, 2.01, -0.66])
y_prob = tf.nn.softmax(y)
print(f"after softmax, y's prob is: {y_prob}")

# argmax: 返回张量沿指定维度最大值的索引
test = np.array([[2, 2, 3], [7, 1, 4], [6, 4, 5]])
tf.argmax(test, axis=0)  # 返回每一列(经度)最大值的索引
tf.argmax(test, axis=1)  # 返回每一行(经度)最大值的索引

# ----------------------------- 简单的梯度下降实现 -----------------------------------
w = tf.Variable(tf.constant(5, dtype=tf.float32))  # Variable函数会将变量标记为“可训练”,会在反向传播中记录梯度信息,常用来标记待训练参数
lr = 0.2
epoch = 40

for epoch in range(epoch):
    with tf.GradientTape() as tape:  # with结构到grads框起了梯度的计算过程
        loss = tf.square(w + 1)  # 损失函数为w+1的平方,即:loss = (w+1)**2
    grads = tape.gradient(loss, w)  # .gradient函数告知谁对谁求导

    w.assign_sub(lr * grads)  # 对变量做自减,即:w -= lr*grads
    print(f"After {epoch + 1} epoch, w is {w.numpy()}, loss is {loss}")  # 打印计算结果


# ----------------------------- 鸢尾花神经网络模型 -----------------------------------
# 鸢尾花数据集读入
from sklearn.datasets import load_iris
x_data = load_iris().data
y_data = load_iris().target
x_data_f = pd.DataFrame(x_data, columns=["花萼长", "花萼宽", "花瓣长", "花瓣宽"])
x_data_f["类别"] = y_data

# 数据集乱序
np.random.seed(110)  # 使用相同的种子,保证输入特征/标签能一一对应
np.random.shuffle(x_data)
np.random.seed(110)  # 使用相同的种子,保证输入特征/标签能一一对应
np.random.shuffle(y_data)

# 测试集和训练集划分
x_train = x_data[:-30]
y_train = y_data[:-30]
x_test = x_data[-30:]  # 保留30个数据作为测试集
y_test = y_data[-30:]

# 配成【输入特征,标签】对,每次喂入一小撮(batch)
x_train = tf.cast(x_train, tf.float32)
x_test = tf.cast(x_test, tf.float32)
tf.random.set_seed(110)
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)

# 定义神经网络中所有可训练参数
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))

lr = 0.1
train_loss_results = []
test_acc = []
epochs = 500
loss_all = 0

# 训练部分
for epoch in range(epochs):
    for step, (x_train, y_train) in enumerate(train_db):
        with tf.GradientTape() as tape:
            y = tf.matmul(x_train, w1) + b1  # 神经网络
            y_prob = tf.nn.softmax(y)  # 概率转换
            y_ = tf.one_hot(y_train, depth=3)  # 真实值的独热编码
            loss = tf.reduce_mean(tf.square(y_-y_prob))  # 均方误差损失
            loss_all += loss.numpy()  # loss累加
        grads = tape.gradient(loss, [w1, b1])
        w1.assign_sub(lr*grads[0])
        b1.assign_sub(lr*grads[1])
    print(f"Epoch {epoch}, loss: {loss_all/4}")
    train_loss_results.append(loss_all/4)
    loss_all = 0

    # 测试部分
    total_correct, total_number = 0, 0
    for x_test, y_test in test_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)
        correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)
        correct = tf.reduce_sum(correct)
        total_correct += int(correct)
        total_number += x_test.shape[0]
    acc = total_correct / total_number
    test_acc.append(acc)
    print(f"Test_acc: {acc}")
    print("--------------------------------")

# 绘制loss曲线
import matplotlib.pyplot as plt
plt.title("loss function curve")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.plot(train_loss_results, label="$loss$")
plt.legend()
plt.show()

# 绘制acc曲线
plt.title("accuracy curve")
plt.xlabel("epoch")
plt.ylabel("acc")
plt.plot(test_acc, label="$accuracy$")
plt.legend()
plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Trisyp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值