Besondere Lernleistung – Reinforcement Learning

Share

In den letzten Monaten habe ich mich mit meiner Abschlussarbeit für die 12. Klasse beschäftigt.
Es geht, wieder mal, um neuronale Netze.

Diemal mit der TU Chemnitz zusammen und dem Thema Reinforcement Learning.
Wer sich dafür interessiert, kann die komplette Dokumentation hier runterladen:

BellDokumentation


NNSpace – The next one

Share

Jetzt ist es wieder mal so weit. Wie jedes Jahr um diese Zeit, endlich … nein es ist noch nicht Weihnachten! Ich habe mich dazu durchgerungen mit einer neuen Version von NNSpace anzufangen. Mein Plan ist es im Moment alle Algorithmen, Ausführungspläne und so weiter als Activities/Workflows mit der WF 4 auszulagern. Das sollte möglichst grafisch passieren,  nur die Grundbausteine sollen noch in C# implementiert werden. Für einen Algorithmus wie z.B. die Backpropagation hat das mehrere Vorteile:

  • Man versteht den Algorithmus! Selbst als Programmierer blickt man bei den Algorithmen im Code kaum durch. Ich habe bei der letzten Version (CTP 2) regelmäßig Stunden damit zugebracht irgendwelche Fehler in den Algorithmen zu suchen .. Mit einer grafischen Übersicht dürfte das etwas einfacher werden. Außerdem kann man so besser erklären was passiert.
  • Der Algorithmus ist sehr dynamisch! Wenn wir die Workflows als XAML abspeichern und laden, kann man das jederzeit ändern. Das kann dann sogar der Benutzer machen, wenn er ein bisschen Durchblick hat.

Also, wie muss man sich das dann vorstellen? Ungefähr so:

Das ist mein erster Entwurf für einen Backpropagation-Workflow. Ihr erinnert euch sicherlich noch an die Backprop, also:

  1. Wir nehmen ein feed-forward Netz (Verbindungen nur in eine Richtung) und führen das aus (Forward Execute)
  2. Wir vergleichen das Ergebnis mit einem vorgegebenen Ziel-Vektor und berechnen den quadratischen Fehler (MSE)
  3. Wir berechnen die Ableitungen des Fehlers nach den Gewichten (die Delta-Werte sind hier zwischengespeicherte Teil-Ableitungen, die wir vorher cachen um Performance zu sparen)
  4. Wir aktualisieren die Gewichte anhand der Ableitungen
  5. Wir fangen wieder von vorne an, bis wir der Meinung sind, dass es gut ist

Dafür brauchen wir soweit erstmal nur folgende Code-Activities:

  • Mean Squared Error (quadratischer Fehler) mit Ableitung
  • Sigmoid für die Aktivierungsfunktionen mit Ableitung
  • For-Activity zum durchlaufen der Units, also z.B. zum Berechnen vom NetInput usw. (scheinbar gibt es gar keine For im .NET Framework, also hab ich fix mal selber eine gebastelt)

Innen drin sieht das dann z.B. so aus (für die Ausführung):

und innerhalb von “Calculate Hidden States” werden zunächst die net-Inputs zusammengezält und dann die Ergebnisse gesammelt durch die sigmoide Aktivierungsfunktion gezogen:

Eigentlich cool oder? Durch die Möglichkeit die Dinger im Designer zusammenzuklappen bleibt das Ganze auch immer schön übersichtlich. Ich bin selber gespannt, wie es jetzt noch weitergeht. Auf jeden Fall könnte es eventuell mit der Performance Probleme geben, wenn ja, müsste ich nochmal umdenken. Es stehen also nach der Logik noch ein paar Tests und dann die Integration in den Rehosted Workflow Designer an.


Visual Studio 2012 Metro Styles für WPF–Metro Window Update

Share

Der letzte Schliff für meine Visual Studio 2012 Metro Styles ist natürlich das MetroWindow, was dann wirklich die ganze Anwendung im typischen Grauton erscheinen lässt. Glücklicherweise gibt es bereits ein Projekt, dass sich um die Implementierung eines solchen MetroWindows gekümmert hat, nämlich das MahApps.Metro Projekt. Den Style von dort können wir ganz einfach an unsere Wünsche anpassen, indem wir folgende Resourcen überschreiben:

<Color x:Key="AccentColor">#2D2D30</Color>
<Color x:Key="WhiteColor">#2D2D30</Color>
<Color x:Key="BlackColor">#FFFFFFFF</Color>

Screen1Screen2

AccentColor setzt den Hintergrund der Titelleiste (mit Schließen, Minimieren … Buttons) und WhiteColor legt den Window-Hintergrund fest. Die beiden sind in unserem Fall gleich. BlackColor ist der Vordergrund für das MetroWindow.

Download

Meine Visual Studio Styles sind jetzt auch Teil des MahApps.Metro Projekts und können also vom GitHub Repository mit runtergeladen werden. Wer also den Sourcecode für das MetroWindow und die VS Styles haben möchte, kann sich das Repository hier auschecken. Die VS Styles liegen dann unter MahApps.Metro/Styles/VS, das Beispielfenster findet man unter MetroDemo (wichtig für alle StarTreck Fans: Käptn Kirk schläft immer noch). Für das MahApps.Metro Projekt hab ich zusätzlich noch eine System.Windows.Interactivity-TriggerAction gebastelt, um die Tabs zu schließen, wenn das jemanden interessiert .. im normalen Download ist die aber nicht dabei (der soll ja nur die Styles zeigen).

Ansonsten hab ich natürlich auch den Artikel und den direkten Download aktualisiert, die MahApps.Metro.dll liegt dann im lib Verzeichnis:

Direkter Download

Codeproject Artikel


Visual Studio 2012 Metro Styles für WPF–Teil 1

Share

Obwohl viele bei dem Wort “Metro” wahrscheinlich an Windows 8 und an das “Kachelwand”-Startmenü denken werden, folgt auch der Visual Studio 2012 Style dem Metro-Prinzip.

Weil sich dieser VS-Metro-Style für komplizierte Anwendungen, die nicht unbedingt dafür gedacht sind auf irgendwelchen Smartphones oder so zu laufen, viel besser eignet, habe ich ein paar Styles für Standard Controls und eine Beispielanwendung dazu gebastelt.

Screenshots

Screen1Screen2

Übersicht

Die Styles sind in mehrere ResourceDictionaries aufgeteilt. Für jedes Control gibt es ein eigenes Dictionary. Die Styles sind jeweils mit einem Schlüssel versehen, sodass man sie explizit referenzieren muss. Das “Styles.xaml” ResourceDictionary fasst alle Styles zusammen und setzt sie als Standard (ohne Key).

Komplettes Styleset verwenden

App.xaml:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/Selen.Wpf.SystemStyles;component/Styles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

 

Nur Teile davon

App.xaml:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary 
                Source="pack://application:,,,/Selen.Wpf.SystemStyles;component/ButtonStyles.xaml"/>
            <ResourceDictionary 
                Source="pack://application:,,,/Selen.Wpf.SystemStyles;component/TextBoxStyles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

 

Bei Verwendung explizit referenzieren:

<Button Content="blastallenemies.cmd" Style="{StaticResource LinkButton}"/>

 

Liste der Styles (Typ und Key)

TargetType Key
Button StandardButton
Button LinkButton
TabControl StandardTabControl
Menu StandardMenu
ListBox StandardListBox
ScrollBar StandardScrollBar
TextBox StandardTextBox
TextBox SearchTextBox

Download

Direkter Download

Codeproject Artikel


Neue Version vom Rehosted Workflow Designer

Share

Die neue Version von meinem dynamischen Rehosted Workflow Designer steht auf codeproject zum Download. Die wichtigsten Neuerungen sind neben einigen Bug Fixes und Refraktorisierungen vor allem UI Verbesserungen.

Select Workflow Type Dialog

