用python实现损失计算器

前段时间一直在验证损失函数的效果,想法有很多,利用优化模型验证还要一直进行求解,麻烦至极还不能看到具体的效果。

因此,我就决定自己写个方便调参的小计算器,有了它,妈妈再也不用担心的损失函数了。


数据集及源码地址: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()

实现的效果图如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值