Jump to content

Artificial Neural Network UDF


JRowe
 Share

Recommended Posts

I've been tinkering with this on and off for around 9 months and finally figured it out. Here are 100 functions or so that deal with creating, manipulating, training, and ultimately using neural nets.

I'm using the Fann(Fast Artificial Neural Network) library. This is the best open source package I could find, and has many interesting features. I've created the functionality in AutoIt to do everything except the callbacks, c-level convenience functions, and the cascade training system. I'll be adding the cascade system sometime soon.

Neural nets are powerful computational devices that can be used for many things, such as OCR, pathing, targeting, threat detection, function approximation, document sorting, and more.

The dll:

fannfloat.dll

The UDF:

_Fann.au3

[[previous downloads: 14]]

Here's an example. This will create a neural net, train it on some data, and save it to a file called "xor_float.net."

#include "_Fann.au3"

Global $InputsArray[4][2] = [[-1, -1],[-1, 1],[1, -1],[1, 1]]
Global $OutputsArray[4][1] = [[-1],[1],[1],[-1]]
Local $ANNLayers[3] = [2, 3, 1]
_InitializeANN()
$Ann = _CreateAnn(3, $ANNLayers)
_ANNSetActivationFunctionHidden($Ann, $FANN_SIGMOID_SYMMETRIC)
_ANNSetActivationFunctionOutput($Ann, $FANN_SIGMOID_SYMMETRIC)
_ANNTrainOnData($Ann, $InputsArray, $OutputsArray, 5000, 10, 0.001)
_ANNSaveToFile($Ann, "xor_float.net")
_DestroyANN($Ann)
_CloseANN()

Now you have a neural net that is trained to handle the logic of XOR. It takes two inputs and returns one output.

To use the neural net, you'll have to load it, and run some input through it to see what it produces.

#include "_Fann.au3"
Local $myInputs[2] = [1, -1]
_InitializeANN()
$hAnn = _ANNCreateFromFile("xor_float.net")
$calc_out = _ANNRun($hAnn, $myInputs)
MsgBox(0, "XOR", "XOR " & $myInputs[0] & ", " & $myInputs[1] & @CRLF & $calc_out[0])
_DestroyANN($hAnn)
_CloseANN()

The neural net will return an approximation of the XOR value for the pair of inputs you give it. (1 or -1)

If (1,1) or (-1,-1) then it returns something like -.969.

If (-1,1) ir (1,-1) then it will return something like .934

I'll provide a more useful example in the form of a mouse gesture recognition neural net sometime later, but I thought I'd share this now. I hope at least a few people are as excited as I am. This should provide a significant boost to AutoIt's AI firepower.

Documentation is located at: http://leenissen.dk/fann/html/files/fann-h.html

If there are questions, fire away. I'll answer as best I can.

Oh, and before I forget... My everlasting gratitude and thanks to the following, in no particular order:

monoceres, valik, RichardRobertson, trancexx, martin, manadar, and Smoke_N, for the help and teaching they've given me. Thanks, guys (+gal)!

Edited by JRowe
Link to comment
Share on other sites

:) This is totally awesome. I have a hard time accessing the documentation because the DNS server here is having some problems with it, but I've still managed to come up with a cool thing.

This is a number adder, just trying this out. : )

To train the net:

#include <Array.au3>
#include "_Fann.au3"

Local $InputsArray[10][2]
Local $OutputsArray[10][1]

For $i = 0 To 9
    $InputsArray[$i][0] = $i
    $InputsArray[$i][1] = $i * 2
    $OutputsArray[$i][0] = $i * 3
Next

Local $ANNLayers[3] = [2, 3, 1]
_InitializeANN()
$Ann = _CreateAnn(3, $ANNLayers)

Local $Function = $FANN_LINEAR

_ANNSetActivationFunctionHidden($Ann, $Function)
_ANNSetActivationFunctionOutput($Ann, $Function)
_ANNTrainOnData($Ann, $InputsArray, $OutputsArray, 50000, 1000, 0)
_ANNSaveToFile($Ann, "number_add.net")
_DestroyANN($Ann)
_CloseANN()

And getting the results:

