前段时间一直在验证损失函数的效果,想法有很多,利用优化模型验证还要一直进行求解,麻烦至极还不能看到具体的效果。
因此,我就决定自己写个方便调参的小计算器,有了它,妈妈再也不用担心的损失函数了。
数据集及源码地址:https://download.csdn.net/download/wz2671/10483324
图形界面源码如下:
# -*- coding: utf-8 -*-
"""
This is a simple two-dimension calculator for calculating the loss of loss_function.
The data's dimensions were first reduced by PCA, it can be shown with a plot by selecting the top two dimensions.
You can adjust the coefficients of the linear model to view the loss of your function.
"""
from tkinter import filedialog
import loss_fun as vl
import numpy as np
from tkinter import *
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import preparation as vp
# ----------------------------------------------------------------------
def drawPic():
"""
获取GUI界面设置的参数,利用该参数绘制图片
"""
drawPic.figure.clf() # 清空图像
X, Y = drawPic.X, drawPic.Y
w1, w2, b = drawPic.w1, drawPic.w2, drawPic.b
drawPic.subplot = drawPic.figure.add_subplot(111)
# ax = drawPic.figure.gca() # 获取当前的axes
if (X is not None) & (Y is not None):
label_true = Y.T[0] == 1
label_false = Y.T[0] == -1
# D = vl.get_dis(X, Y)
# idx = np.abs(D) < 10
# bound = ~(label_false | label_true) & idx
# unlabel = ~(label_true | label_true) & ~idx
unlabel = ~(label_true | label_false)
drawPic.subplot.scatter(X[unlabel, 0], X[unlabel, 1], c='m', marker='x')
# drawPic.subplot.scatter(X[bound, 0], X[bound, 1], c='r', marker='x')
drawPic.subplot.scatter(X[label_true, 0], X[label_true, 1], c='b')
drawPic.subplot.scatter(X[label_false, 0], X[label_false, 1], c='g')
# 根据散点图的尺寸对直线做适配
x_from = np.min(X[:, 0])
x_to = np.max(X[:, 0])
y_from = np.min(X[:, 1])
y_to = np.max(X[:, 1])
if (w1 == 0) & (w2 == 0): # 构成不了一条直线
x = np.zeros(50)
y = np.zeros(50)
elif w2 == 0:
x = np.zeros(50) - b / w1
y = np.linspace(y_from, y_to, 50)
elif w1 == 0:
y = np.zeros(50) - b / w2
x = np.linspace(x_from, x_to, 50)
else:
k = w1 / w2
# 求交点
y_top = max(-(w1 * x_to + b)/w2, -(w1 * x_from + b)/w2)
y_buttom = min(-(w1 * x_to + b)/w2, -(w1 * x_from + b)/w2)
x_left = min(-(w2 * y_from + b)/w1, -(w2 * y_to + b)/w1)
x_right = max(-(w2 * y_from + b)/w1, -(w2 * y_to + b)/w1)
if (k >= 1) | (k < -1):
y = np.linspace(max(y_from, y_buttom), min(y_to, y_top), 50)
x = -(w2 * y + b) / w1
elif (k < 1) & (k >= -1):
x = np.linspace(max(x_from, x_left), min(x_to, x_right), 50)
y = -(w1 * x + b) / w2
drawPic.subplot.plot(x, y, c='r')
real_loss.config(text=str(vl.loss_rls(X, Y, np.array([w1, w2, b]))))
# 显示画布
drawPic.canvas.draw()
def get_w1(val):
drawPic.w1 = float(val)
drawPic()
def get_w2(val):
drawPic.w2 = float(val)
drawPic()
def get_b(val):
drawPic.b = float(val)
drawPic()
def load():
"""导入数据
:return:
"""
try:
data_path = data_path_entry.get()
except:
raise FileNotFoundError('请选择或输入路徑')
try:
label_n = int(labeled_n_entry.get())
except:
label_n = 50
drawPic.X, drawPic.Y = vp.load(data_path, n=label_n)
drawPic()
def get_file():
""" 获取文件路径
:return:
"""
file_path = filedialog.askopenfilenames()
data_path_val.set(file_path[0])
# 初始化图形
def GUI_init_figure():
drawPic.figure = Figure(figsize=(6, 5), dpi=100)
drawPic.canvas = FigureCanvasTkAgg(drawPic.figure, master=root)
drawPic.canvas.draw()
drawPic.canvas.get_tk_widget().grid(row=2, columnspan=4)
drawPic.w1, drawPic.w2, drawPic.b = 0, 0, 0
drawPic.X, drawPic.Y = None, None
if __name__ == '__main__':
root = Tk()
# 在Tk的GUI上放置一个画布,并用.grid()来调整布局
GUI_init_figure()
# drawPic.figure = Figure(figsize=(6, 5), dpi=100)
# drawPic.canvas = FigureCanvasTkAgg(drawPic.figure, master=root)
# drawPic.canvas.draw()
# drawPic.canvas.get_tk_widget().grid(row=2, columnspan=4)
# 放置标签、文本框和按钮等部件,并设置文本框的默认值和按钮的事件函数
data_path_val = StringVar()
data_path_val.set('datasets/g241c.mat')
data_path_entry = Entry(root, textvariable=data_path_val)
data_path_entry.grid(row=0, column=0, sticky=W)
Button(root, text='打开文件', command=get_file).grid(row=0, column=0, columnspan=2)
Label(root, text='无标签样本个数:').grid(row=0, column=1, sticky=E, padx=20)
labeled_n_entry = Entry(root, width=5)
labeled_n_entry.insert(0, '50')
labeled_n_entry.grid(row=0, column=2, sticky=W)
Button(root, text="导入数据", command=load).grid(row=0, column=3)
Label(root, text="参数调节").grid(row=0, column=4, columnspan=3, sticky=S, padx=10)
# 三个调节参数用的控件, 顺带加了标签
w1_scale = Scale(root, cnf={'length': 300}, from_=-1, to=1, resolution=0.01, command=get_w1)
w1_scale.grid(row=2, column=4, sticky=N, pady=50)
Label(root, text='w1', cnf={'fg': 'red'}).grid(row=2, column=4, sticky=N + E, pady=20)
w2_scale = Scale(root, cnf={'length': 300}, from_=-1, to=1, resolution=0.01, command=get_w2)
w2_scale.grid(row=2, column=5, sticky=N, pady=50)
Label(root, text='w2', cnf={'fg': 'red'}).grid(row=2, column=5, sticky=N + E, pady=20)
b_scale = Scale(root, cnf={'length': 300}, from_=-5, to=5, resolution=0.05, command=get_b)
b_scale.grid(row=2, column=6, sticky=N, pady=50, ipadx=10)
Label(root, text='b', cnf={'fg': 'red'}).grid(row=2, column=6, sticky=N, pady=20)
# 显示损失
loss_label = Label(root, text='loss:', cnf={'fg': 'red', 'font': 'bold'})
loss_label.grid(row=2, column=4, columnspan=3, sticky=S + W, pady=50, padx=20)
real_loss = Label(root, text='', cnf={'fg': 'red', 'font': 'bold'})
real_loss.grid(row=2, column=4, columnspan=3, sticky=S + W, pady=50, padx=60)
# 启动事件循环
root.mainloop()
实现的效果图如下: