首页 > 其他分享 >基于WPF开发动态可交互混淆矩阵

基于WPF开发动态可交互混淆矩阵

时间:2024-06-03 23:33:36浏览次数:24  
标签:DataM 混淆 string 矩阵 private WPF 交互 public

最近在项目中,为了算法结果的可视化,需要用到混淆矩阵(Confusion Matrix),而网上资源大多是基于Python绘制的混淆矩阵,并且是输出图片格式,并不能响应用户点击,今天以一个简单的小例子,简述如何通过WPF绘制混淆矩阵,并可响应用户点击事件,仅供学习分享使用,如有不足之处,还请指正。

 


什么是混淆矩阵?

 

在机器学习中, 混淆矩阵是一个误差矩阵, 常用来可视化地评估监督学习算法的性能. 混淆矩阵大小为 (n_classes, n_classes) 的方阵, 其中 n_classes 表示类的数量. 这个矩阵的每一行表示真实类中的实例, 而每一列表示预测类中的实例 (Tensorflow 和 scikit-learn 采用的实现方式). 也可以是, 每一行表示预测类中的实例, 而每一列表示真实类中的实例 (Confusion matrix From Wikipedia 中的定义). 通过混淆矩阵, 可以很容易看出系统是否会弄混两个类, 这也是混淆矩阵名字的由来.

混淆矩阵是一种特殊类型的列联表(contingency table)或交叉制表(cross tabulation or crosstab). 其有两维 (真实值 "actual" 和 预测值 "predicted" ), 这两维都具有相同的类("classes")的集合. 在列联表中, 每个维度和类的组合是一个变量. 列联表以表的形式, 可视化地表示多个变量的频率分布. 

对于应用程序开发人员而言,混淆矩阵就是一个二维数组,分别表示预测值和真实值,里面的值表示对应值的占比。

 

开发步骤

 

创建WPF应用程序项目

 

在了解了混淆矩阵的用途和原理后,就可以着手去开发,首先创建一个WPF应用程序项目,然后创建模型MatrixM,主要包括标题,x轴,y轴的标签和刻度说明,数据,颜色设置。如下所示:

public class MatrixM:ObservableObject
{
	private string title;
	public string Title { get { return title; } set { SetProperty(ref title, value); } }

	private string xLabel;
	public string XLabel { get { return xLabel; } set { SetProperty(ref xLabel, value); } }

	private string yLabel;
	public string YLabel { get { return yLabel; } set { SetProperty(ref yLabel,value); } }

	private string[] yaxis;
	public string[] Yaxis { get { return yaxis; } set { SetProperty(ref yaxis, value); } }

	private string[] xaxis;
	public string[] Xaxis { get { return xaxis; } set { SetProperty(ref xaxis, value); } }

	public double[,] Data { get; set; }

	private Color minBrush;
	public Color MinBrush { get { return minBrush; } set { SetProperty(ref minBrush, value); } }

	private Color maxBrush;
	public Color MaxBrush { get { return maxBrush; } set { SetProperty(ref maxBrush, value); } }
}

注意:在本示例中,矩阵的数据采用二维数组进行存储。

 

构造数据

 

构造示例数据,在实际开发中,数据来源于算法的真实分析,本例主要用于演示前端开发,所以构造一些测试数据,如下所示:

private MatrixM dataM;
public MatrixM DataM { get { return dataM; } set { SetProperty(ref dataM,value); } }

private UniformGrid matrix;

public MainWindowViewModel()
{
	this.DataM = new MatrixM();
	this.DataM.Title = "Confusion  Matrix on Fer2024";
	this.DataM.XLabel = "Predict Label";
	this.DataM.YLabel = "Truth Label";
	this.DataM.Xaxis = new string[] { "Angry","Disgust","Fear","Happy","Sad","Surprise","Neutral"};
	this.DataM.Yaxis = new string[] { "Angry", "Disgust", "Fear", "Happy", "Sad", "Surprise", "Neutral" };
	this.DataM.MinBrush = Colors.White;
	this.DataM.MaxBrush= Colors.DarkSlateBlue;
	this.DataM.Data = new double[,] {
		{0.66,0.01,0.09,0.04,0.11,0.01,0.09 },
		{0.23,0.64,0.0,0.04,0.09,0.0,0.0},
		{0.08,0.0,0.58,0.02,0.15,0.08,0.1},
		{0.01,0.0,0.01,0.89,0.01,0.02,0.06 },
		{0.09,0.0,0.11,0.03,0.6,0.01,0.15},
		{0.02,0.0,0.05,0.04,0.02,0.85,0.02 },
		{0.05,0.0,0.04,0.07,0.11,0.01,0.72 }
	};
}

 

