|
|
import tensorflow as tf
|
|
|
import numpy as np
|
|
|
from sklearn import datasets
|
|
|
from matplotlib import pyplot as plt
|
|
|
from tensorflow.python.ops.resource_variable_ops import ResourceVariable
|
|
|
import tkinter as tk
|
|
|
|
|
|
class evaclassy():
|
|
|
|
|
|
def __init__(self):
|
|
|
self.data = datasets.load_iris().data
|
|
|
self.target = datasets.load_iris().target
|
|
|
self.train_loss_list = []
|
|
|
self.test_acc_list = []
|
|
|
self.k1=0
|
|
|
self.b1=0
|
|
|
self.lr=0.1 #学习率设置
|
|
|
self.epoch=200
|
|
|
self.eval_loss_all=0 # 初始化loss_all的值,用于记录每轮四个step生成的4个loss的和
|
|
|
def main(self):
|
|
|
#------------------------------------------------------------------------#
|
|
|
# ----------------------数据处理-----------------------------#
|
|
|
np.random.seed(116) # 使用用一个种子 保持输入特征与标签对应
|
|
|
np.random.shuffle(self.data)
|
|
|
np.random.seed(116)
|
|
|
np.random.shuffle(self.target)
|
|
|
tf.random.set_seed(116)
|
|
|
data_train = self.data[:-30] # 使用切片,使前120组数据作为训练集,后30组数据作为验证集
|
|
|
data_test = self.data[-30:]
|
|
|
target_train = self.target[:-30]
|
|
|
target_test = self.target[-30:]
|
|
|
data_train = tf.cast(data_train, tf.float32)
|
|
|
data_test = tf.cast(data_test, tf.float32)
|
|
|
train_db = tf.data.Dataset.from_tensor_slices((data_train, target_train)).batch(32)
|
|
|
test_db = tf.data.Dataset.from_tensor_slices((data_test, target_test)).batch(32)
|
|
|
k = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))
|
|
|
b = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))
|
|
|
#---------------------------------------------------------------------------------------------#
|
|
|
for self.epoch in range(self.epoch):
|
|
|
for step, (data_train, target_train) in enumerate(train_db):
|
|
|
with tf.GradientTape() as tape:
|
|
|
dat = tf.matmul(data_train, k) + b
|
|
|
dat = tf.nn.softmax(dat) # 使输出结果符合概率分布
|
|
|
targ = tf.one_hot(target_train, depth=3) # 将标签转化为独热码格式
|
|
|
loss = tf.reduce_mean(tf.square(targ - dat)) # 使用均方差损失函数mse计算损失函数
|
|
|
self.eval_loss_all += loss.numpy()
|
|
|
grads = tape.gradient(loss, [k, b]) # 计算loss对各个参数的梯度
|
|
|
k.assign_sub(self.lr * grads[0])
|
|
|
b.assign_sub(self.lr * grads[1]) # 更新模型偏置量参数b
|
|
|
print("Epoch: {}, loss: {}".format(self.epoch, self.eval_loss_all / 4))
|
|
|
self.train_loss_list.append(self.eval_loss_all / 4) # 记录loss_all均值放入列表
|
|
|
self.eval_loss_all = 0 # 归零,便于记录下一个epoch的loss
|
|
|
total_correct, total_number = 0, 0
|
|
|
with open('k.txt','w') as f:
|
|
|
f.write(str(k))
|
|
|
with open('b.txt', 'w') as f:
|
|
|
f.write(str(b))
|
|
|
self.k1=k
|
|
|
self.b1=b
|
|
|
for data_test, target_test in test_db:
|
|
|
dat = tf.matmul(data_test, k) + b
|
|
|
dat = tf.nn.softmax(dat)
|
|
|
pred = tf.argmax(dat, axis=1) # 返回y中最大值的索引,即鸢尾花的分类标签
|
|
|
pred = tf.cast(pred, dtype=target_test.dtype) # 转换数据类型
|
|
|
correct = tf.cast(tf.equal(pred, target_test), dtype=tf.int32) # 根据分类是否正确返回布尔 # 值且转换为int型
|
|
|
correct = tf.reduce_sum(correct)
|
|
|
total_correct += int(correct)
|
|
|
total_number += data_test.shape[0]
|
|
|
acc = total_correct / total_number # 总正确次数/总预测次数,计算准确率
|
|
|
self.test_acc_list.append(acc) # 添加准确率数据到列表记录下来
|
|
|
print("acc: ", acc)
|
|
|
def draw(self):
|
|
|
plt.title('Acc Curve') # 图片标题
|
|
|
plt.xlabel('迭代次数', fontproperties='SimHei', fontsize=15)
|
|
|
plt.ylabel('准确率', fontproperties='SimHei', fontsize=15)
|
|
|
plt.plot(self.test_acc_list, label="$Accuracy$")
|
|
|
plt.legend()
|
|
|
plt.savefig('准确率图像')#图片保存
|
|
|
plt.show()
|
|
|
|
|
|
plt.title('Loss Function Curve')
|
|
|
plt.xlabel('迭代次数', fontproperties='SimHei', fontsize=15)
|
|
|
plt.ylabel('损失率', fontproperties='SimHei', fontsize=15)
|
|
|
plt.plot(self.train_loss_list, label="$Loss$")
|
|
|
plt.legend()
|
|
|
plt.savefig('损失率图像')#图片保存
|
|
|
plt.show()
|
|
|
def predict(self,data):
|
|
|
y = tf.matmul(data, self.k1) + self.b1
|
|
|
y = tf.nn.softmax(y)
|
|
|
pred = tf.argmax(y, axis=1)
|
|
|
pred=int(pred)
|
|
|
if pred==0:
|
|
|
print('是山鸢尾花')
|
|
|
return '山鸢尾花'
|
|
|
if pred==1:
|
|
|
print('是变色鸢尾花')
|
|
|
return '是变色鸢尾花'
|
|
|
if pred==2:
|
|
|
print('是维吉尼亚鸢尾花')
|
|
|
return '是维吉尼亚鸢尾花'
|
|
|
#数据处理
|
|
|
def dataloader(list1):
|
|
|
data_train=[]
|
|
|
data_train.append(list1)
|
|
|
data_train = tf.cast(data_train, tf.float32)
|
|
|
return data_train
|
|
|
#窗口展示
|
|
|
class draw1():
|
|
|
def insert_point(self):
|
|
|
var = self.e.get()
|
|
|
c=str(var)
|
|
|
var = list(var)
|
|
|
var=list(map(float,var))
|
|
|
print(var)
|
|
|
self.v1.set('')
|
|
|
var=dataloader(var)
|
|
|
try:
|
|
|
predic=a.predict(var)
|
|
|
except:
|
|
|
self.t.delete('1.0', 'end')
|
|
|
self.t.insert('insert', '请重新输入')
|
|
|
else:
|
|
|
self.t.delete('1.0', 'end')
|
|
|
self.t.insert('insert', c+predic)
|
|
|
|
|
|
def insert_end(self):
|
|
|
self.t.delete('1.0', 'end')
|
|
|
def main(self):
|
|
|
window = tk.Tk()
|
|
|
window.title('classy')
|
|
|
window.geometry('500x500')
|
|
|
self.v1 = tk.StringVar()
|
|
|
self.e = tk.Entry(window, show=None,width=200, textvariable=self.v1)
|
|
|
self.e.pack()
|
|
|
self.k = tk.Text(window, height=2,state = 'disabled')
|
|
|
self.k.pack()
|
|
|
self.k.insert('insert', '输入四个范围为1-6的数字不加任何连接符')
|
|
|
self.t = tk.Text(window, height=2)
|
|
|
self.t.pack()
|
|
|
b1 = tk.Button(window, text='insert point', width=15,
|
|
|
height=2, command=self.insert_point)
|
|
|
b1.pack()
|
|
|
self.v1.set('')
|
|
|
b2 = tk.Button(window, text='insert end',width=15,height=2,
|
|
|
command=self.insert_end)
|
|
|
b2.pack()
|
|
|
window.mainloop()
|
|
|
if __name__ == '__main__':
|
|
|
a = evaclassy()
|
|
|
a.main()
|
|
|
# a.draw() #损失 正确函数画图
|
|
|
b=draw1()
|
|
|
b.main() |