翼度科技»论坛 编程开发 .net 查看内容

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

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
最近在项目中,为了算法结果的可视化,需要用到混淆矩阵(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轴的标签和刻度说明,数据,颜色设置。如下所示:
  1. public class MatrixM:ObservableObject
  2. {
  3.         private string title;
  4.         public string Title { get { return title; } set { SetProperty(ref title, value); } }
  5.         private string xLabel;
  6.         public string XLabel { get { return xLabel; } set { SetProperty(ref xLabel, value); } }
  7.         private string yLabel;
  8.         public string YLabel { get { return yLabel; } set { SetProperty(ref yLabel,value); } }
  9.         private string[] yaxis;
  10.         public string[] Yaxis { get { return yaxis; } set { SetProperty(ref yaxis, value); } }
  11.         private string[] xaxis;
  12.         public string[] Xaxis { get { return xaxis; } set { SetProperty(ref xaxis, value); } }
  13.         public double[,] Data { get; set; }
  14.         private Color minBrush;
  15.         public Color MinBrush { get { return minBrush; } set { SetProperty(ref minBrush, value); } }
  16.         private Color maxBrush;
  17.         public Color MaxBrush { get { return maxBrush; } set { SetProperty(ref maxBrush, value); } }
  18. }
复制代码
注意:在本示例中,矩阵的数据采用二维数组进行存储。
 
构造数据

 
构造示例数据,在实际开发中,数据来源于算法的真实分析,本例主要用于演示前端开发,所以构造一些测试数据,如下所示:
  1. private MatrixM dataM;
  2. public MatrixM DataM { get { return dataM; } set { SetProperty(ref dataM,value); } }
  3. private UniformGrid matrix;
  4. public MainWindowViewModel()
  5. {
  6.         this.DataM = new MatrixM();
  7.         this.DataM.Title = "Confusion  Matrix on Fer2024";
  8.         this.DataM.XLabel = "Predict Label";
  9.         this.DataM.YLabel = "Truth Label";
  10.         this.DataM.Xaxis = new string[] { "Angry","Disgust","Fear","Happy","Sad","Surprise","Neutral"};
  11.         this.DataM.Yaxis = new string[] { "Angry", "Disgust", "Fear", "Happy", "Sad", "Surprise", "Neutral" };
  12.         this.DataM.MinBrush = Colors.White;
  13.         this.DataM.MaxBrush= Colors.DarkSlateBlue;
  14.         this.DataM.Data = new double[,] {
  15.                 {0.66,0.01,0.09,0.04,0.11,0.01,0.09 },
  16.                 {0.23,0.64,0.0,0.04,0.09,0.0,0.0},
  17.                 {0.08,0.0,0.58,0.02,0.15,0.08,0.1},
  18.                 {0.01,0.0,0.01,0.89,0.01,0.02,0.06 },
  19.                 {0.09,0.0,0.11,0.03,0.6,0.01,0.15},
  20.                 {0.02,0.0,0.05,0.04,0.02,0.85,0.02 },
  21.                 {0.05,0.0,0.04,0.07,0.11,0.01,0.72 }
  22.         };
  23. }
复制代码
 
页面布局

 
在WPF中,为了弹性呈现数据及自动缩放,主要用Grid,UniformGrid进行页面布局,交互主要用Button来实现,都是基础知识。如下所示:
  1. <Grid>
  2.     <Grid.ColumnDefinitions>
  3.         <ColumnDefinition Width="Auto"></ColumnDefinition>
  4.         <ColumnDefinition Width="*"></ColumnDefinition>
  5.         <ColumnDefinition Width="Auto"></ColumnDefinition>
  6.     </Grid.ColumnDefinitions>
  7.     <Grid.RowDefinitions>
  8.         <RowDefinition Height="Auto"></RowDefinition>
  9.         <RowDefinition></RowDefinition>
  10.         <RowDefinition Height="Auto"></RowDefinition>
  11.     </Grid.RowDefinitions>
  12.     <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>
  13.     <TextBlock Text="{Binding DataM.YLabel}" Grid.Row="1" Grid.Column="0" FontWeight="Bold" FontSize="14" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5">
  14.         <TextBlock.LayoutTransform>
  15.             <RotateTransform Angle="270"></RotateTransform>
  16.         </TextBlock.LayoutTransform>
  17.     </TextBlock>
  18.     <Grid Grid.Row="1" Grid.Column="1">
  19.         <Grid.RowDefinitions>
  20.             <RowDefinition Height="*"></RowDefinition>
  21.             <RowDefinition Height="Auto"></RowDefinition>
  22.         </Grid.RowDefinitions>
  23.         <Grid.ColumnDefinitions>
  24.             <ColumnDefinition Width="Auto"></ColumnDefinition>
  25.             <ColumnDefinition Width="*"></ColumnDefinition>
  26.             <ColumnDefinition Width="Auto"></ColumnDefinition>
  27.         </Grid.ColumnDefinitions>
  28.         <ItemsControl Grid.Row="0" Grid.Column="0" Grid.RowSpan="1" ItemsSource="{Binding DataM.Yaxis}">
  29.             <ItemsControl.ItemsPanel>
  30.                 <ItemsPanelTemplate>
  31.                     <UniformGrid Columns="1"></UniformGrid>
  32.                 </ItemsPanelTemplate>
  33.             </ItemsControl.ItemsPanel>
  34.             <ItemsControl.ItemTemplate>
  35.                 <DataTemplate>
  36.                     <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Right">
  37.                         <TextBlock Text="{Binding}"></TextBlock>
  38.                         <Border Width="10" Height="1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Right" Margin="10 0 0 0"></Border>
  39.                     </StackPanel>
  40.                 </DataTemplate>
  41.             </ItemsControl.ItemTemplate>
  42.         </ItemsControl>
  43.         <Border BorderBrush="Black" BorderThickness="1" Grid.Row="0" Grid.Column="1" >
  44.             <UniformGrid x:Name="matrix" >
  45.                 <UniformGrid.Resources>
  46.                     
  47.                 </UniformGrid.Resources>
  48.             </UniformGrid>
  49.         </Border>
  50.         <ItemsControl Grid.Row="1" Grid.Column="1" ItemsSource="{Binding DataM.Xaxis}">
  51.             <ItemsControl.ItemsPanel>
  52.                 <ItemsPanelTemplate>
  53.                     <UniformGrid Rows="1"></UniformGrid>
  54.                 </ItemsPanelTemplate>
  55.             </ItemsControl.ItemsPanel>
  56.             <ItemsControl.ItemTemplate>
  57.                 <DataTemplate>
  58.                     <StackPanel Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Center">
  59.                         <Border Width="10" Height="1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Center" Margin="0 0 0 0">
  60.                             <Border.RenderTransformOrigin>
  61.                                 <Point X="0.5" Y="0.5"></Point>
  62.                             </Border.RenderTransformOrigin>
  63.                             <Border.LayoutTransform>
  64.                                 <TransformGroup>
  65.                                     <RotateTransform Angle="90"></RotateTransform>
  66.                                 </TransformGroup>
  67.                             </Border.LayoutTransform>
  68.                         </Border>
  69.                         <TextBlock Text="{Binding}">
  70.                             <TextBlock.RenderTransformOrigin>
  71.                                 <Point X="0.5" Y="0.5"></Point>
  72.                             </TextBlock.RenderTransformOrigin>
  73.                             <TextBlock.LayoutTransform>
  74.                                 <TransformGroup>
  75.                                     <RotateTransform Angle="-45"></RotateTransform>
  76.                                     <TranslateTransform Y="20"></TranslateTransform>
  77.                                 </TransformGroup>
  78.                             </TextBlock.LayoutTransform>
  79.                         </TextBlock>
  80.                     </StackPanel>
  81.                 </DataTemplate>
  82.             </ItemsControl.ItemTemplate>
  83.         </ItemsControl>
  84.         <Rectangle  Grid.Row="0" Grid.Column="2" Width="20" Margin="10 0">
  85.             <Rectangle.Fill>
  86.                 <LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
  87.                     <GradientStop Offset="0" Color="{Binding DataM.MaxBrush}"></GradientStop>
  88.                     <GradientStop Offset="1" Color="{Binding DataM.MinBrush}"></GradientStop>
  89.                 </LinearGradientBrush>
  90.             </Rectangle.Fill>
  91.         </Rectangle>
  92.     </Grid>
  93.     <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>
  94. </Grid>
复制代码
 
注意:标题,刻度,轴说明 ,都是固定布局,可以进行数据绑定,而矩阵内容需要动态创建,所以分开处理。
 
构造矩阵

 
在本示例中,混淆矩阵以UniformGrid为容器,动态根据数据创建,并填充到容器中,如下所示:
  1. private IRelayCommand<object> loadedCommand;
  2. public IRelayCommand<object> LoadedCommand =>loadedCommand??=new RelayCommand<object>(Loaded);
  3. private void Loaded(object obj)
  4. {
  5.         if (obj != null)
  6.         {
  7.                 var win = obj as MainWindow;
  8.                 if (win != null)
  9.                 {
  10.                         this.matrix = win.matrix;
  11.                         InitMatrix();
  12.                 }
  13.         }
  14. }
  15. private void InitMatrix()
  16. {
  17.         if(this.matrix == null)
  18.         {
  19.                 return;
  20.         }
  21.         this.matrix.Children.Clear();
  22.         this.matrix.Rows = this.DataM.Data.GetLength(0);
  23.         this.matrix.Columns = this.DataM.Data.GetLength(1);
  24.         var color = this.DataM.MaxBrush;
  25.         for(int row = 0; row < this.DataM.Data.GetLength(0); row++)
  26.         {
  27.                 for(int col = 0; col < this.DataM.Data.GetLength(1); col++)
  28.                 {
  29.                         Border border = new Border();
  30.                         border.Background = new SolidColorBrush(Color.FromArgb((byte)(this.DataM.Data[row, col] * color.A), color.R, color.G, color.B));
  31.                         var button = new Button();
  32.                         button.Content = this.DataM.Data[row, col].ToString("0.00");
  33.                         button.FontSize = 12;
  34.                         button.HorizontalContentAlignment= System.Windows.HorizontalAlignment.Center;
  35.                         button.VerticalContentAlignment= System.Windows.VerticalAlignment.Center;
  36.                         button.Background = Brushes.Transparent;
  37.                         button.BorderThickness = new System.Windows.Thickness(0);
  38.                         border.Child= button;
  39.                         this.matrix.Children.Add(border);
  40.                 }
  41.         }
  42. }
复制代码
注意,在Grid,UniformGrid此类容器中,控件不需要设置宽和高,会自动根据容器大小进行自适应。且不能设置对齐属性,否则控件大小则不会自适应调整大小。
 
示例效果

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

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

来源:https://www.cnblogs.com/hsiang/p/18227765
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具