页面布局

 

在WPF中,为了弹性呈现数据及自动缩放,主要用Grid,UniformGrid进行页面布局,交互主要用Button来实现,都是基础知识。如下所示:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="Auto"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
    </Grid.RowDefinitions>
    <TextBlock Text="{Binding DataM.Title}" FontSize="20" FontWeight="Bold" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"></TextBlock>
    <TextBlock Text="{Binding DataM.YLabel}" Grid.Row="1" Grid.Column="0" FontWeight="Bold" FontSize="14" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5">
        <TextBlock.LayoutTransform>
            <RotateTransform Angle="270"></RotateTransform>
        </TextBlock.LayoutTransform>
    </TextBlock>
    <Grid Grid.Row="1" Grid.Column="1">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <ItemsControl Grid.Row="0" Grid.Column="0" Grid.RowSpan="1" ItemsSource="{Binding DataM.Yaxis}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Columns="1"></UniformGrid>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Right">
                        <TextBlock Text="{Binding}"></TextBlock>
                        <Border Width="10" Height="1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Right" Margin="10 0 0 0"></Border>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <Border BorderBrush="Black" BorderThickness="1" Grid.Row="0" Grid.Column="1" >
            <UniformGrid x:Name="matrix" >
                <UniformGrid.Resources>
                    <Style TargetType="Button">
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Opacity" Value="0.5"></Setter>
                                <Setter Property="FontWeight" Value="Bold"></Setter>
                                <Setter Property="FontSize" Value="16"></Setter>
                                <Setter Property="Cursor" Value="Hand"></Setter>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </UniformGrid.Resources>
            </UniformGrid>
        </Border>
        <ItemsControl Grid.Row="1" Grid.Column="1" ItemsSource="{Binding DataM.Xaxis}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Rows="1"></UniformGrid>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Center">

                        <Border Width="10" Height="1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Center" Margin="0 0 0 0">
                            <Border.RenderTransformOrigin>
                                <Point X="0.5" Y="0.5"></Point>
                            </Border.RenderTransformOrigin>
                            <Border.LayoutTransform>
                                <TransformGroup>
                                    <RotateTransform Angle="90"></RotateTransform>
                                </TransformGroup>
                            </Border.LayoutTransform>
                        </Border>
                        <TextBlock Text="{Binding}">
                            <TextBlock.RenderTransformOrigin>
                                <Point X="0.5" Y="0.5"></Point>
                            </TextBlock.RenderTransformOrigin>
                            <TextBlock.LayoutTransform>
                                <TransformGroup>
                                    <RotateTransform Angle="-45"></RotateTransform>
                                    <TranslateTransform Y="20"></TranslateTransform>
                                </TransformGroup>

                            </TextBlock.LayoutTransform>
                        </TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <Rectangle  Grid.Row="0" Grid.Column="2" Width="20" Margin="10 0">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
                    <GradientStop Offset="0" Color="{Binding DataM.MaxBrush}"></GradientStop>
                    <GradientStop Offset="1" Color="{Binding DataM.MinBrush}"></GradientStop>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
    </Grid>

    <TextBlock Text="{Binding DataM.XLabel}" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" FontWeight="Bold" FontSize="14" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"></TextBlock>

</Grid>

 

注意:标题,刻度,轴说明 ,都是固定布局,可以进行数据绑定,而矩阵内容需要动态创建,所以分开处理。

 

构造矩阵

 

在本示例中,混淆矩阵以UniformGrid为容器,动态根据数据创建,并填充到容器中,如下所示:

private IRelayCommand<object> loadedCommand;

public IRelayCommand<object> LoadedCommand =>loadedCommand??=new RelayCommand<object>(Loaded);

private void Loaded(object obj)
{
	if (obj != null)
	{
		var win = obj as MainWindow;
		if (win != null)
		{
			this.matrix = win.matrix;
			InitMatrix();
		}
	}
}

private void InitMatrix()
{
	if(this.matrix == null)
	{
		return;
	}
	this.matrix.Children.Clear();
	this.matrix.Rows = this.DataM.Data.GetLength(0);
	this.matrix.Columns = this.DataM.Data.GetLength(1);
	var color = this.DataM.MaxBrush;
	for(int row = 0; row < this.DataM.Data.GetLength(0); row++)
	{
		for(int col = 0; col < this.DataM.Data.GetLength(1); col++)
		{
			Border border = new Border();
			border.Background = new SolidColorBrush(Color.FromArgb((byte)(this.DataM.Data[row, col] * color.A), color.R, color.G, color.B));
			var button = new Button();
			button.Content = this.DataM.Data[row, col].ToString("0.00");
			button.FontSize = 12;
			button.HorizontalContentAlignment= System.Windows.HorizontalAlignment.Center;
			button.VerticalContentAlignment= System.Windows.VerticalAlignment.Center;
			button.Background = Brushes.Transparent;
			button.BorderThickness = new System.Windows.Thickness(0);
			border.Child= button;
			this.matrix.Children.Add(border);
		}
	}
}