#include "_Fann.au3"
Local $myInputs[2] = [4, 5]
_InitializeANN()
$hAnn = _ANNCreateFromFile("number_add.net")
$calc_out = _ANNRun($hAnn, $myInputs)
MsgBox(0, "Add", $myInputs[0] & " + " & $myInputs[1] & " = " & $calc_out[0])
_DestroyANN($hAnn)
_CloseANN()

Can't wait to do more with this! Really excited about your mouse gestures script, I can't believe it if you get that working. :)

Edited by Manadar
Link to comment
Share on other sites

Almost done, working on the patterns training. I got the mouse input vectorization working nicely, just a few fiddly bits left.

Link to comment
Share on other sites

Same as default. Right now I'm focused more on getting a demo than perfecting it. And as such, here we be:

First, the training file: save this as "mousepatterns.data"

4 24 4
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
1 0 0 0
-1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0
0 1 0 0
0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1
0 0 1 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 0 0 1

24 inputs (mouse vectors), 4 outputs(right, left, down, up patterns)

#include "_Fann.au3"
Local $ANNLayers[3] = [24, 4]
_InitializeANN()
$Ann = _CreateAnn(2, $ANNLayers)
_ANNSetActivationFunctionHidden($Ann, $FANN_SIGMOID_SYMMETRIC)
_ANNSetActivationFunctionOutput($Ann, $FANN_SIGMOID_SYMMETRIC)
_ANNTrainOnFile($Ann, "mousepatterns.data", 5000, 10, 0.01957)
_ANNSaveToFile($Ann, "mousepatterns.net")
_DestroyANN($Ann)
_CloseANN()

This trains and generates the neural network, then saves it to "mousepatterns.net"

Now we run it:

;Get array of recorded mouse path

#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <Array.au3>
#include "_Fann.au3"
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>



Global Const $WM_MOUSEWHEEL = 0x020A ;wheel up/down
Global Const $WM_LBUTTONDOWN = 0x0201
;Global Const $WM_LBUTTONUP = 0x0202
Global Const $WM_RBUTTONDOWN = 0x0204
Global Const $WM_RBUTTONUP = 0x0205
Global Const $WM_MBUTTONDOWN = 0x0207
Global Const $WM_MBUTTONUP = 0x0208
Global Const $MSLLHOOKSTRUCT = $tagPOINT & ";dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo"
Global $currentEvent[2]
Global $iLBUTTONDOWN, $iRBUTTONDOWN, $iMBUTTONDOWN, $LRClickStatus, $RLClickStatus, $LRDrag, $RLDrag, $LMDrag, $RMDrag, $doubleClickTime = 400
Global $mousePathX[1000], $mousePathY[1000], $mousePath[1000][2]

$Form1 = GUICreate("Form1", 633, 447, 192, 124)
$Label1 = GUICtrlCreateLabel("What the neural net is thinking:", 144, 48, 316, 41)
GUISetState(@SW_SHOW)

_InitializeANN()
$hAnn = _ANNCreateFromFile("mousepatterns.net")

;Register callback
$hKey_Proc = DllCallbackRegister("_Mouse_Proc", "int", "int;ptr;ptr")
$hM_Module = DllCall("kernel32.dll", "hwnd", "GetModuleHandle", "ptr", 0)
$hM_Hook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", $WH_MOUSE_LL, "ptr", DllCallbackGetPtr($hKey_Proc), "hwnd", $hM_Module[0], "dword", 0)

#EndRegion ### END Koda GUI section ###
Global $sizeOfMousePath = 0
$i = 0

