public TrainAndTestPage(NeuralNetRunType runtype, NeuralNet neuralnet, MNISTDataManager mnistdata)
        {
            // Define GUI

            // Page properties
            Title           = string.Format("{0} Net", runtype.ToString().ToUpperFirstOnly());
            BackgroundColor = Color.SteelBlue;
            Padding         = new Thickness(Application.Current.MainPage.Width * 0.05, Application.Current.MainPage.Height * 0.05);

            // Label for description
            Label description = new Label
            {
                Text   = string.Format("Please define the number of data sets from the MNIST {0} data base to be used for {0}ing. Each data set represents one digit. The {0} data base holds about {1:N0} data sets in total.", runtype.ToString(), mnistdata.CountData),
                Margin = new Thickness(0, 0, 0, Application.Current.MainPage.Height * 0.075)
            };

            // Label for number of training / testing sets used
            Label label_useddatasets = new Label
            {
                Text   = String.Format("{0:N0} data set{1} selected", mnistdata.UsedDataSets, mnistdata.UsedDataSets == 0 ? "" : "s"),
                Margin = new Thickness(0, 0, 0, Application.Current.MainPage.Height * 0.075)
            };

            // Slider for number of data sets used for training / testing
            Slider slider_useddatasets = new Slider(1, mnistdata.CountData, mnistdata.UsedDataSets);

            slider_useddatasets.ValueChanged += (s, e) =>
            {
                mnistdata.UsedDataSets  = (int)e.NewValue;
                label_useddatasets.Text = String.Format("{0:N0} data set{1} selected", mnistdata.UsedDataSets, mnistdata.UsedDataSets == 0 ? "" : "s");
            };

            // Progress bar
            ProgressBar progressbar = new ProgressBar {
                Progress = 0
            };

            // Label for showing progress
            Label label_progress = new Label
            {
                Text = "Currently no calculation running",
            };

            // Button to start training / testing
            Button button = new Button
            {
                Text          = string.Format("Start {0}ing", runtype.ToString().ToUpperFirstOnly()),
                WidthRequest  = Application.Current.MainPage.Width * 0.5,
                HeightRequest = Application.Current.MainPage.Height * 0.10
            };

            // Define page
            Content = new ScrollView
            {
                Content = new StackLayout
                {
                    Children =
                    {
                        description,
                        label_useddatasets,
                        slider_useddatasets,
                        button,
                        progressbar,
                        label_progress
                    }
                }
            };

            // Button event
            // Here training and test sessions are executed
            button.Clicked += async(s, e) =>
            {
                // Check if another calculation is currently running
                if (activerun == true)
                {
                    var answer = await DisplayAlert("Warning", "Do you want to stop current calculation?", "Yes", "No");

                    if (answer)
                    {
                        endrun = true;
                    }
                    return;
                }

                // Check if selected data set is big
                if (mnistdata.UsedDataSets > mnistdata.UsedDataSetsWarning)
                {
                    bool answer = await DisplayAlert("Warning", "Please be aware that big data sets effect run time. Continue?", "Yes", "No");

                    if (!answer)
                    {
                        return;
                    }
                }

                // Set activerun and endrun flags
                activerun = true;
                endrun    = false;

                // Disable Back button
                NavigationPage.SetHasBackButton(this, false);

                // Rename Button to Stop
                button.Text = string.Format("Stop {0}ing", runtype.ToString().ToUpperFirstOnly());

                // Define parameters for progress bar calculation (increase bar 100 times or each 20 runs)
                int progresssteps = Math.Max(100, mnistdata.UsedDataSets / 20);
                int progressspan  = (int)Math.Ceiling((double)mnistdata.UsedDataSets / progresssteps);

                // Counter for training / testing runs
                int i = 0;

                // Initialize progress bar
                label_progress.Text = i.ToString() + " / " + mnistdata.UsedDataSets.ToString();
                await progressbar.ProgressTo((double)i / mnistdata.UsedDataSets, 1, Easing.Linear);

                // Train neural net
                if (runtype == NeuralNetRunType.train)
                {
                    while (i < mnistdata.UsedDataSets && endrun == false)
                    {
                        // Counter for runs in progress step
                        int j = 0;

                        // Training loop for one progress step done as task
                        await Task.Run(() =>
                        {
                            while (j < progressspan && i < mnistdata.UsedDataSets)
                            {
                                // Train net with data set i
                                neuralnet.Train(mnistdata.Input(i), mnistdata.Output(i));

                                j++;
                                i++;
                            }

                            // Remember number of training data sets
                            neuralnet.TrainingDataCounter += j;
                        });

                        // Update progress bar
                        label_progress.Text = i.ToString() + " / " + mnistdata.UsedDataSets.ToString();
                        await progressbar.ProgressTo((double)i / mnistdata.UsedDataSets, 1, Easing.Linear);
                    }

                    // Show mesage
                    await DisplayAlert("Result", string.Format("Neural net trained with {0:N0} data sets", i), "OK");
                }

                if (runtype == NeuralNetRunType.test)
                {
                    // Setup scorecard for capturing test results
                    // digittotal counts all trained figures, digitcorrect the ones that are identified correctly
                    Vector <double> digittotal = Vector <double> .Build.Dense(10);

                    Vector <double> digitcorrect = Vector <double> .Build.Dense(10);

                    // Testing loop
                    while (i < mnistdata.UsedDataSets && endrun == false)
                    {
                        // Counter for runs in progress step
                        int j = 0;

                        // Testing loop for one progress step done as task
                        await Task.Run(() =>
                        {
                            while (j < progressspan && i < mnistdata.UsedDataSets)
                            {
                                // Increase counter for testet digit (0..9)
                                int number = mnistdata.Number(i);
                                digittotal[number]++;

                                // Ask net
                                Vector <double> answer = neuralnet.Query(mnistdata.Input(i));

                                // Check if it's correct
                                if (answer.AbsoluteMaximumIndex() == number)
                                {
                                    digitcorrect[number]++;
                                }

                                j++;
                                i++;
                            }

                            // Remember number of training data sets
                            neuralnet.TrainingDataCounter += j;
                        });

                        // Update progress bar
                        label_progress.Text = i.ToString() + " / " + mnistdata.UsedDataSets.ToString();
                        await progressbar.ProgressTo((double)i / mnistdata.UsedDataSets, 1, Easing.Linear);
                    }

                    // Remeber performance result
                    neuralnet.Performance.Add(digitcorrect.Sum() / digittotal.Sum());

                    // Show test results
                    await Navigation.PushAsync(new ResultsMNISTPage(neuralnet, mnistdata, digittotal, digitcorrect));
                }

                // Reset progress bar
                label_progress.Text = "Currently no calculation running";
                await progressbar.ProgressTo(0.0, 250, Easing.Linear);

                // Rename Button to Start
                button.Text = string.Format("Start {0}ing", runtype.ToString().ToUpperFirstOnly());

                // Enable Back button
                NavigationPage.SetHasBackButton(this, true);

                // Cancel activerun flag
                activerun = false;
            };
        }