Den Dialog zur Typauswahl habe ich komplett überarbeitet. Der Style ist dunkler geworden und die ListBox an der linken Seite hat ein schickes TreeView ersetzt. Damit ist es jetzt möglich die Workflowtypen in Gruppen einzuteilen und so anzuzeigen. IWorkflowType leitet dazu von dem Interface IAppTreeDataProvider ab, welches relevante Daten für das TreeView bereitstellt.

public interface IAppTreeDataProvider
{
     string Name { get; }
     string Path { get; }
     // ..
}

Fehleranzeige

Die Fehleranzeige für ungültiges Xaml habe ich überarbeitet. Neben der Anzeige von Zeilennummern in der TextBox kann sich der Balken zum Anzeigen der Exceptions an längere Texte anpassen und in der Größe variieren.

Download: Hier nochmal der Link zum codeproject Artikel, oder hier der direkte Download von meinem FTP  Server.


Rehosted Workflow Designer auf codeproject

Share

Meine neue Version vom dynamischen Rehosted Workflow Designer auf codeproject

  • XAML View – Das Workflow XAML kann jetzt direkt im Designer bearbeitet werden
  • Error handling – Bei fehlerhaftem XAML in der Datenbank wir nur die XAML View geladen und der Workflow kann korrigiert werden

Dynamischer Rehosted Workflowdesigner für die WF 4 – Teil 3

Share

Rückblick auf Teil 2: Das Storage Module kümmert sich um

  1. Erzeugen eines neuen Workflows
  2. Speichern eines Workflows
  3. Laden eines vorhandenen Workflows
  4. Löschen eines vorhandenen Workflows

abhängig vom ausgewählten Workflowtyp.

In diesem Teil wollen wir uns damit beschäftigen eigene Activities zu bauen, wie das auch der Visual-Studio-Designer macht. Im VS-Designer werden für alle Workflows eigene Typen kompiliert, die dann auch als Black-Boxes in anderen Workflows wiederverwendet werden können bzw. denen Argumente und ein spezielles Aussehen verpasst werden können (wie z.B. bei allen Standardactivities wie Assign, For, Foreach und so weiter). Wir werden dann die Interfaces vom vorigen Teil mit dieser Logik implementieren und damit einen ersten Workflowtyp haben. Dann müssen wir als  letztes noch einen ToolboxService schreiben, der unsere eigenen Activities in die Toolbox lädt. Der fertige Activity-Designer sieht so aus:

(continue reading…)


Dynamischer Rehosted Workflowdesigner für die WF 4 – Teil 2

Share

Rückblick auf das Ziel von Teil 1: Die Vorteile der Prism-Architektur sind:

  • Möglichkeit die Prism-Module in eine bestehende Anwendung einzubauen
  • Möglichkeit nur die benötigten Module zu verwenden
  • Möglichkeit die Module beliebig anzuordnen

Nachdem es also das letzte Mal um die grundsätzliche auf Prism-Modulen basierende Infrastruktur ging, möchte ich nun ein spezielleres Modul vorstellen, das sich um Speicher- und Ladevorgänge kümmert. Natürlich soll man hier dynamisch die Datenquelle ändern können, also z. B. entscheiden können, ob man den Workflow aus einer Datenbank oder aus einer Datei liest. Sinnvoll ist es natürlich auch mehrere solche Speicheroptionen zur Verfügung zu stellen. Ich habe mich dafür entschieden ein Dialogfeld zu implementieren, was die Speicheroptionen anzeigt und aus dem heraus man neue Workflows erstellen oder andere laden bzw. löschen kann. Zu bedenken ist auch, dass beim Erstellen eines neuen Workflows verschiedene Root-Activities verwendet werden können sollen und damit auch die Toolbox abhängig vom “Workflow-Typ” aufgebaut werden muss. Es ergibt sich damit das folgende Interface für  unsere Workflow-Typdefinition:

public interface IWorkflowType
{
    IToolboxCreatorService ToolboxCreatorService { get; }
    IStorageAdapter StorageAdapter { get; }
    string DisplayName { get; }
    string Description { get; }
}

Neben einer Beschreibung  und  einem Namen verweist der Workflowtyp auf zwei andere Interfaces, die Toolboxaufbau und Datenzugriffe kapseln. Das Interface für den Toolboxaufbau ist recht einfach, es liefert einfach eine Liste der Kategorien, die anzuzeigen sind. Im vorigen Artikel hatte ich ja schon das ToolboxModul erwähnt, das sich um das Laden der Toolbox kümmert. Dieses Modul nimmt später einfach wieder den ToolboxCreatorService entgegen.

Das Interface für die Datenzugriffe lässt sich in 2 Bereiche einteilen:

  • Abfrage von Name + Beschreibung aller im Datenspeicher vorhandenen Workflows
  • Abfragen der RootActivity und weiterer typspezifischer Daten

Der Grund für die Trennung ist natürlich die Performance. Es würde ewig dauern für alle Workflows ständig den Activity-Baum zu laden, zumal dieser ja zunächst noch aus XAML erzeugt werden muss. Workflow Description (Name + Beschreibung) und DesignerModel (RootActivity + weitere Daten) lassen sich über einen eindeutigen Schlüssel zuordnen, der abhängig von den Daten im DesignerModel ermittelt werden kann (wird z.B. dann beim Speichern ausgelesen).

public interface IStorageAdapter
{
    IEnumerable<IWorkflowDescription> GetAllWorkflowDescriptions();

    IDesignerModel CreateNewDesignerModel();
    bool CanCreateNewDesignerModel { get; }
    IDesignerModel GetDesignerModel(object key);
    bool SaveDesignerModel(IDesignerModel designerModel);
    bool DeleteDesignerModel(object key);
}

Hier mal ein Screenshot vom dazugehörigen Dialog:

Zusammengehalten und gesteuert wird das Ganze von einem eigenen Modul, was das Menüband oben erweitert. Durch WPF-Commands werden die Aktionen in zwei zentrale ViewModels weitergeleitet, die nach einigen Validierungen wieder die Interfaces aufrufen. Im nächsten Teil geht es dann um eine konkrete Implementierung der Interfaces.

Sourcecode:

Den kompletten (weiterentwickelten) Quellcode gibt es wieder hier.


Dynamischer Rehosted Workflowdesigner für die WF 4 – Teil 1

Share

Frohe Weihnachten! Und hier auch gleich mein kleines Weihnachtsgeschenk:

Ein immer wiederkehrendes Problem mit eigenen Anwendungen basierend auf der Workflow Foundation, ist die eigene Implementierung eines Workflowdesigners. Dafür stellt das .Net Framework einige Klassen zur Verfügung, die auf MSDN kurz erklärt werden.

Eigentlich ist es nutzlos, für jede Anwendung ein neues WPF-Projekt für den Workflow-Designer zu erstellen, weil sich eigentlich kaum etwas ändert. Zusätzlich muss man sich immer noch um eine Lösung für Speichern/Laden (Datenbank, Filesystem …) Gedanken machen, was ja auch immer gleich ist. Sinnvoll wäre es eine dynamische Standardanwendung zu haben, die man auf den jeweiligen Anwendungsfall noch ein bisschen anpassen kann. Als Lösung für diese immer wiederkehrende nervige Sache bietet sich eine modulare Implementierung an. Dabei sollte es möglich sein frei zu entscheiden wie flexibel man sein möchte, also wie viel Logik man aus der Infrastruktur übernimmt.

Also, genug rumgeschwafelt, jetzt kommt meine Implementierung. Ich hab mir gedacht, weil es ein größeres Projekt ist ein paar Artikel dazu zu schreiben. In diesem Artikel soll es zunächst um die grobe Struktur und um die “Core-Module” meiner Implementierung gehen, bevor wir dann später zum einzelnen optionalen Aufgaben kommen. Vorher aber trotzdem mal ein Screenshot:

dynamischer Workflowdesigner

Workflowdesigner

Meine Implementierung basiert auf Prism, obwohl ich eigentlich nur den RegionManager davon verwende. Mein Ziel, was ich damit erreicht habe, war es nicht vorzugeben, dass die Toolbox links ist oder so, sondern eben einfach eine Toolbox da ist, die dann der RegionManager an eine beliebige Stelle platziert. Damit sind die Kernkomponenten von meinem kleinen Framework ganz schlank und schlicht. Es gibt:

  • Ein zentrales ViewModel, das die Klasse WorkflowDesigner zur Verfügung stellt und sich um Dinge wie das Aktualisieren der Designfläche, oder Designerfehler usw. kümmert
  • Zwei zentrale Views (Toolbox, Designfläche und PropertyInspector) mit diesem ViewModel als DataContext
  • Ein weiteres zentrales ViewModel für die Toolbox (dazu später mehr)
  • Eine zentrale View mit diesem ViewModel als DataContext

Die Views beinhalten ledeglich jeweils ein Content-Control, dass an die jeweilige Property von der WorkflowDesigner Instanz bzw. eben an die Toolbox gebunden ist. Damit ist der WorkflowDesigner schön modular und nicht mehr alles in einer Klasse zentriert. Hier mal als Beispiel einen Ausschnitt vom StandardDesignerViewModel (DesignView und PropertyInspector) mit der Initialisierungslogik:

public class StandardDesignerViewModel : INotifyPropertyChanged, IDesignerViewModel
{
    public WorkflowDesigner Designer
    {
        get;
        set;
    }

    public void ReloadDesigner(Activity root)
    {
        this.Designer = new WorkflowDesigner();
        (new DesignerMetadata()).Register();
        this.Designer.Load(root);
    }
}

Die Views sehen alle gleich aus, z. B. so die Design-View:

<UserControl x:Class="RehostedDesigner.Designer.ViewModule.StandardView"
             ...>
    <ContentControl Content="{Binding Designer.View}"/>
</UserControl>

Die einzige größere Herausvorderung war hier das Laden der Bildchen für die Toolbox, dazu vielleicht mal in einem anderen Artikel. Grundsätzlich kann man über ein Interface steuern, welche Elemente gerade in der Toolbox angezeigt werden und mein ViewModel versucht dann die Icons automatisch zu finden (wer möchte schaut sich einfach den Quellcode an).

Zusammensetzen kann man das ganze dann mit einem Prism-Bootstrapper. Der Name klingt gewaltiger als was dahintersteckt: Eine kleine Klasse, die anstatt des MainWindows von der App.xaml aufgerufen wird:

protected override void OnStartup(StartupEventArgs e)
{
    new Bootstrapper().Run();
}

Die müssen wir von UnityBootstrapper ableiten und setzen damit den ganzen Apparat von Prism in Gang. Die Implementierung ist sehr standardmäßig, wenn ich mir meinen Bootstrapper so anschaue kommt es mir fast so vor, als hätte ich ihn irgendwo von der MSDN Hilfe kopiert, ist zwar absolut korrekt, aber absolut nicht hilfreich/aufschlussreich/sinnvoll? … naja ich kopiers trotzdem mal rein:

public class Bootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        MainWindow shell = new MainWindow();
        shell.Show();

        return shell;
    }

    protected override IModuleCatalog CreateModuleCatalog()
    {
        return new ConfigurationModuleCatalog();
    }

    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();
        ((UnityConfigurationSection)ConfigurationManager.GetSection("unity")).Configure(this.Container);
    }
}

Natürlich brauchen wir jetzt noch unser MainWindow, in dem wir die Regions für den RegionManager definieren. Eigentlich ziemlich selbsterklärend (Standardanordung Toolbox links, PropertyInspector rechts):

<Window x:Class="Selen.WorkflowDesigner.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Selen.WorkflowDesigner"
        xmlns:regions="clr-namespace:Microsoft.Practices.Prism.Regions;assembly=Microsoft.Practices.Prism" 
        Title="Workflow Designer" Height="350" Width="525" WindowState="Maximized">
    <DockPanel>
        <Menu DockPanel.Dock="Top" regions:RegionManager.RegionName="StorageRegion"/>
        <StatusBar DockPanel.Dock="Bottom" Height="25">
            <StatusBarItem HorizontalAlignment="Right">
                <Image Source="logo.png" HorizontalAlignment="Right"/>
            </StatusBarItem>
        </StatusBar>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="4*"/>
                <ColumnDefinition Width="2*"/>
            </Grid.ColumnDefinitions>
            <ContentControl Grid.Column="0" Grid.Row="0" 
                            regions:RegionManager.RegionName="ToolboxRegion" Margin="5"/>
            <ContentControl Grid.Column="1" Grid.Row="0" 
                            regions:RegionManager.RegionName="DesignerViewRegion" Margin="5"/>
            <ContentControl Grid.Column="2" Grid.Row="0" 
                            regions:RegionManager.RegionName="DesignerPropertyInspectorViewRegion" Margin="5"/>
            <GridSplitter Grid.Column="0" HorizontalAlignment="Right" .../>
            <GridSplitter Grid.Column="1" HorizontalAlignment="Right" .../>
        </Grid>
        <DockPanel.Background>
            <LinearGradientBrush>
                <GradientStop Color="Black" Offset="0"/>
                <GradientStop Color="Gray" Offset="0.5"/>
                <GradientStop Color="Black" Offset="0.7"/>
                <GradientStop Color="Gray" Offset="1"/>
            </LinearGradientBrush>
        </DockPanel.Background>
    </DockPanel>
</Window>

Das wars dann für den ersten Teil. Als nächstes stehen weitere Module auf dem Plan, die optionale Funktionalität übernehmen können (Speichern u.ä.), inzwischen gibts aber schonmal den gesamten Quellcode des Projekts zum Download: Download hier


WCF Cluster 1.0

Share

Nach einiger Zeit, möchte ich jetzt endlich die erste Version von meinem WCF-Cluster Beispiel vorstellen. Wie man einen einfachen Client bauen kann hatte ich ja schon im vorigen Artikel geschrieben. Ich lade jetzt auch noch einen Command mit hoch, der Pi berechnet um mal ein richtiges Beispiel mit längerer Ausführungsdauer zu haben.

Der ganze Quellcode ist im Download mit drin, deshalb werde ich hier nicht viel reinkopieren. Das Distributor-Gerüst sieht so aus:

public class ComputingPowerDistributor : IComputingPowerDistributor
{
  public void ExecuteCommand(Stream input)
  {
      calculators.ElementAt(calculatorIndex).Value.ProducerExecuteCommand(input);
  }

  public void Connect()
  { 
     calculators[header.ClientAdress] = new ChannelFactory<IPowerProducerClient>(binding, new EndpointAddress(header.ClientAdress)).CreateChannel();
  }

  public void Disconnect()
  {
      calculators.Remove(header.ClientAdress);
  }
}

Die Producer/Calculator können sich an- und  abmelden, jeder Command, der von einem Consumer kommt wird an einen Producer weitergeleitet. Die Adressen und IDs werden im Header von der Nachricht übertragen.

Dann ist die Funktion von Producer/Consumer eigentlich nur noch Fleißarbeit. Einen WCF-Service im Code erstellen und die Methoden vom Distributor aufrufen. Der Producer ist ja immer gleich, deshalb habe ich dafür mal ein UI geschrieben, das im Moment so aussieht:

p1

Der Test-Conumer, der mitkommt sieht so aus:

p2

Der setzt 50 Commands ab, die bei der Pi-Berechnung mitmachen. Diese Commands werden der Reihe nach vom Distributor auf alle Calculator verteilt. Natürlich ist das noch nicht die Endlösung der Lastverteilung, aber zum Testen funktioniert es ganz gut.

Wenn man mit mehreren Computern arbeitet ist es wichtig vorher die Adresse vom Distributor zu ändern (im Moment als localhost), ansonsten sollte alles so funktionieren.

Als erstes muss man den Distributor Host starten, dann die Power Producer und den Consumer, die dll vom Command liegt schon im bin Verzeichnis.

Und hier ist der Link zum Download: Selen.Clustering


Copyright © 1996-2010 Selen - Composite Development Techniques. All rights reserved.
Jarrah theme by Templates Next | Powered by WordPress