While 1
    Sleep(20)
    $nMsg = GUIGetMsg()
    Select
        Case $nMsg = $GUI_EVENT_CLOSE
            Exit
        Case $currentEvent[0] = "LDrag"

            While $currentEvent[0] = "LDrag"
                $pos = MouseGetPos()
                $mousePathX[$i] = $pos[0]
                $mousePathY[$i] = $pos[1]
                $i += 1
                Sleep(20)
                $sizeOfMousePath = $i
            WEnd

        Case $currentEvent[0] = "MClick"
            _ArrayDisplay($mousePath)

            Exit

        Case $currentEvent[0] = "LDrop"
            Local $mousePath[$sizeOfMousePath][2]

            ;Generate points array
            For $i = 1 To UBound($mousePath) Step 1
                $mousePath[$i - 1][0] = $mousePathX[$i - 1]
                $mousePath[$i - 1][1] = $mousePathY[$i - 1]
            Next
            $i = 0
            $currentEvent[0] = ""
            Do
                $shortest = 1000
                $pointIndex = 0
                For $j = 2 To UBound($mousePath)
                    $length = Sqrt(($mousePath[$j - 1][0] - $mousePath[$j - 2][0]) ^ 2 + _
                            ($mousePath[$j - 1][1] - $mousePath[$j - 2][1]) ^ 2)
                    If $length < $shortest Then
                        $pointIndex = $j - 2
                        $shortest = $length
                    EndIf
                Next
                $NewPointX = Round(($mousePath[$pointIndex][0] + $mousePath[$pointIndex + 1][0]) / 2)
                $NewPointY = Round(($mousePath[$pointIndex][1] + $mousePath[$pointIndex + 1][1]) / 2)

                _ArrayDelete($mousePath, $pointIndex)
                $mousePath[$pointIndex][0] = $NewPointX
                $mousePath[$pointIndex][1] = $NewPointY

                $numPoints = UBound($mousePath)
                ;fill in mousePath array with 13 points, for 12 vectors.
            Until $numPoints <= 13

            $annInput = _VectorizeMousePath($mousePath)
            $calc_out = _ANNRun($hAnn, $annInput)
            $indexOfResult = _ArrayMaxIndex($calc_out)
                Select
                    Case $indexOfResult = 0
                        GUICtrlSetData($Label1, "The Neural net thinks your mouse went Right")
                    Case $indexOfResult = 1
                        GUICtrlSetData($Label1, "The Neural net thinks your mouse went Left")
                    Case $indexOfResult = 2
                        GUICtrlSetData($Label1, "The Neural net thinks your mouse went Down")
                    Case $indexOfResult = 3
                        GUICtrlSetData($Label1, "The Neural net thinks your mouse went Up")
                EndSelect


            $mousePath = ""
            $NewPointX = ""
            $NewPointY = ""
        EndSelect

WEnd


Func _VectorizeMousePath($aArray)
    Local $aVector = ""
    Local $aVector[1]
    Local $vectorX, $vectorY
    $iTolerance = 15
    For $i = 1 to 12 Step 1
        If $aArray[$i-1][0] > $aArray[$i][0] Then $vectorX = -1
        If $aArray[$i-1][0] < $aArray[$i][0] Then $vectorX = 1
        If $aArray[$i-1][0] = $aArray[$i][0] Then $vectorX = 0
        If Abs($aArray[$i-1][0]-$aArray[$i][0]) < $iTolerance Then $vectorX = 0
            _ArrayAdd($aVector, $vectorX)

        If $aArray[$i-1][1] > $aArray[$i][1] Then $vectorY = 1
        If $aArray[$i-1][1] < $aArray[$i][1] Then $vectorY = -1
        If $aArray[$i-1][1] = $aArray[$i][1] Then $vectorY = 0
        If Abs($aArray[$i-1][1]-$aArray[$i][1]) < $iTolerance Then $vectorY = 0
            _ArrayAdd($aVector, $vectorY)
        Next
        _ArrayDelete($aVector, 0)
            $i = 0
            ;For $i = 1 to UBound($aVector) Step 1
                ;ConsoleWrite($aVector[$i-1])
                ;If $i <  UBound($aVector) Then ConsoleWrite(", ")
            ;Next
            ;ConsoleWrite(@CRLF)
    Return $aVector
    EndFunc


