You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1213 lines
57 KiB

import sys
import pickle
import subprocess
import tkinter as tk
11 months ago
from tkinter import ttk
from tkinter import messagebox
import tkinter.scrolledtext as st
from PIL import Image, ImageTk
from tkinter import Canvas, Frame, BOTH, PhotoImage, filedialog
from X3 import load_data
from X2 import ModelObj,connect_class
# 网络模型正确的图元和连接关系的数据结构,用一个数组表示
RIGHT_MODEL = [
[0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1],
[0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0]
]
# 创建三个空的卷积层图元实例和三个空的全连接层图元实例
Conv1 = None
Conv2 = None
Conv3 = None
Pool1 = None
Pool2 = None
Pool3 = None
Fullconn1 = None
Fullconn2 = None
Fullconn3 = None
11 months ago
global Viewcanvas # 定义画布
global Text # 带滚动条
global Root # 主窗口
global AllModelObj # 网络对象
11 months ago
List_image = [] # 存储图元的列表
Prob_images = [] # 存储图元的列表
Train_images = [] # 存储训练集的列表
Test_images = [] # 存储测试集的列表
Items1 = [] # 存储新图元的列表
Items2 = [] # 存储新数据线的列表
Items3 = [] # 存储被拖拽的图元的列表
Items4 = [] # 存储新图元文字标签的列表
Counts = {} # 用来存储Items3每个数字出现过的次数
Conv_xy_list = [] # 存储卷积图元的坐标
Fullconn_xy_list = [] # 存储全连接图元的坐标
Train_list = [] # 存储训练设置参数
Listinstance = [] # 图元对象实例
Dragged_item = () # 记录被拖拽的图元id
Original_x = 0 # 记录图元原来的x坐标
Original_y = 0 # 记录图元原来的y坐标
Offset_x = 0 # 记录鼠标相对于图元的x偏移量
Offset_y = 0 # 记录鼠标相对于图元的y偏移量
11 months ago
Yt = 0 # 新图元的y坐标
Batch = 0 # 批次
def create_instance():
# 创建图元对象实例
11 months ago
DataSet = ModelObj("DataSet", 1, "数据集", "LoadData", "SetDataPara", ".", 90, 40).output()
Conv = ModelObj("Conv", 2, "卷积", "ConvProc", "SetConvPara", ".", 200, 40).output()
Pool = ModelObj("Pool", 3, "最大池化", "MaxPoolProc", "SetPollPara", ".", 90, 105).output()
FullConn = ModelObj("FullConn", 4, "全连接", "FullConnProc", "SetFullConnPara", ".", 200, 105).output()
Nonline = ModelObj("Nonline", 5, "非线性函数", "NonlinearProc", "SetNonLPara", ".", 90, 170).output()
Classifier = ModelObj("Classifier", 6, "分类", "ClassifierProc", "SetClassifyPara", ".", 200, 170).output()
Error = ModelObj("Error", 7, "误差计算", "ErrorProc", "SetErrorPara", ".", 90, 235).output()
AjConv = ModelObj("AjConv", 8, "卷积调整", "AjConvProc", "SetAjConvPara", ".", 200, 235).output()
AjFullconn = ModelObj("AjFullconn", 9, "全连接调整", "AjFullconnProc", "SetAjFCPara", ".", 90, 300).output()
AjNonline = ModelObj("AjNonline", 10, "非线性调整", "AjNonlineProc", "SetAjNLPara", ".", 200, 300).output()
listinstance = [DataSet, Conv, Pool, FullConn, Nonline, Classifier, Error, AjConv, AjFullconn, AjNonline]
return listinstance # 还回图元对象实例列表
def picture_frame(window_width,window_height):
gap = 20 # 设置矩形框之间的间隔为10像素
# 计算矩形框的坐标和尺寸
rect1_x = gap # 第一个矩形框的左上角x坐标
rect1_y = gap # 第一个矩形框的左上角y坐标
11 months ago
rect1_width = window_width * 1 / 3 - gap-30 # 第一个矩形框的宽度
rect1_height = window_height * 3 / 4 - gap * 2 # 第一个矩形框的高度
rect2_x = window_width * 1 / 3 + gap - 30 # 第二个矩形框的左上角x坐标
rect2_y = gap # 第二个矩形框的左上角y坐标
11 months ago
rect2_width = window_width * 2 / 3 - gap + 30 # 第二个矩形框的宽度
rect2_height = window_height * 3 / 4 - gap * 2 # 第二个矩形框的高度
rect3_x = gap # 第三个矩形框的左上角x坐标
11 months ago
rect3_y = window_height * 3 / 4 + gap # 第三个矩形框的左上角y坐标
rect3_width = window_width - gap * 2 # 第三个矩形框的宽度
11 months ago
rect3_height = window_height * 1 / 4 - gap * 2 # 第三个矩形框的高度
global Viewcanvas
# 创建一个画布,用于绘制矩形框,设置画布的大小和背景色
11 months ago
Viewcanvas = tk.Canvas(Root, width=window_width, height=window_height, bg="white")
Viewcanvas.pack() # 将画布添加到主窗口中
# 绘制矩形框,使用不同的颜色和线宽,指定矩形框的左上角和右下角坐标,填充色,边框色和边框宽度
Viewcanvas.create_rectangle(rect1_x, rect1_y, rect1_x + rect1_width, rect1_y + rect1_height,
fill=None, outline="lightblue", width=2)
Viewcanvas.create_rectangle(rect2_x, rect2_y + 20, rect2_x + rect2_width - 20, rect2_y + rect2_height,
fill=None, outline="lightblue", width=2)
Viewcanvas.create_rectangle(rect3_x, rect3_y, rect3_x + rect3_width, rect3_y + rect3_height,
fill=None, outline="lightblue", width=2)
global Text
Text = st.ScrolledText(Root) # 创建一个带滚动条的文本框,用于展示计算过程
11 months ago
Text.place(x=rect3_x, y=rect3_y, width=760, height=rect3_height - 1)
# if __name__ == '__main__':
# Root = tk.Tk()
# # 设置窗口的大小为1200*750
# window_width = 1200 # 窗口的宽度
# window_height = 750 # 窗口的高度
# Root.title("神经网络可视化")
# Root.geometry("1200x750") # 设置窗口的大小和位置
# picture_frame(window_width, window_height)
# Root.mainloop()
def element(path):
# 加载图元对应的图片文件
img=Image.open(path)
# 使用resize方法调整图片
11 months ago
img = img.resize((40, 30))
# 把Image对象转换成PhotoImage对象
img = ImageTk.PhotoImage(img)
# 保存图片的引用,防止被垃圾回收
Root.img = img
return img
def push_button():
button = {}
11 months ago
style = ttk.Style(Root)
# 设置blue.TButton样式的背景色为亮蓝灰前景色为白色
11 months ago
style.configure("blue.TButton", background="LightSlateGray", foreground="black", font=("黑体", 10))
style.map("blue.TButton",
background=[('active', 'PowderBlue'), ('pressed', 'red')], # 设置激活状态下的背景色为粉蓝色,按下状态下的背景色为红色
foreground=[('active', 'black'), ('pressed', 'white')]) # 设置激活状态下的前景色为黑色,按下状态下的前景色为白色
# 设置green.TButton样式的背景色为中海洋绿前景色为白色
11 months ago
style.configure("green.TButton", background="MediumSeaGreen", foreground="black", font=("黑体", 8))
style.map("green.TButton",
background=[('active', 'PaleGreen'), ('pressed', 'red')], # 设置激活状态下的背景色为弱绿色,按下状态下的背景色为红色
foreground=[('active', 'black'), ('pressed', 'white')]) # 设置激活状态下的前景色为黑色,按下状态下的前景色为白色
# 创建三个按钮,用于触发训练参数的设置、训练、输出模型程序的操作
button1 = ttk.Button(Root, text=" 训练参数设置 ", style="blue.TButton")
11 months ago
button1.place(x=20, y=330)
button['button1'] = button1
button2 = ttk.Button(Root, text=" 训练 ", style="blue.TButton")
11 months ago
button2.place(x=140, y=330)
button['button2'] = button2
button3 = ttk.Button(Root, text=" 输出模型程序 ", style="blue.TButton")
11 months ago
button3.place(x=240, y=330)
button['button3'] = button3
# 创建五个按钮,用于触发操作
button4 = ttk.Button(Root, text=" 加载已有模型 ", style="green.TButton")
11 months ago
button4.place(x=255, y=10)
button['button4'] = button4
button5 = ttk.Button(Root, text=" 新建模型 ", style="green.TButton")
11 months ago
button5.place(x=355, y=10)
button['button5'] = button5
button6 = ttk.Button(Root, text=" 图元参数设置 ", style="green.TButton")
11 months ago
button6.place(x=435, y=10)
button['button6'] = button6
button7 = ttk.Button(Root, text=" 保存模型 ", style="green.TButton")
11 months ago
button7.place(x=535, y=10)
button['button7'] = button7
button8 = ttk.Button(Root, text=" 模型正确性检查 ", style="green.TButton")
11 months ago
button8.place(x=615, y=10)
button['button8'] = button8
button9 = ttk.Button(Root, text="退出", style="green.TButton")
11 months ago
button9.place(x=725, y=10)
button['button9'] = button9
return button
def setload_data():
# 设置数据集路径信息
train_imgPath = filedialog.askdirectory(title="请选择训练集") + "/" # 训练集文件夹的位置
test_imgPath = filedialog.askdirectory(title="请选择测试集") + "/" # 测试集文件夹的位置
# 设置图片大小
img_width = 48 # 图片宽度
img_height = 48 # 图片高度
# 设置每批次读入图片的数量
batch_size = 32 # 批次大小
# 返回DataPara参数这里用一个字典来存储
DataPara = {"train_imgPath": train_imgPath,
"test_imgPath": test_imgPath,
"img_width": img_width,
"img_height": img_height,
"batch_size": batch_size}
return DataPara
# 定义图元拖拽开始的函数
def on_drag_start(event):
global Dragged_item # 记录被拖拽的图元id
global Original_x # 记录图元原来的x坐标
global Original_y # 记录图元原来的y坐标
global Offset_x # 记录鼠标相对于图元的x偏移量
global Offset_y # 记录鼠标相对于图元的y偏移量
# 获取当前图元的id
# 这个物体的id是由tkinter自动分配的。当在画布上创建一个物体时它会返回一个唯一的整数id可以用它来引用这个物体
Dragged_item = event.widget.find_closest(event.x, event.y)
Original_x = event.widget.coords(Dragged_item)[0] # 获取当前图元的x坐标
Original_y = event.widget.coords(Dragged_item)[1] # 获取当前图元的y坐标
Offset_x = Original_x - event.x # 计算鼠标相对于图元的x偏移量
Offset_y = Original_y - event.y # 计算鼠标相对于图元的y偏移量
# 定义图元拖拽移动的函数
def on_drag_motion(event):
x = event.x + Offset_x # 计算图元新的x坐标
y = event.y + Offset_y # 计算图元新的y坐标
event.widget.coords(Dragged_item, x, y) # 更新图元的位置
def entity_loading_dataset(event):
global Viewcanvas
x = event.x + Offset_x
y = event.y + Offset_y
Items3.append(0) # 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
new_item1 = Viewcanvas.create_image(x, y, image=List_image[0]) # 复制一个图片表示数据集1
Viewcanvas.create_text(x, y + 45, text='数据集')# 复制图元对象的标签
event.widget.coords(Dragged_item, Original_x, Original_y)# 恢复图元的原位置
Items1.append((new_item1, x, y))# 将新图元的id和坐标添加到列表中
global Yt
Items_y = Items1[0] # 将新图元的y坐标取出方便后续图元水平排列
Yt = Items_y[2]
# 创建一个tkinter根窗口并隐藏它
root1 = tk.Tk()
root1.withdraw()
DataPara = setload_data() # 调用X3中setload_data()函数,获取加载数据集的参数
global Train_images
global Test_images
Train_images, Test_images = load_data(DataPara) # 调用X3中load_data()函数,根据参数加载数据集
# 打印一些信息,检查是否正确加载
print("训练集图片的形状:", Train_images.shape)
print("测试集图片的形状:", Test_images.shape)
# 创建弹出窗口
def creat_window(title):
top = tk.Toplevel(Root)
top.geometry("300x350")
top.title(title)
return top
# 输入框
def create_input_box(top, text,value):
box_label = tk.Label(top, text=text)
box_label.pack(padx=10, pady=10)
box_size = tk.IntVar(top, value=value) # 创建一个IntVar对象并设置默认值为3
box_size_entry = tk.Entry(top, textvariable=box_size) # 关联IntVar对象
box_size_entry.pack(padx=20, pady=20)
return box_size_entry
# 下拉框
def create_dropdown_box(top, text, listvalues):
# 创建一个下拉框,用于选择
box_mode_label = tk.Label(top, text=text)
box_mode_label.pack(padx=10, pady=10)
box_mode_combobox = ttk.Combobox(top)
box_mode_combobox["values"] = listvalues
box_mode_combobox.pack(padx=20, pady=15)
return box_mode_combobox
def convolution(event):
global Items3
global Viewcanvas
x = event.x + Offset_x
Items3.append(1) # 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
new_item1 = Viewcanvas.create_image(x, Yt, image=List_image[1]) # 复制一个图片,表示卷积层
event.widget.coords(Dragged_item, Original_x, Original_y) # 恢复图元的原位置
Items1.append((new_item1, x, Yt)) # 将新图元的id和坐标添加到列表中
top = creat_window('卷积参数配置') # 创建弹出窗口
kernel_size_entry = create_input_box(top,"卷积核大小:",3) # 创建一个输入框,获取卷积核大小
stride_entry = create_input_box(top,"卷积核大小:",1) # 创建一个输入框,获取卷积步长
def get_input(): # 创建
global Listinstance
result1 = int(kernel_size_entry.get())# 获取输入框的内容
result2 = int(stride_entry.get())
Viewcanvas.create_text(x, Yt + 40, text=str(result1) + "*" + str(result1) + "卷积") # 创建图元对象的标签
if Listinstance[1][5] == ".":
Listinstance[1][5] = str(result1) + "," + str(result2)
else:
Listinstance[1][5] = Listinstance[1][5] + " " + str(result1) + "," + str(result2)
top.destroy()# 关闭窗口
button = tk.Button(top, text="获取信息", command=get_input)
button.pack()
def pooling(event):
global Items3
global Viewcanvas
x = event.x + Offset_x
# 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
Items3.append(2)
# 复制一个图片,表示池化层
new_item1 = Viewcanvas.create_image(x, Yt, image=List_image[2])
# 恢复图元的原位置
event.widget.coords(Dragged_item, Original_x, Original_y)
# 将新图元的id和坐标添加到列表中
Items1.append((new_item1, x, Yt))
# 创建弹出窗口
top=creat_window("池化参数配置")
pool_type_combobox=create_dropdown_box(top, "池化池类型:", ["max", "avg", "min"])# 创建一个下拉框,用于选择池化类型
pool_size_entry = create_input_box(top, "池化池大小:", 2)# 创建一个输入框,用于输入池大小
# 创建
def get_input():
# 从下拉框中获取池化类型
pool_type = pool_type_combobox.get()
# 从输入框中获取池大小
pool_size = int(pool_size_entry.get())
# 复制对象的标签
Viewcanvas.create_text(x, Yt + 40, text=str(pool_size) + "*" + str(pool_size) + str(pool_type) + "池化")
if Listinstance[2][5] == ".":
Listinstance[2][5] = str(pool_type) + "," + str(pool_size)
else:
Listinstance[2][5] = Listinstance[2][5] + " " + str(pool_type) + "," + str(pool_size)
# 关闭窗口
top.destroy()
button = tk.Button(top, text="获取信息", command=get_input)
button.pack()
def fully_connected(event):
global Items3
global Viewcanvas
x = event.x + Offset_x
# 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
Items3.append(3)
# 复制一个图片,表示全连接层
new_item1 = Viewcanvas.create_image(x, Yt, image=List_image[3])
# 恢复图元的原位置
event.widget.coords(Dragged_item, Original_x, Original_y)
# 将新图元的id和坐标添加到列表中
Items1.append((new_item1, x, Yt))
11 months ago
top = tk.Toplevel(Root) # 创建弹出窗口
top.geometry("300x250")
top.title("全连接参数配置")
num_outputs_entry = create_input_box(top, "全连接输出维度:", 10)
# 创建
def get_input():
global Listinstance
# 从下拉框中获取输出维度
11 months ago
num = int(num_outputs_entry.get())
# 复制对象的标签
Viewcanvas.create_text(x, Yt + 40, text=str(num) + "--全连接")
if Listinstance[3][5] == ".":
Listinstance[3][5] = str(num)
else:
Listinstance[3][5] = Listinstance[3][5] + " " + str(num)
# 关闭窗口
top.destroy()
button = tk.Button(top, text="获取信息", command=get_input)
button.pack(padx=20, pady=50)
def nonlinear(event):
global Items3
global Viewcanvas
x = event.x + Offset_x
# 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
Items3.append(4)
# 复制一个图片,表示非线性函数图元
new_item1 = Viewcanvas.create_image(x, Yt, image=List_image[4])
# 恢复图元的原位置
event.widget.coords(Dragged_item, Original_x, Original_y)
# 将新图元的id和坐标添加到列表中
Items1.append((new_item1, x, Yt))
top = creat_window('非线性参数配置') # 创建弹出窗口
# 创建一个下拉框,用于选择非线性类型
nonlinear_mode_combobox = create_dropdown_box(top, "非线性类型", ["Sigmoid", "ReLU", "Tanh"])# 创建一个下拉框,用于选择池化类型
# 创建
def get_input():
global Listinstance
# 从下拉框中获取池化类型
nonlinear_mode = nonlinear_mode_combobox.get()
# 复制对象的标签
Viewcanvas.create_text(x, Yt + 40, text=str(nonlinear_mode) + "处理")
if Listinstance[4][5] == ".":
Listinstance[4][5] = str(nonlinear_mode)
else:
Listinstance[4][5] = Listinstance[4][5] + " " + str(nonlinear_mode)
# 关闭窗口
top.destroy()
button = tk.Button(top, text="获取信息", command=get_input)
button.pack()
def class_ification(event):
global Listinstance
global Viewcanvas
global Items3
x = event.x + Offset_x
# 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
Items3.append(5)
# 复制一个图片,表示分类器
new_item1 = Viewcanvas.create_image(x, Yt, image=List_image[5])
# 恢复图元的原位置
event.widget.coords(Dragged_item, Original_x, Original_y)
# 将新图元的id和坐标添加到列表中
Items1.append((new_item1, x, Yt))
11 months ago
top = tk.Toplevel(Root) # 创建弹出窗口
top.geometry("300x250")
top.title("分类参数配置")
# 创建一个输入框,用于输入阈值
threshold_label = tk.Label(top, text="阈值:")
threshold_label.pack(padx=10, pady=10)
threshold = tk.DoubleVar(top, value=0.001) # 创建一个DoubleVar对象并设置默认值为0.001
threshold_entry = tk.Entry(top, textvariable=threshold) # 关联DoubleVar对象
threshold_entry.pack(padx=20, pady=20)
# 创建
def get_input():
# 从输入框中获取阈值
11 months ago
threshold = float(threshold_entry.get())
# 复制对象的标签
Viewcanvas.create_text(x, Yt + 40, text="输出分类结果")
if Listinstance[5][5] == ".":
Listinstance[5][5] = str(threshold)
else:
Listinstance[5][5] = Listinstance[5][5] + " " + str(threshold)
# 关闭窗口
top.destroy()
button = tk.Button(top, text="获取信息", command=get_input)
button.pack()
def error_calculation(event):
global Items3
global Viewcanvas
x = event.x + Offset_x
y = event.y + Offset_y
# 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
Items3.append(6)
# 复制一个图片,表示误差计算
new_item1 = Viewcanvas.create_image(x, y, image=List_image[6])
# 恢复图元的原位置
event.widget.coords(Dragged_item, Original_x, Original_y)
# 将新图元的id和坐标添加到列表中
Items1.append((new_item1, x, y))
global x_loss
global y_loss
x_loss = x
y_loss = y
# 创建弹出窗口
top = creat_window('误差参数配置')
# 创建一个下拉框,用于选择误差类型
loss_type_combobox=create_dropdown_box(top, '', ["CEE", "MSE", "MAE"])
# 创建
def get_input():
# 从下拉框中获取池化类型
loss_type = loss_type_combobox.get()
# 复制对象的标签
Viewcanvas.create_text(x, y_loss + 40,
text=str(loss_type) + "误差计算")
if Listinstance[6][5] == ".":
Listinstance[6][5] = str(loss_type)
else:
Listinstance[6][5] = Listinstance[6][5] + " " + str(loss_type)
# 关闭窗口
top.destroy()
button = tk.Button(top, text="获取信息", command=get_input)
button.pack()
def adjust_one(event):
global Viewcanvas
global Items1
global Items3
x = event.x + Offset_x
y = event.y + Offset_y
# 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
Items3.append(7)
# 复制一个图片,表示调整操作
new_item1 = Viewcanvas.create_image(x, y_loss - 20, image=List_image[7])
Viewcanvas.create_text(x, y_loss + 20, text='调整1')# 复制对象的标签
event.widget.coords(Dragged_item, Original_x, Original_y) # 恢复图元的原位置
Items1.append((new_item1, x, y))# 将新图元的id和坐标添加到列表中
def adjust_two(event):
global Viewcanvas
global Items1
global Items3
x = event.x + Offset_x
y = event.y + Offset_y
# 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
Items3.append(8)
# 复制一个图片,表示调整操作
new_item1 = Viewcanvas.create_image(x, y_loss + 20, image=List_image[7])
# 复制对象的标签
Viewcanvas.create_text(x, y_loss + 60, text='调整2')
event.widget.coords(Dragged_item, Original_x, Original_y) # 恢复图元的原位置
# 将新图元的id和坐标添加到列表中
Items1.append((new_item1, x, y))
def adjust_three(event):
global Viewcanvas
global Items1
global Items3
x = event.x + Offset_x
y = event.y + Offset_y
# 记录被拖拽的原始图元的id方便后续进行模型的正确性检查
Items3.append(9)
# 复制一个图片,表示调整操作
new_item1 = Viewcanvas.create_image(x, y, image=List_image[7])
# 复制对象的标签
Viewcanvas.create_text(x, y + 40, text='调整3')
event.widget.coords(Dragged_item, Original_x, Original_y) # 恢复图元的原位置
# 将新图元的id和坐标添加到列表中
Items1.append((new_item1, x, y))
def train_setting():
global Train_list
Train_list = []
top = creat_window("训练参数配置")# 创建弹出的参数配置窗口
epoch_entry = create_input_box(top,"训练轮数:", 4)# 创建一个输入框,获取训练轮数
rate_entry=create_input_box(top, '学习率:', 0.1)# 创建一个输入框,获取学习率
batch_size_entry=create_input_box(top, "批次:", 60)# 创建一个输入框,获取批次
# 创建
def get_input():
# 获取输入框的内容
result1 = int(epoch_entry.get())
result2 = float(rate_entry.get())
result3 = int(batch_size_entry.get())
Train_list.append(result1)
Train_list.append(result2)
Train_list.append(result3)
# 关闭窗口
top.destroy()
button = tk.Button(top, text="获取信息", command=get_input)
button.pack()
def connecting_line():
global Viewcanvas
global Items2
last_item = Items1[-1] # 获取最后一个图元的id和坐标
prev_item = Items1[-2] # 获取倒数第二个图元的id和坐标
# 获取最后一个图元的边界框坐标,形式为(x1,y1,x2,y2),其中(x1,y1)是左上角,(x2,y2)是右下角
last_bbox = Viewcanvas.bbox(last_item[0])
# 获取倒数第二个图元的边界框坐标,形式同上
prev_bbox = Viewcanvas.bbox(prev_item[0])
# 计算线条的起点和终点,使其与图元的边界对齐,并留出一定距离以避免重叠
start_x = prev_bbox[2] + 5 # 起点x坐标为倒数第二个图元右边界加10像素
start_y = prev_bbox[3] - (prev_bbox[3] - prev_bbox[1]) / 2 # 起点y坐标为倒数第二个图元垂直中心
end_x = last_bbox[0] # 终点x坐标为最后一个图元左边界
end_y = last_bbox[3] - (last_bbox[3] - last_bbox[1]) / 2 # 终点y坐标为最后一个图元垂直中心
# 创建一条线,带有箭头,并设置箭头形状、大小、颜色和平滑度等参数
if Items3[-1] < 6:
new_item = Viewcanvas.create_line(start_x, start_y, end_x, end_y, arrow=tk.LAST,
arrowshape=(16, 20, 4), fill='lightblue', smooth=True)
if Items3[-1] == 1:
x = last_bbox[2] - (last_bbox[2] - last_bbox[0]) / 2
y = last_bbox[1]
Conv_xy_list.append((x, y))
if Items3[-1] == 3:
x = last_bbox[2] - (last_bbox[2] - last_bbox[0]) / 2
y = last_bbox[1]
Fullconn_xy_list.append((x, y))
elif Items3[-1] == 6:
# 计算折线的中间点,使其与图元的边界对齐,并留出一定距离以避免重叠
mid_x = prev_bbox[2] - (prev_bbox[2] - prev_bbox[0]) / 2 # 中间点x坐标为起点和终点的平均值
mid_y = prev_bbox[1] - 80 # 中间点y坐标为起点y坐标减20像素
# 创建一条折线,带有箭头,并设置箭头形状、大小、颜色和平滑度等参数
x1 = prev_bbox[2] - (prev_bbox[2] - prev_bbox[0]) / 2
y1 = prev_bbox[1]
x2 = last_bbox[2]
y2 = last_bbox[3] - (last_bbox[3] - last_bbox[1]) / 2
new_item = Viewcanvas.create_line(x1, y1, mid_x, mid_y, x2, y2, arrow=tk.LAST,
arrowshape=(16, 20, 4), fill='lightblue', smooth=False)
elif Items3[-1] == 7:
x1 = x_loss
y1 = y_loss
x2, y2 = Conv_xy_list[0]
new_item = Viewcanvas.create_line(x1, y1, last_bbox[2] - (last_bbox[2] - last_bbox[0]) / 2,
last_bbox[3] - (last_bbox[3] - last_bbox[1]) / 2, x2, y2, arrow=tk.LAST,
arrowshape=(16, 20, 4), fill='lightblue', smooth=False)
Conv_xy_list.remove(Conv_xy_list[0])
elif Items3[-1] == 8:
x1 = x_loss
y1 = y_loss
x2, y2 = Fullconn_xy_list[0]
new_item = Viewcanvas.create_line(x1, y1, last_bbox[2] - (last_bbox[2] - last_bbox[0]) / 2,
last_bbox[3] - (last_bbox[3] - last_bbox[1]) / 2, x2, y2, arrow=tk.LAST,
arrowshape=(16, 20, 4), fill='lightblue', smooth=False)
Fullconn_xy_list.remove(Fullconn_xy_list[0])
Items2.append(new_item)
def on_drag(obj_id1,event):
while obj_id1 == 4: # 如果拖拽的是图元加载数据集
entity_loading_dataset(event)
break
while obj_id1 == 6: # 卷积
convolution(event)
break
while obj_id1 == 8: # 池化
pooling(event)
break
while obj_id1 == 10: # 全连接
fully_connected(event)
break
while obj_id1 == 12: # 非线性
nonlinear(event)
break
while obj_id1 == 14: # 分类
class_ification(event)
break
while obj_id1 == 16: # 误差计算
error_calculation(event)
break
while obj_id1 == 18: # 调整1
adjust_one(event)
break
while obj_id1 == 20: # 调整2
adjust_two(event)
break
while obj_id1 == 22: # 调整3
adjust_three(event)
break
# 定义图元拖拽结束的函数
def on_drag_end(event):
obj_id1 = Dragged_item[0] # 获取被拖拽的图元的id
# 使用 print(obj_id1) 从而查看各个图元的id,此步省略
# 根据图元的类型,复制相应的图片到右侧画布
on_drag(obj_id1,event)
# 如果列表中有至少两个图元,就创建一条线,连接最后两个图元的中心点
while len(Items1) >= 2:
connecting_line()
break
def element_binding(obj_x, obj_y, image, y, text):
global Viewcanvas
l1 = Viewcanvas.create_image(obj_x, obj_y, image=image) # 创建图元对象
# 创建图元对象的标签
11 months ago
Viewcanvas.create_text(obj_x - 40, obj_y + y, text=text, font=("黑体", 10))
return l1
def create_left_element(AllModelObj,List_image):
global Viewcanvas
# 遍历AllModelObj列表在窗口左侧创建图元菜单
for obj in AllModelObj:
# 获取图元对象的类型、标签等信息
obj_type = obj[1]
# 并且要根据需求调整每个对象的位置
obj_x = obj[6] # 根据对象的id计算x坐标
obj_y = obj[7] # 根据对象的id计算y坐标
# 根据对象的类型,绘制相应的图形
if obj_type == 1: # 加载数据集
l1 = element_binding(obj_x, obj_y, List_image[0], 3, " 加载" + "\n" + "数据集")
elif obj_type == 2: # 卷积
l1 = element_binding(obj_x, obj_y, List_image[1], 0, "卷积")
elif obj_type == 3: # 池化
l1 = element_binding(obj_x, obj_y, List_image[2], 0, "池化")
elif obj_type == 4: # 全连接
l1 = element_binding(obj_x, obj_y, List_image[3], 0, "全连接" + "\n" + " 函数")
elif obj_type == 5: # 非线性
l1 = element_binding(obj_x, obj_y, List_image[4], 0, "非线性" + "\n" + " 函数")
elif obj_type == 6: # 分类
l1 = element_binding(obj_x, obj_y, List_image[5], 0, "类别")
elif obj_type == 7: # 误差计算
l1 = element_binding(obj_x, obj_y, List_image[6], 0, "误差")
elif obj_type == 8: # 调整
l1 = element_binding(obj_x, obj_y, List_image[7], 0, "调整1")
elif obj_type == 9: # 调整
l1 = element_binding(obj_x, obj_y, List_image[7], 0, "调整2")
elif obj_type == 10: # 调整
l1 = element_binding(obj_x, obj_y, List_image[7], 0, "调整3")
elif obj_type == 11: # 调整
l1 = element_binding(obj_x, obj_y, List_image[8], 3, "主数据连接线")
elif obj_type == 12: # 调整
l1 = element_binding(obj_x, obj_y, List_image[9], 3, "参数连接线")
# 为左边菜单的每个图元绑定鼠标按下、移动和松开的事件
Viewcanvas.tag_bind(l1, "<Button-1>", on_drag_start)
Viewcanvas.tag_bind(l1, "<B1-Motion>", on_drag_motion)
Viewcanvas.tag_bind(l1, "<ButtonRelease-1>", on_drag_end)
# if __name__ == '__main__':
# Root = tk.Tk()
# # 设置窗口的大小为1200*750
# window_width = 1200 # 窗口的宽度
# window_height = 750 # 窗口的高度
# Root.title("神经网络可视化")
# Root.geometry("1200x750") # 设置窗口的大小和位置
# picture_frame(window_width,window_height)
# Listinstance = create_instance()
# listclass = connect_class(Listinstance)
# # 创建网络对象总表和网络连接对象总表
# AllModelObj = [Listinstance[0], Listinstance[1], Listinstance[2], Listinstance[3], Listinstance[4], Listinstance[5],
# Listinstance[6], Listinstance[7], Listinstance[8], Listinstance[9]]
# AllModelConn = [listclass[0], listclass[1], listclass[2], listclass[3], listclass[4], listclass[5], listclass[6],
# listclass[7], listclass[8], listclass[9]]
# img_path = ["img/data.png", "img/conv.png", "img/pool.png", "img/full_connect.png", "img/nonlinear.png",
# "img/classifier.png", "img/error.png", "img/adjust.png", "img/arrow1.png", "img/arrow2.png"]
# List_image = []
# for path in img_path:
# List_image.append(element(path))
# create_left_element(AllModelObj, List_image)
# button = push_button()
# Root.mainloop()
# if __name__ == '__main__':
# Root = tk.Tk()
# train_setting()
# Root.mainloop()
def check_connection():
connection = [x for x in Items3 if x < 6]
length = len(connection)
if length == 0:
messagebox.showerror("错误", "请添加图元!")
return
for i in range(length-1):
right_model_x = connection[i]
right_model_y = connection[i+1]
if RIGHT_MODEL[right_model_x][right_model_y] == 0:
messagebox.showerror("错误", "连接不正确,请检查!")
return
messagebox.showinfo("成功", "连接正确,恭喜!")
def number_judgments(lsts):
global Items3
count = []
sequence = []
for index,lll in enumerate(lsts):
if type(lll) == list:
count.append(lll[1])
sequence.append(index)
11 months ago
if lll[1]==7:
break
count_2,count_3,count_4=0,0,0
list_count=[]
for i in count:
if i == 2:
count_2 += 1
list_count.append(i*10+count_2)
elif i == 3:
count_3 += 1
list_count.append(i * 10 + count_3)
elif i == 4:
count_4 += 1
list_count.append(i * 10 + count_4)
else:
list_count.append(i * 10)
Items3 = [0]
for i in count:
Items3.append(i - 1)
return count,list_count,sequence
def load_file():
filename = filedialog.askopenfilename(filetypes=[("Pickle files", "*.pkl")])
# 从本地文件中读取两个列表用rb模式打开文件
with open(filename, "rb") as f:
# 创建一个空列表,用来存储读取的列表
lsts = []
# 用一个循环来读取所有的列表,直到文件结束
while True:
try:
# 读取一个列表,并追加到大列表中
lst = pickle.load(f)
lsts.append(lst)
except EOFError:
# 如果遇到文件结束的错误,就跳出循环
break
return lsts
def connecting_lines(obj_x, obj_y, index, x, y, x1, x2, y1, y2, y3 , image, text, smooth, width):
# 创建图元对象
11 months ago
Viewcanvas.create_image(obj_x+(index + x) * 80, obj_y, image=image)
# 创建图元对象的标签
11 months ago
Viewcanvas.create_text(obj_x+(index + x) * 80, obj_y + y1, text=text, font=("黑体", 8))
# 创建数据线箭头
11 months ago
Viewcanvas.create_line(obj_x+(index + x) * 80 + x1, obj_y + y2, obj_x+(index + y) * 80 + x2, obj_y + y3, arrow=tk.LAST,
arrowshape=(16, 20, 4), fill='lightblue', smooth=smooth, width=1)
def connecting(obj_x, obj_y, index, x, y1, image, text):
# 创建图元对象
11 months ago
Viewcanvas.create_image(obj_x+(index + x) * 80, obj_y, image=image)
# 创建图元对象的标签
11 months ago
Viewcanvas.create_text(obj_x+(index + x) * 80, obj_y + y1, text=text, font=("黑体", 8))
# 加载已有模型
def load_model():
import copy
global Train_images
global Test_images
global Viewcanvas
global Listinstance
global Viewcanvas
lsts = load_file()
DataPara = setload_data()
11 months ago
Viewcanvas.delete('all')
create_left_element(AllModelObj, List_image)
Train_images, Test_images = load_data(DataPara) # load_data()函数,根据参数加载数据集
# 打印一些信息,检查是否正确加载
print("训练集图片的形状:", Train_images.shape)
print("测试集图片的形状:", Test_images.shape)
# 根据pkl文件的前向传播顺序列表依次识别卷积层、池化层、全连接层、非线性层和分类层的操作
count,counts,sequence = number_judgments(lsts)
11 months ago
x,y = 290,200
connecting_lines(x, y, 0, 0, 0, 25, 60, 45, 0, 0, List_image[0], '数据集', True, 3)
for layer in range(len(count)):
if count[layer] == 2: # 如果是卷积层将读取的卷积层的信息存储到Conv实例
11 months ago
if counts[layer] % 10 == 1:
global Conv1
Listinstance[1] = copy.deepcopy(lsts[sequence[layer]])
Conv1 = lsts[sequence[layer]]
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[1], '卷积层1', True, 3)
11 months ago
if counts[layer] % 10 == 2:
global Conv2
Conv2 = lsts[sequence[layer]]
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[1], '卷积层2', True, 3)
11 months ago
if counts[layer] % 10 == 3:
global Conv3
Conv3 = lsts[sequence[layer]]
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[1], '卷积层3', True, 3)
if count[layer] == 3: # 如果是池化层将读取的池化层的信息存储到Pool实例
11 months ago
if counts[layer] % 10 == 1:
global Pool1
Listinstance[2] =copy.deepcopy(lsts[sequence[layer]])
Pool1 = lsts[sequence[layer]]
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[2], '池化1', True, 3)
if counts[layer]%10 == 2:
global Pool2
Pool2 = lsts[sequence[layer]]
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[2], '池化2', True, 3)
if counts[layer]%10 == 3:
global Pool3
Pool3 = lsts[sequence[layer]]
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[2], '池化3', True, 3)
if count[layer] == 4: # 如果是全连接层将读取的全连接层的信息存储到Pool实例
if counts[layer]%10 == 1:
global Fullconn1
Listinstance[3] = lsts[sequence[layer]]
Fullconn1 = copy.deepcopy(lsts[sequence[layer]])# 深拷贝创建了一个全新的对象,要使用深拷贝,不然报错
Listinstance[3][5] = str(Fullconn1[5][1]["num_outputs"])
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[3], '全连接1', True, 3)
if counts[layer]%10 == 2:
global Fullconn2
Fullconn2 = lsts[sequence[layer]]
# FullConn[5] = FullConn[5] + " " + str(Fullconn2[5][2]["num_outputs"])
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[3], '全连接3', True, 3)
if counts[layer]%10 == 3:
global Fullconn3
Fullconn3 = lsts[sequence[layer]]
# FullConn[5] = FullConn[5] + " " + str(Fullconn3[5][3]["num_outputs"])
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[3], '全连接3', True, 3)
if count[layer] == 5: # 如果是非线性层将读取的非线性层的信息存储到Nonline实例
Listinstance[4] = lsts[sequence[layer]]
connecting_lines(x, y, layer, 1, 2, 25, -25, 45, 0, 0, List_image[4], '非线性', True, 3)
if count[layer] == 6: # 如果是分类输出层将读取的信息存储到Nonline实例
Listinstance[5] = lsts[sequence[layer]]
connecting(x, y, layer, 1, 45,List_image[5], '分类')
if count[layer] == 7: # 如果是计算误差层将读取的信息存储到Error实例
Listinstance[6] = lsts[sequence[layer]]
connecting(x-30, y-120, layer, 0, 45, List_image[6], '计算误差')
11 months ago
Viewcanvas.create_line(x + 5 * 80 + 25, y, x + 5 * 80 + 20, y - 80,
x + 5 * 80 -20 , y-120, arrow=tk.LAST, arrowshape=(16, 20, 4),
fill='lightblue', smooth=True, width=1)
def create_window(number,count,list1,list2,list3,list4,list5,list6):
global Listinstance
if number == 1:
# 把数字的出现次数加一
count[number] = count.get(number, 0) + 1
if count[number] == 1:
# 获取第一层卷积层的参数
para_list = list1[count[number] - 1].split(",")
para_list = [int(x) for x in para_list]
window = creat_window('卷积1参数调整') # 创建一个新的窗口
kernel_size_entry = create_input_box(window, "卷积核大小:", para_list[0]) # 创建一个输入框,获取卷积核大小
stride_entry = create_input_box(window, "卷积步长:", para_list[1]) # 创建一个输入框,获取卷积步
def modify_para():
# 获取输入框的内容
result1 = int(kernel_size_entry.get())
result2 = int(stride_entry.get())
new_para = str(result1)+ ','+str(result2)
Listinstance[1][5] = Listinstance[1][5].replace(list1[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="卷积参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
if count[number] == 2:
# 获取第一层卷积层的参数
para_list = list1[count[number] - 1].split(",")
para_list = [int(x) for x in para_list]
window = creat_window('卷积2参数调整') # 创建一个新的窗口
kernel_size_entry = create_input_box(window, "卷积核大小:", para_list[0]) # 创建一个输入框,获取卷积核大小
stride_entry = create_input_box(window, "卷积步长:", para_list[1]) # 创建一个输入框,获取卷积步
def modify_para():
# 获取输入框的内容
result1 = int(kernel_size_entry.get())
result2 = int(stride_entry.get())
new_para = str(result1)+ ','+str(result2)
Listinstance[1][5] = Listinstance[1][5].replace(list1[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="卷积参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
if count[number] == 3:
# 获取第一层卷积层的参数
para_list = list1[count[number] - 1].split(",")
para_list = [int(x) for x in para_list]
# 创建一个输入框,获取卷积核大小
window = creat_window('卷积3参数调整') # 创建一个新的窗口
kernel_size_entry = create_input_box(window, "卷积核大小:", para_list[0]) # 创建一个输入框,获取卷积核大小
stride_entry = create_input_box(window, "卷积步长:", para_list[1]) # 创建一个输入框,获取卷积步
def modify_para():
# 获取输入框的内容
result1 = int(kernel_size_entry.get())
result2 = int(stride_entry.get())
new_para = str(result1)+ ','+str(result2)
Listinstance[1][5] = Listinstance[1][5].replace(list1[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="卷积参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
# 返回窗口对象
return window
# 如果是池化层
if number == 2:
# 把数字的出现次数加一
count[number] = count.get(number, 0) + 1
if count[number] == 1:
# 获取第一层卷积层的参数
para_list = list2[count[number] - 1].split(",")
para_list[1] = int(para_list[1])
window = creat_window('池化1参数调整') # 创建一个新的窗口
pool_type_combobox = create_dropdown_box(window, "池化池类型:", ["max", "avg", "min"]) # 创建一个下拉框,用于选择池化类型
pool_size_entry = create_input_box(window, "池化池大小:", para_list[1]) # 创建一个输入框,获取卷积步
def modify_para():
# 从下拉框中获取池化类型
pool_type = pool_type_combobox.get()
# 从输入框中获取池大小
pool_size = int(pool_size_entry.get())
# 关闭窗口
new_para = str(pool_type)+ ','+str(pool_size)
Listinstance[2][5] = Listinstance[2][5].replace(list2[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="池化参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
if count[number] == 2:
# 获取第一层卷积层的参数
para_list = list2[count[number] - 1].split(",")
para_list[1] = int(para_list[1])
window = creat_window('池化2参数调整') # 创建一个新的窗口
pool_type_combobox = create_dropdown_box(window, "池化池类型:", ["max", "avg", "min"]) # 创建一个下拉框,用于选择池化类型
pool_size_entry = create_input_box(window, "池化池大小:", para_list[1]) # 创建一个输入框,获取卷积步
def modify_para():
# 从下拉框中获取池化类型
pool_type = pool_type_combobox.get()
# 从输入框中获取池大小
pool_size = int(pool_size_entry.get())
# 关闭窗口
new_para = str(pool_type)+ ','+str(pool_size)
Listinstance[2][5] = Listinstance[2][5].replace(list2[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="池化参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
if count[number] == 3:
# 获取第一层卷积层的参数
para_list = list2[count[number] - 1].split(",")
para_list[1] = int(para_list[1])
window = creat_window('池化3参数调整') # 创建一个新的窗口
pool_type_combobox = create_dropdown_box(window, "池化池类型:", ["max", "avg", "min"]) # 创建一个下拉框,用于选择池化类型
pool_size_entry = create_input_box(window, "池化池大小:", para_list[1]) # 创建一个输入框,获取卷积步
def modify_para():
# 从下拉框中获取池化类型
pool_type = pool_type_combobox.get()
# 从输入框中获取池大小
pool_size = int(pool_size_entry.get())
# 关闭窗口
new_para = str(pool_type)+ ','+str(pool_size)
Listinstance[2][5] = Listinstance[2][5].replace(list2[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="池化参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
# 返回窗口对象
return window
if number == 3:
# 把数字的出现次数加一
count[number] = count.get(number, 0) + 1
if count[number] == 1:
# 获取第一层全连接层的参数
para = list3[count[number] - 1]
para = int(para)
window = creat_window('全连接1参数调整') # 创建一个新的窗口
num_outputs_entry = create_input_box(window, "输出维度:", para) # 创建一个输入框,获取卷积步
def modify_para():
# 获取输入框的内容
num = int(num_outputs_entry.get())
new_para = str(num)
Listinstance[3][5] = Listinstance[3][5].replace(list3[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="全连接参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
if count[number] == 2:
# 获取第一层全连接层的参数
para = list3[count[number] - 1]
para = int(para)
window = creat_window('全连接2参数调整') # 创建一个新的窗口
num_outputs_entry = create_input_box(window, "输出维度:", para) # 创建一个输入框,获取全连接
def modify_para():
# 获取输入框的内容
num = int(num_outputs_entry.get())
new_para = str(num)
Listinstance[3][5] = Listinstance[3][5].replace(list3[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="全连接参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
if count[number] == 3:
# 获取第一层全连接层的参数
para = list3[count[number] - 1]
para = int(para)
window = creat_window('全连接3参数调整') # 创建一个新的窗口
num_outputs_entry = create_input_box(window, "输出维度:", para) # 创建一个输入框,获取全连接
def modify_para():
# 获取输入框的内容
num = int(num_outputs_entry.get())
new_para = str(num)
Listinstance[3][5] = Listinstance[3][5].replace(list3[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="全连接参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
# 返回窗口对象
return window
if number == 4:
# 把数字的出现次数加一
count[number] = count.get(number, 0) + 1
if count[number] == 1:
# 获取第一层非线性层的参数
para = list3[count[number] - 1]
window = creat_window('非线性1参数调整') # 创建一个新的窗口
nonlinear_mode_combobox = create_dropdown_box(window, "非线性类型:",
["Sigmoid", "ReLU", "Tanh"]) # 创建一个下拉框,用于选择非线性类型
def modify_para():
# 获取输入框的内容
nonlinear_mode = nonlinear_mode_combobox.get()
new_para = f"{nonlinear_mode}"
Listinstance[4][5] = Listinstance[4][5].replace(list4[count[number] - 1], new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="非线性参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
# 返回窗口对象
return window
if number == 5:
# 把数字的出现次数加一
count[number] = count.get(number, 0) + 1
if count[number] == 1:
# 获取分类的参数
para = list5
para = float(para)
window = creat_window('分类参数调整') # 创建一个新的窗口
threshold_entry = create_input_box(window, "阈值:", para) # 创建一个输入框,用于输入阈值
11 months ago
def modify_para():
# 获取输入框的内容
threshold = threshold_entry.get()
new_para = str(threshold)
Listinstance[5][5] = Listinstance[5][5].replace(list5, new_para)
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="分类参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
# 返回窗口对象
return window
if number == 6:
# 把数字的出现次数加一
count[number] = count.get(number, 0) + 1
if count[number] == 1:
# 获取分类的参数
para = list6
window = creat_window('误差参数调整') # 创建一个新的窗口
loss_type_combobox = create_dropdown_box(window, "误差类型:",
["CEE", "MSE", "MAE"]) # 创建一个下拉框,用于选择误差类型
def modify_para():
# 获取输入框的内容
loss_type = loss_type_combobox.get()
new_para = str(loss_type)
Listinstance[6][5] = Listinstance[6][5].replace(list6[count[number] - 1], new_para)
print(Listinstance[6])
# 关闭窗口
window.destroy()
# 创建一个按钮,文本为数字
button = tk.Button(window, text="误差参数修改")
# 绑定按钮的点击事件,使得点击后销毁窗口
button.config(command=modify_para)
# 把按钮放在窗口中
button.pack()
return window # 返回窗口对象
# 清空当前模型展示区
def restart_new_model():
# 这将在子进程中调用当前Python解释器并传递当前文件的路径作为参数
subprocess.call([sys.executable, __file__])
def setpara_func(): # 图元参数配置与修改
global Viewcanvas
# 一个字典,用来记录每个数字出现的次数
count = {}
list1 = Listinstance[1][5].split()
list2 = Listinstance[2][5].split()
list3 = Listinstance[3][5].split()
list4 = Listinstance[4][5].split()
list5 = Listinstance[5][5]
list6 = Listinstance[6][5].split()
for i in Items4: # 清除所有文字标签
Viewcanvas.delete(i[0])
numbers = [x for x in Items3 if x <= 6] # 一个函数,用来创建一个带有一个数字标签的按钮的窗口
numbers = numbers[1:]
def iterate_numbers(): # 一个函数,用来遍历数字列表,依次创建窗口
if numbers: # 如果数字列表不为空
number = numbers.pop(0) # 从列表中弹出第一个数字
window = create_window(number, count, list1, list2, list3, list4, list5, list6)
window.wait_window() # 等待窗口被关闭
iterate_numbers() # 再次调用这个函数,创建下一个窗口
iterate_numbers() # 调用遍历数字的函数
def redirector(inputStr):
global Text
Text.configure(state="normal") # 设置文本框为可编辑状态
Text.insert("end", inputStr) # 在文本框末尾插入内容
Text.see("end") # 滚动到末尾
Text.configure(state="disabled") # 设置文本框为只读状态
def close_program():
sys.exit()
if __name__ == '__main__':
# 创建一个主窗口
Root = tk.Tk()
# 设置窗口的大小为1200*750
11 months ago
window_width = 800 # 窗口的宽度
window_height = 450 # 窗口的高度
Root.title("神经网络可视化")
11 months ago
Root.geometry("800x450") # 设置窗口的大小和位置
picture_frame(window_width,window_height)
Listinstance = create_instance()
listclass = connect_class(Listinstance)
# 创建网络对象总表和网络连接对象总表
AllModelObj = [Listinstance[0], Listinstance[1], Listinstance[2], Listinstance[3], Listinstance[4], Listinstance[5],
Listinstance[6], Listinstance[7], Listinstance[8], Listinstance[9]]
AllModelConn = [listclass[0], listclass[1], listclass[2], listclass[3], listclass[4], listclass[5], listclass[6],
listclass[7], listclass[8], listclass[9]]
img_path = ["img/data.png", "img/conv.png", "img/pool.png", "img/full_connect.png", "img/nonlinear.png",
"img/classifier.png", "img/error.png", "img/adjust.png", "img/arrow1.png", "img/arrow2.png"]
List_image = []
for path in img_path:
List_image.append(element(path))
create_left_element(AllModelObj, List_image)
button = push_button()
button['button1'].config(command=train_setting)
button['button4'].config(command=load_model)
button['button5'].config(command=restart_new_model)
button['button6'].config(command=setpara_func)
button['button8'].config(command=check_connection)
button['button9'].config(command=close_program)
sys.stdout.write = redirector
Root.mainloop()