Beispiel #2
0
        public ResultsDetailsPage(NeuralNet neuralnet, MNISTDataManager mnistdata)
        {
            // Save parameters
            this.neuralnet = neuralnet;
            this.mnistdata = mnistdata;

            // Define GUI

            // Page properties
            Title           = "Details";
            BackgroundColor = Color.SteelBlue;
            Padding         = new Thickness(Application.Current.MainPage.Width * 0.05, Application.Current.MainPage.Height * 0.05);

            // Step 1: Generate initial collection of pictures from MNIST database (buffersize elements)
            pictures = new ObservableCollection <CarouselItem>();
            AddPictures(0);

            // Step 2: Generate data template (just a Image with data binding to CarouselItem class)
            DataTemplate template = new DataTemplate(() =>
            {
                Image image = new Image();
                image.SetBinding(Image.SourceProperty, "Picture");
                return(image);
            });

            // Step 3: Generate carousel view
            var myCarousel = new CarouselViewControl();

            myCarousel.Position          = 0; //default
            myCarousel.ItemsSource       = pictures;
            myCarousel.ItemTemplate      = template;
            myCarousel.InterPageSpacing  = 2;
            myCarousel.Orientation       = CarouselViewOrientation.Horizontal;
            myCarousel.ShowIndicators    = false;
            myCarousel.HorizontalOptions = LayoutOptions.FillAndExpand;
            myCarousel.VerticalOptions   = LayoutOptions.FillAndExpand;

            // Define labels
            labelheadline       = new Label();
            labeldigitcorrect   = new Label();
            labeldigitanswernet = new Label
            {
                HorizontalOptions     = LayoutOptions.FillAndExpand,
                HeightRequest         = Application.Current.MainPage.Height * 0.1,
                VerticalTextAlignment = TextAlignment.Center
            };
            SetLabels(0);

            // Step 4: Build page
            Content = new ScrollView
            {
                Content = new StackLayout
                {
                    Children = { labelheadline, labeldigitcorrect, myCarousel, labeldigitanswernet },
                    Spacing  = Application.Current.MainPage.Height * 0.05
                }
            };

            // Update page when image is swiped
            myCarousel.PositionSelected += (s, e) =>
            {
                // Add new pictures if user has reached end of carousel
                // KNOWN ERROR: When end is reached the wrong picture is displayed (first picture of uploaded data)
                // Warning: stepping through all MINST data may yield to memory problems
                if (myCarousel.Position == pictures.Count - 1)
                {
                    AddPictures(myCarousel.Position + 1);
                }

                // Update label
                SetLabels(myCarousel.Position);
            };
        }
        public ResultsMNISTPage(NeuralNet neuralnet, MNISTDataManager mnistdata, Vector <double> digittotal, Vector <double> digitcorrect)
        {
            // Define GUI

            // Page properties
            Title           = "Results";
            BackgroundColor = Color.SteelBlue;
            Padding         = new Thickness(Application.Current.MainPage.Width * 0.05, Application.Current.MainPage.Height * 0.05);

            // Define styles for labels in grid
            var labelgridStyle = new Style(typeof(Label))
            {
                Setters =
                {
                    new Setter {
                        Property = Label.TextColorProperty, Value = Color.GhostWhite
                    },
                    new Setter {
                        Property = Label.BackgroundColorProperty, Value = Color.SteelBlue
                    },
                    new Setter {
                        Property = Label.HorizontalOptionsProperty, Value = LayoutOptions.FillAndExpand
                    },
                    new Setter {
                        Property = Label.HorizontalTextAlignmentProperty, Value = TextAlignment.Center
                    },
                    new Setter {
                        Property = Label.VerticalOptionsProperty, Value = LayoutOptions.FillAndExpand
                    },
                    new Setter {
                        Property = Label.VerticalTextAlignmentProperty, Value = TextAlignment.Center
                    }
                }
            };

            var labelgridhighlightStyle = new Style(typeof(Label))
            {
                BasedOn = labelgridStyle,
                Setters =
                {
                    new Setter {
                        Property = Label.TextColorProperty, Value = Color.GhostWhite
                    },
                    new Setter {
                        Property = Label.BackgroundColorProperty, Value = Color.DarkOrange
                    },
                    new Setter {
                        Property = Label.FontAttributesProperty, Value = FontAttributes.Bold
                    }
                }
            };

            var labelgridheadlineStyle = new Style(typeof(Label))
            {
                BasedOn = labelgridStyle,
                Setters =
                {
                    new Setter {
                        Property = Label.TextColorProperty, Value = Color.SteelBlue
                    },
                    new Setter {
                        Property = Label.BackgroundColorProperty, Value = Color.GhostWhite
                    },
                    new Setter {
                        Property = Label.FontAttributesProperty, Value = FontAttributes.Bold
                    }
                }
            };

            // Define 11x3 grid for representing results
            Grid grid = new Grid();

            grid.BackgroundColor   = Color.GhostWhite;
            grid.ColumnSpacing     = 1;
            grid.RowSpacing        = 1;
            grid.Padding           = new Thickness(1);
            grid.HorizontalOptions = LayoutOptions.FillAndExpand;
            grid.VerticalOptions   = LayoutOptions.FillAndExpand;

            for (int i = 0; i < 4; i++)
            {
                grid.ColumnDefinitions.Add(new ColumnDefinition {
                    Width = new GridLength(1, GridUnitType.Star)
                });
            }
            for (int i = 0; i < 12; i++)
            {
                grid.RowDefinitions.Add(new RowDefinition {
                    Height = new GridLength(1, GridUnitType.Star)
                });
            }

            // Add headlines to grid
            grid.Children.Add(new Label {
                Text = "Digit", Style = labelgridheadlineStyle
            }, 0, 0);
            grid.Children.Add(new Label {
                Text = "Total", Style = labelgridheadlineStyle
            }, 1, 0);
            grid.Children.Add(new Label {
                Text = "Correct", Style = labelgridheadlineStyle
            }, 2, 0);
            grid.Children.Add(new Label {
                Text = "in %", Style = labelgridheadlineStyle
            }, 3, 0);

            // Add results for each digit to grid
            for (int i = 0; i < 10; i++)
            {
                grid.Children.Add(new Label {
                    Text = i.ToString(), Style = labelgridStyle
                }, 0, i + 1);
                grid.Children.Add(new Label {
                    Text = String.Format("{0:N0}", digittotal[i]), Style = labelgridStyle
                }, 1, i + 1);
                grid.Children.Add(new Label {
                    Text = String.Format("{0:N0}", digitcorrect[i]), Style = labelgridStyle
                }, 2, i + 1);
                grid.Children.Add(new Label {
                    Text = String.Format("{0:P0}", digittotal[i] > 0 ? digitcorrect[i] / digittotal[i] : 0), Style = labelgridStyle
                }, 3, i + 1);
            }

            // Add sum to grid
            grid.Children.Add(new Label {
                Text = "Sum", Style = labelgridhighlightStyle
            }, 0, 11);
            grid.Children.Add(new Label {
                Text = String.Format("{0:N0}", digittotal.Sum()), Style = labelgridhighlightStyle
            }, 1, 11);
            grid.Children.Add(new Label {
                Text = String.Format("{0:N0}", digitcorrect.Sum()), Style = labelgridhighlightStyle
            }, 2, 11);
            grid.Children.Add(new Label {
                Text = String.Format("{0:P0}", digitcorrect.Sum() / digittotal.Sum()), Style = labelgridhighlightStyle
            }, 3, 11);

            // Define button for details
            Button button = new Button
            {
                Text            = "Details",
                WidthRequest    = Application.Current.MainPage.Width * 0.8,
                HeightRequest   = Application.Current.MainPage.Height * 0.10,
                VerticalOptions = LayoutOptions.Center,
            };

            // Show page with detailed results for each digit
            button.Clicked += (s, e) =>
            {
                if (messageflag == false)
                {
                    DisplayAlert("Information", "Look at the details by swiping left and right.", "OK");
                    messageflag = true;
                }

                Navigation.PushAsync(new ResultsDetailsPage(neuralnet, mnistdata));
            };

            // Define page
            Content = new ScrollView
            {
                Content = new StackLayout
                {
                    Children = { grid, button },
                    Spacing  = Application.Current.MainPage.Height * 0.05
                }
            };
        }