Func _Mouse_Proc($nCode, $wParam, $lParam)
    Local $info, $mouseData, $time, $timeDiff
    If $nCode < 0 Then
        $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
                "int", $nCode, "ptr", $wParam, "ptr", $lParam)
        Return $ret[0]
    EndIf

    $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam)
    $mouseData = DllStructGetData($info, 3)
    $time = DllStructGetData($info, 5)
    $timeDiff = $time - $currentEvent[1]

    Select
        Case $wParam = $WM_MOUSEMOVE
            ;Test for Drag in here
            If $currentEvent[0] <> "LDrag" Or $currentEvent[0] <> "LRDrag" Or $currentEvent[0] <> "LMDrag" Then
                If $iLBUTTONDOWN = 1 Then
                    $currentEvent[0] = "LDrag"
                    If $iRBUTTONDOWN = 1 Then
                        $currentEvent[0] = "LRDrag"
                        $LRDrag = 2
                    EndIf
                EndIf
            EndIf
            If $currentEvent[0] <> "RDrag" Or $currentEvent[0] <> "RMDrag" Or $currentEvent[0] <> "LRDrag" Then
                If $iRBUTTONDOWN = 1 Then
                    $currentEvent[0] = "RDrag"
                EndIf
            EndIf

            If $currentEvent[0] <> "MDrag" Then
                If $iMBUTTONDOWN = 1 Then
                    $currentEvent[0] = "MDrag"
                    $currentEvent[1] = $time
                EndIf
            EndIf

            If $iRBUTTONDOWN = 1 And $iMBUTTONDOWN = 1 And $currentEvent[0] <> "RMDrag" Then
                $RMDrag = 2
                $currentEvent[0] = "RMDrag"
                $currentEvent[1] = $time
            EndIf

            If $iLBUTTONDOWN = 1 And $iMBUTTONDOWN = 1 And $currentEvent[0] <> "LMDrag" Then
                $LMDrag = 2
                $currentEvent[0] = "LMDrag"
                $currentEvent[1] = $time
            EndIf

        Case $wParam = $WM_MOUSEWHEEL
            If _WinAPI_HiWord($mouseData) > 0 Then
                ;Wheel Up
                $currentEvent[0] = "WheelUp"
                $currentEvent[1] = $time
            Else
                ;Wheel Down
                $currentEvent[0] = "WheelDown"
                $currentEvent[1] = $time
            EndIf

        Case $wParam = $WM_LBUTTONDOWN
            ;Register Button Down, check for Right/Left
            If $currentEvent[0] = "RClick" Then
                $LRClickStatus = 1
            EndIf

            $iLBUTTONDOWN = 1


        Case $wParam = $WM_LBUTTONUP
            ;Update $iLBUTTONDOWN
            $iLBUTTONDOWN = 0
            ;Test for Right/Left Click
            If $RLClickStatus = 1 And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "RLClick"
                $currentEvent[1] = $time
            EndIf
            If $currentEvent[0] = "LClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "LDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "LDrag" Then
                $currentEvent[0] = "LDrop"
                $currentEvent[1] = $time
            EndIf

            If $LRDrag = 2 And $iRBUTTONDOWN = 1 Then
                $LRDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LRDrag = 1 And $iRBUTTONDOWN = 0 Then
                $currentEvent[0] = "LRDrop"
                $currentEvent[1] = $time
                $LRDrag = 0
            EndIf



            If $LMDrag = 2 And $iMBUTTONDOWN = 1 Then
                $LMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $LMDrag = 1 And $iMBUTTONDOWN = 0 Then
                $currentEvent[0] = "LMDrop"
                $currentEvent[1] = $time
                $LMDrag = 0
            EndIf

            ;Set LClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "LClick"
                $currentEvent[1] = $time
            EndIf

            ;Negate $LRClickStatus
            $RLClickStatus = 0



        Case $wParam = $WM_RBUTTONDOWN
            ;Register Button Down
            If $currentEvent[0] = "LClick" Then
                $RLClickStatus = 1
            EndIf
            $iRBUTTONDOWN = 1

        Case $wParam = $WM_RBUTTONUP
            ;Test for Left, Right, and Right Doubleclick here
            ;Update $iRBUTTONDOWN
            $iRBUTTONDOWN = 0
            ;Test for Right/Left Click
            If $LRClickStatus = 1 And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "LRClick"
                $currentEvent[1] = $time
            EndIf
            If $currentEvent[0] = "RClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "RDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "RDrag" Then
                $currentEvent[0] = "RDrop"
                $currentEvent[1] = $time
            EndIf

            If $LRDrag = 2 And $iLBUTTONDOWN = 1 Then
                $LRDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LRDrag = 1 And $iLBUTTONDOWN = 0 Then
                $currentEvent[0] = "LRDrop"
                $currentEvent[1] = $time
                $LRDrag = 0
            EndIf



            If $RMDrag = 2 And $iMBUTTONDOWN = 1 Then
                $RMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $RMDrag = 1 And $iMBUTTONDOWN = 0 Then
                $currentEvent[0] = "RMDrop"
                $currentEvent[1] = $time
                $RMDrag = 0
            EndIf

            ;Set LClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "RClick"
                $currentEvent[1] = $time
            EndIf

            ;Negate $LRClickStatus
            $LRClickStatus = 0


        Case $wParam = $WM_MBUTTONDOWN
            ;Register Button Down
            $iMBUTTONDOWN = 1

        Case $wParam = $WM_MBUTTONUP
            ;Test for Middle Double Click here
            ;Update $iRBUTTONDOWN
            $iMBUTTONDOWN = 0
            ;Test for Right/Left Click
            If $currentEvent[0] = "MClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "MDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "MDrag" Then
                $currentEvent[0] = "MDrop"
                $currentEvent[1] = $time
            EndIf

            If $LMDrag = 2 And $iLBUTTONDOWN = 1 Then
                $LMDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LMDrag = 1 And $iLBUTTONDOWN = 0 Then
                $currentEvent[0] = "LMDrop"
                $currentEvent[1] = $time
                $LMDrag = 0
            EndIf



            If $RMDrag = 2 And $iRBUTTONDOWN = 1 Then
                $RMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $RMDrag = 1 And $iRBUTTONDOWN = 0 Then
                $currentEvent[0] = "RMDrop"
                $currentEvent[1] = $time
                $RMDrag = 0
            EndIf

            ;Set MClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "MClick"
                $currentEvent[1] = $time
            EndIf

    EndSelect

    $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
            "int", $nCode, "ptr", $wParam, "ptr", $lParam)
    Return $ret[0]