注意,在Grid,UniformGrid此类容器中,控件不需要设置宽和高,会自动根据容器大小进行自适应。且不能设置对齐属性,否则控件大小则不会自适应调整大小。

 

示例效果

 

运行VS,实例效果如下所示:

以上就是【基于WPF开发动态可交互混淆矩阵】的全部内容。希望可以一起学习,共同进步。

标签:DataM,混淆,string,矩阵,private,WPF,交互,public
From: https://www.cnblogs.com/hsiang/p/18227765

相关文章

  • WPF canvas mousewheel to zoom in or out
    <Windowx:Class="WpfApp133.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft......
  • WPF draw ellipse as array or matrix
    <Windowx:Class="WpfApp133.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft......
  • HTML动态响应2-Servlet+Ajax实现HTTP前后台交互方式
    作者:私语茶馆前言其他涉及到的参考章节:HTML动态响应1—Ajax动态处理服务端响应-CSDN博客Web应用JSON解析—FastJson1.2.83/Tomcat/IDEA解析案例-CSDN博客HTML拆分与共享方式——多HTML组合技术-CSDN博客1.场景:   WEb项目经常需要前后端交互数据,并动态修改HTML页面,......
  • FPGA/ZYNQ:生成3x3矩阵
    一、简述在对图像进行处理时经常用到矩阵操作,包括sobel边缘检测、中值滤波、形态学等。本篇博客介绍一下用两个RAM生成3x3矩阵的方法。二、实现方法1.设计line_shift模块用于对三行数据进行寄存;2.设计一个产生3x3矩阵的模块。三、实现过程1.line_shift_RAM_24bit通过时钟......
  • WPF DataGrid自动增长序号列
    ///<summary>///自动增长序号列///</summary>publicclassDataGridRowIndexColumn:DataGridTextColumn{///<summary>///可以指定开始序号///</summary>publicintStartIndex{get{return(int)GetValue(StartIndex......
  • STM32与陶晶驰串口屏交互
    1、串口屏界面设计1.新建工程保存位置自定义,作为一个合格的嵌入式工程师要有路径下没有中文的情况并命名。选择自己串口屏对应的芯片,一般屏幕背面会有,也可以查看资料。 选择显示方向,自行选择。按照自己的爱好右边可对当前页面重命名。再进行一些基础代码修改。一般......
  • 短视频矩阵系统升级,开发完善功能强大的AI短视频矩阵助手
    一、短视频矩阵的趋势平台整合:未来,短视频平台之间的整合将更加紧密。短视频矩阵将更加注重跨平台的整合营销,使创作者能在一个统一的界面中管理多个短视频平台,从而提高运营效率,并实现更加全面的营销覆盖。数据驱动:数据将成为短视频矩阵的核心驱动力。借助丰富的数据分析工具,短......
  • 第04章—探索CesiumWidget:构建交互式3D地球应用的深度实践
    引言在前两章节中,我们一同探索了Cesium与Vue,React框架结合的基础应用,从环境搭建到如何在组件中无缝嵌入Cesium的三维地球视图,为前端项目注入了地理空间可视化的能力。这一过程不仅加深了我们对MVVM框架的理解,也让Cesium的强大多媒体与空间分析功能得以在现代Web应用中大放......
  • 深度学习--向量,矩阵常见的乘法运算--82
    目录1.向量的数乘2.向量的内积--也叫做点乘3.向量的外积--也叫向量积、叉乘、叉积4.矩阵的数乘5.矩阵的乘法(matmulproduct)6.矩阵的哈达玛积(hadamardproduct):两个相乘的矩阵维度一致,逐元素相乘(也叫矩阵点乘,element-wiseproduct,entrywiseproduct)7卷积1.向量的数......
  • 红薯矩阵自热系统,独家不死号引流玩法!矩阵操作日引流500+
    大家好,今天我要给大家介绍一个很特别的系统,叫做红薯矩阵自热系统。这个名字听起来可能有点奇怪,但其实它是一个很好的工具,可以帮助我们在互联网上吸引更多的人来看我们的内容。这个系统的特别之处在于它有一个独家不死号引流玩法。什么是引流呢?简单来说,引流就是让更多的人......