EndFunc   ;==>_Mouse_Proc

Func OnAutoItExit()
    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hM_Hook[0])
    $hM_Hook[0] = 0
    DllCallbackFree($hKey_Proc)
    $hKey_Proc = 0
EndFunc   ;==>OnAutoItExit

This detects 4 patterns: Right, Left, Up, and Down. Click on the GUI and drag and it will give you it's best estimation of what you just did. It can even estimate in situations where it's not going to be clear what just happened. For example, it will tell you "Up" if the movement was mostly up, or "Right" if mostly right, even if there's a lot of other noise.

I hid the funky inner workings, and I'll explain those in a future post. This is just a proof of concept. :)

Edited by JRowe
Link to comment
Share on other sites

**Alert** _AnnRun() is broken. Here's the fix, I'm updating the download.

Replace _ANNRun() in _Fann.au3 with this:

Func _ANNRun($hAnn, ByRef $arrayOfInput)
    $numInputs = UBound($arrayOfInput)
    $inputStruct = DllStructCreate("float[" & $numInputs & "]")
    For $i = 1 To UBound($arrayOfInput) Step 1
        DllStructSetData($inputStruct, 1, $arrayOfInput[$i - 1], $i)
    Next

    $ANNRun = DllCall($hFannDll, "ptr", "_fann_run@8", "ptr", $hAnn, "ptr", DllStructGetPtr($inputStruct))

    $numOutput = DllCall($hFannDll, "int", "_fann_get_num_output@4", "ptr", $hAnn)
    $outputArrayStruct = DllStructCreate("float[" & $numOutput[0] & "]", $ANNRun[0])

    Local $outputArray[$numOutput[0]]

    For $i = 1 To $numOutput[0] Step 1
        $outputArray[$i - 1] = DllStructGetData($outputArrayStruct, 1, $i)
    Next
    Return $outputArray
EndFunc   ;==>_ANNRun
Link to comment
Share on other sites

Here's a GUI-less version that uses messageboxes to announce what the neural net detected.

Really rough, I only used the advanced mouse events monitor because it was simple. There's some overlap as the message boxes fire and multiple events can be detected when there's only actually one. I'll tweak it a bit.

;Get array of recorded mouse path
#include <Misc.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <Array.au3>
#include "_Fann.au3"


Global $mousePathX[800], $mousePathY[800]

$Form1 = GUICreate("Form1", 633, 447, 192, 124)
$Label1 = GUICtrlCreateLabel("What the neural net is thinking:", 144, 48, 316, 41)
GUISetState(@SW_SHOW)

_InitializeANN()
$hAnn = _ANNCreateFromFile("mousepatterns.net")

#EndRegion ### END Koda GUI section ###
Global $sizeOfMousePath = 0
$newInput = 0
$i = 0
While 1

    While _IsPressed(11)
        $pos = MouseGetPos()
        $mousePathX[$i] = $pos[0]
        $mousePathY[$i] = $pos[1]
        $i += 1
        $sizeOfMousePath = $i
        $newInput = 1
        Sleep(20)
    WEnd

    $nMsg = GUIGetMsg()
    Select
        Case $nMsg = $GUI_EVENT_CLOSE
            _DestroyANN($hAnn)
            _CloseANN()
            Exit
        Case $newInput = 1
            Local $mousePath[$sizeOfMousePath][2]
            ;Generate points array
            For $i = 0 To UBound($mousePath) - 1 Step 1
                $mousePath[$i][0] = $mousePathX[$i]
                $mousePath[$i][1] = $mousePathY[$i]
            Next


            $pathData = _VectorizeMousePath($mousePath)
            $calc_out = _ANNRun($hAnn, $pathData)
            $indexOfResult = _ArrayMaxIndex($calc_out)

            Select
                Case $indexOfResult = 0
                    GUICtrlSetData($Label1, "The Neural net thinks your mouse went Up")

                Case $indexOfResult = 1
                    GUICtrlSetData($Label1, "The Neural net thinks your mouse went Down")

                Case $indexOfResult = 2
                    GUICtrlSetData($Label1, "The Neural net thinks your mouse went Left")

                Case $indexOfResult = 3
                    GUICtrlSetData($Label1, "The Neural net thinks your mouse went Right")

            EndSelect
            $newInput = 0
            $i = 0
    EndSelect
    Sleep(50)
WEnd

Func _VectorizeMousePath($aMousePath)
    Do
        $shortest = 1000
        $pointIndex = 0
        For $j = 2 To UBound($aMousePath)
            $length = Sqrt(($aMousePath[$j - 1][0] - $aMousePath[$j - 2][0]) ^ 2 + _
                    ($aMousePath[$j - 1][1] - $aMousePath[$j - 2][1]) ^ 2)
            If $length < $shortest Then
                $pointIndex = $j - 2
                $shortest = $length
            EndIf
        Next
        $NewPointX = Round(($aMousePath[$pointIndex][0] + $aMousePath[$pointIndex + 1][0]) / 2)
        $NewPointY = Round(($aMousePath[$pointIndex][1] + $aMousePath[$pointIndex + 1][1]) / 2)

        _ArrayDelete($aMousePath, $pointIndex)
        $aMousePath[$pointIndex][0] = $NewPointX
        $aMousePath[$pointIndex][1] = $NewPointY

        $numPoints = UBound($aMousePath)
    Until $numPoints <= 13

    Local $aVector[12], $vectorX, $vectorY
    Local $iTolerance = 15
    If UBound($aMousePath) = 13 Then
        For $i = 1 To 12 Step 1
            If $aMousePath[$i - 1][0] > $aMousePath[$i][0] Then $vectorX = -1
            If $aMousePath[$i - 1][0] < $aMousePath[$i][0] Then $vectorX = 1
            If $aMousePath[$i - 1][0] = $aMousePath[$i][0] Then $vectorX = 0
            If Abs($aMousePath[$i - 1][0] - $aMousePath[$i][0]) < $iTolerance Then $vectorX = 0
            _ArrayAdd($aVector, $vectorX)

            If $aMousePath[$i - 1][1] > $aMousePath[$i][1] Then $vectorY = 1
            If $aMousePath[$i - 1][1] < $aMousePath[$i][1] Then $vectorY = -1
            If $aMousePath[$i - 1][1] = $aMousePath[$i][1] Then $vectorY = 0
            If Abs($aMousePath[$i - 1][1] - $aMousePath[$i][1]) < $iTolerance Then $vectorY = 0
            _ArrayAdd($aVector, $vectorY)
        Next
    EndIf
    _ArrayDelete($aVector, 0)
    Return $aVector

EndFunc   ;==>_VectorizeMousePath

Edited:

Much cleaner, saner demo. More of the inner workings are easier to follow, no potential for wonky behavior.

Press control key and make the mouse gesture, release control to activate.

Edited by JRowe
Link to comment
Share on other sites

Neural nets can be used for Forex. People do it all the time. They also build poker bots, day trader bots, and other things using neural networks as a decision engine. This UDF is probably quite capable of producing such decision engines. I know of several projects that make heavy use of the Fann library, and they are quite successful.

I, however, am not quite there yet. :)

Manadar, anyone else who wants 'em: here's some additional patterns:

;Up + Right
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 0 0 0 0 0 0
;Right + Down
1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1
0 0 0 0 0 1 0 0 0 0 0
;Up, Left, Down, Right
0 1 0 1 0 1 -1 0 -1 0 -1 0 0 -1 0 -1 0 -1 1 0 1 0 1 0
0 0 0 0 0 0 1 0 0 0 0
;Down, Left, Up, Right
0 -1 0 -1 0 -1 -1 0 -1 0 -1 0 0 1 0 1 0 1 1 0 1 0 1 0
0 0 0 0 0 0 0 1 0 0 0
;Right, Down+Left
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 -1 -1 -1 -1 -1 -1 -1 -1
0 0 0 0 0 0 0 0 1 0 0
;Left, Down+Right
0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 -1 1 -1 1 -1 1 -1 1
0 0 0 0 0 0 0 0 0 1 0
;Left, Down+Right, Left
0 1 0 1 0 1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 0 1 0 1 0 1
0 0 0 0 0 0 0 0 0 0 1

Format to taste in mousepatterns.data, remember that comments aren't allowed in the training data.

I have 11 patterns being trained, haven't figured out how to get the network properly trained (more reading for me til I figure this out.)

I think it requires a certain level of experience to get these things right, and that over time you develop a feeling for how to put networks together.

@trancexx, no worries, within a day or so I'll get some cool stuff up here. Right now I'm still exploring and learning, shouldn't be too much longer.

Edited by JRowe
Link to comment
Share on other sites

Looks very promise although I am still having hard time to run the example in post #9.

I am getting this error while testing the example above:

FANN Error 3: Wrong version of configuration file, aborting read of configuration file "mousepatterns.net".

Whats wrong with the data? And where I can find information about the acceptable format?

Thanks For sharing it.

Be Green Now or Never (BGNN)!

Link to comment
Share on other sites

The training data file has to be formatted like this:

The first line has to be:

Number of Sets, followed by the number of inputs in each set, followed by the number of outputs in each set, each separated by a space.

If there were 10 sets, with 5 inputs and 2 outputs, then the first line would look like this:

10 5 2

If there were 4 sets, with 20 inputs and 47 outputs, it would look like this:

4 20 47

Each "set" is 2 separate lines. One line of inputs and one line of expected outputs. The mouse patterns I had above need to be added and formatted depending on how many patterns you have. You cannot have comments in the data, either.

This is a single set of 24 inputs and 11 outputs.

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 0 0 0 0 0 0

My whole training file has 11 sets of data, 24 inputs, and 11 outputs. It looks like this:

11 24 11
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
1 0 0 0 0 0 0 0 0 0 0
-1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0
0 1 0 0 0 0 0 0 0 0 0
0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1
0 0 1 0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 0 0 1 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 0 0 0 0 0 0
1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1
0 0 0 0 0 1 0 0 0 0 0
0 1 0 1 0 1 -1 0 -1 0 -1 0 0 -1 0 -1 0 -1 1 0 1 0 1 0
0 0 0 0 0 0 1 0 0 0 0
0 -1 0 -1 0 -1 -1 0 -1 0 -1 0 0 1 0 1 0 1 1 0 1 0 1 0
0 0 0 0 0 0 0 1 0 0 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 -1 -1 -1 -1 -1 -1 -1 -1
0 0 0 0 0 0 0 0 1 0 0
0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 -1 1 -1 1 -1 1 -1 1
0 0 0 0 0 0 0 0 0 1 0
0 1 0 1 0 1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 0 1 0 1 0 1
0 0 0 0 0 0 0 0 0 0 1

You can also create arrays of training data. I'll do a how-to at some point, but for now it's easiest to use formatted files.

Link to comment
Share on other sites

To train a network using arrays of data, you can use the function

_ANNTrainOnData($hAnn, $aInputs, $aOutputs, $iMaxEpochs, $iEpochsBetweenReports, $fDesiredError)

$hAnn is the handle to your neural network. $aInputs is an array of values, which can be int or float. $aOutputs is an array of desired outputs, which can be int or float. $iMaxEpochs is the maximum number of times the neural net will train on the data. $iEpochsBetweenReports is the number of epochs, or individual training runs, that pass until a report is sent to stdout, which will show on the console in Scite. $fDesiredError is a float that represents the % error you want to target before your network stops training.

The network will stop training either when it reaches the max number of epochs or when the error drops below $fDesiredError.

You can train the network similarly, a single time, by using this function:

_ANNTrain($hAnn, $aInput, $aOutput)
Link to comment
Share on other sites

The training data file has to be formatted like this:

The first line has to be:

Number of Sets, followed by the number of inputs in each set, followed by the number of outputs in each set, each separated by a space.

If there were 10 sets, with 5 inputs and 2 outputs, then the first line would look like this:

10 5 2

If there were 4 sets, with 20 inputs and 47 outputs, it would look like this:

4 20 47

Each "set" is 2 separate lines. One line of inputs and one line of expected outputs. The mouse patterns I had above need to be added and formatted depending on how many patterns you have. You cannot have comments in the data, either.

This is a single set of 24 inputs and 11 outputs.

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 0 0 0 0 0 0

My whole training file has 11 sets of data, 24 inputs, and 11 outputs. It looks like this:

11 24 11
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
1 0 0 0 0 0 0 0 0 0 0
-1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0
0 1 0 0 0 0 0 0 0 0 0
0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1
0 0 1 0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 0 0 1 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 0 0 0 0 0 0
1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1
0 0 0 0 0 1 0 0 0 0 0
0 1 0 1 0 1 -1 0 -1 0 -1 0 0 -1 0 -1 0 -1 1 0 1 0 1 0
0 0 0 0 0 0 1 0 0 0 0
0 -1 0 -1 0 -1 -1 0 -1 0 -1 0 0 1 0 1 0 1 1 0 1 0 1 0
0 0 0 0 0 0 0 1 0 0 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 -1 -1 -1 -1 -1 -1 -1 -1
0 0 0 0 0 0 0 0 1 0 0
0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 -1 1 -1 1 -1 1 -1 1
0 0 0 0 0 0 0 0 0 1 0
0 1 0 1 0 1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 0 1 0 1 0 1
0 0 0 0 0 0 0 0 0 0 1

You can also create arrays of training data. I'll do a how-to at some point, but for now it's easiest to use formatted files.

I think I understood how it should be formated.

I am using your example above, But still Autoit crashes with same error.

>Running:(3.3.1.0):C:\Program Files\AutoIt3\beta\autoit3.exe "C:\Documents and Settings\aaa\Desktop\ANN\New AutoIt v3 Script.au3"    
FANN Error 3: Wrong version of configuration file, aborting read of configuration file "mousepatterns.net".
!>11:19:53 AutoIT3.exe ended.rc:-1073741819
+>11:19:54 AutoIt3Wrapper Finished
>Exit code: -1073741819    Time: 31.429

Be Green Now or Never (BGNN)!

Link to comment
Share on other sites

You need to train a neural net on data, using this code:

#include "_Fann.au3"

Global $InputsArray[4][2] = [[-1, -1],[-1, 1],[1, -1],[1, 1]]
Global $OutputsArray[4][1] = [[-1],[1],[1],[-1]]
Local $ANNLayers[3] = [2, 3, 1]
_InitializeANN()
$Ann = _CreateAnn(3, $ANNLayers)
_ANNSetActivationFunctionHidden($Ann, $FANN_SIGMOID_SYMMETRIC)
_ANNSetActivationFunctionOutput($Ann, $FANN_SIGMOID_SYMMETRIC)
_ANNTrainOnData($Ann, $InputsArray, $OutputsArray, 5000, 10, 0.001)
_ANNSaveToFile($Ann, "xor_float.net")
_DestroyANN($Ann)
_CloseANN()

The ANN being created has 3 layers, 2 input, 3 hidden, and 1 output neuron.

For my example, you need to create a neural network with 3 layers, 24 inputs in the first one, 12 hidden neurons, and 11 outputs. The training data is saved into .data files, the networks into .net. It looks like you tried to load the training data as a network.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...