Jump to content
Sign in to follow this  
JRowe

Need help using a neural net dll

Recommended Posts

JRowe

So, first off: here's the dll. There are 6 obj files, one lib file, and an exp file. Do I need to worry about those at all, or am I right in assuming that the dll is the only thing needed to use this package? I just downloaded the source and compiled the windows dll, in the non multi-threaded, release, floating point configuration.

Secondly: http://leenissen.dk/fann/html/files/fann-h.html

Much thanks!

*Edited heavily, got rid of useless information, trying to make it easier to understand, for both myself and those people willing to help.*

Edited by JRowe

Share this post


Link to post
Share on other sites
martin

What I want to do is use neural nets in AutoIt. While I could use native scripting to achieve that, I decided that I might as well do it the right way, and get balls to the wall performance and a reliable package, to boot.

My thought was that dllCall was the appropriate place to start.

So, first off: here's the dll. There are 6 obj files, one lib file, and an exp file. Do I need to worry about those at all, or am I right in assuming that the dll is the only thing needed to use this package? I just downloaded the source and compiled the windows dll, in the non multi-threaded, release, floating point configuration.

Secondly: http://leenissen.dk/fann/html/files/fann-h.html

I want to basically add all those functions to AutoIt. I believe it's relatively easy, but was hoping that maybe I could get an assist from one of the gurus.

So... could someone explain to me how to get from this function to it's AutoIt equivalent using DllCall?

Much thanks!

The function would be used something like this

;$dlltocall is the name of the dll file

$res = DllCall($dlltocall, "ptr", "fan_create_standard", "int", $numberoflayers)
If Not @error Then
    $pstructfan = DllStructCreate($fanstruct, $res[0])
EndIf

$pstructfan is a pointer to a fan struct which is needed as a parameter in further dllcalls, you don't need to deal with the structure directly.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
monoceres

There are 6 obj files, one lib file, and an exp file. Do I need to worry about those at all, or am I right in assuming that the dll is the only thing needed to use this package? I just downloaded the source and compiled the windows dll, in the non multi-threaded, release, floating point configuration.

When using the exported functions you only need the dll, the lib file and such is just there so you can statically link an application so it doesn't need the dll. Something we AutoIt'ers doesn't have to care about.


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites
JRowe

Sorry about the abrupt ending there, I just got interrupted. Basically, what I want to do is expose the whole neural net API available from the dll to AutoIt.

I'm not nearly as familiar with dllCall as I should be.

Here's a c example showing the creation of a standard neural net. The function returns a pointer to struct_fann . struct_fann is the data structure of the neural net, and according to the docs, should never be accessed directly.

// Creating an ANN with 2 input neurons, 1 output neuron,
// and two hidden neurons with 8 and 9 neurons
struct fann *ann = fann_create_standard(4, 2, 8, 9, 1);
So, here's a basic idea of how itwould work in AutoIt (doesnt work, but I'm trying, anyway.)

; load dll
$fannDll = DllOpen(@ScriptDir & "/fannfloat.dll")
;Initialize a parameter
$num_layers = "4, 2, 8, 9, 1"
;call the function "fann_create_standard"
;struct fann *ann = fann_create_standard(4, 2, 8, 9, 1);
$fannPtr = DllCall($fannDll, "ptr", "fann_create_standard", "uint", $num_layers)
DllClose($fannDll)

Getting all sorts of errors. From what I understand, I will need to use the dll struct functions to create the data.

Share this post


Link to post
Share on other sites
martin

Sorry about the abrupt ending there, I just got interrupted. Basically, what I want to do is expose the whole neural net API available from the dll to AutoIt.

I'm not nearly as familiar with dllCall as I should be.

Here's a c example showing the creation of a standard neural net. The function returns a pointer to struct_fann . struct_fann is the data structure of the neural net, and according to the docs, should never be accessed directly.

// Creating an ANN with 2 input neurons, 1 output neuron,
 // and two hidden neurons with 8 and 9 neurons
 struct fann *ann = fann_create_standard(4, 2, 8, 9, 1);
So, here's a basic idea of how itwould work in AutoIt (doesnt work, but I'm trying, anyway.)

; load dll
 $fannDll = DllOpen(@ScriptDir & "/fannfloat.dll")
;Initialize a parameter
 $num_layers = "4, 2, 8, 9, 1"
;call the function "fann_create_standard"
;struct fann *ann = fann_create_standard(4, 2, 8, 9, 1);
 $fannPtr = DllCall($fannDll, "ptr", "fann_create_standard", "uint", $num_layers)
 DllClose($fannDll)

Getting all sorts of errors. From what I understand, I will need to use the dll struct functions to create the data.

Sorry, I didn't read the info correctly and I missed out the numbers for each layer. So using

$num_layers = "4, 2, 8, 9, 1" (ie 4 layers with 2,8,9 and 1 neurons)

; load dll
$fannDll = DllOpen(@ScriptDir & "/fannfloat.dll")
;Initialize a parameter
$num_layers = "4, 2, 8, 9, 1"
;call the function "fann_create_standard"
;struct fann *ann = fann_create_standard(4, 2, 8, 9, 1);
$fannPtr = DllCall($fannDll, "ptr", "fann_create_standard", "uint", $num_layers,"uint",2,"uint",8,"uint",9,"uint",1)
DllClose($fannDll)

It's not clear to me that the number of neurons should be unsigned or not so maybe "uint" should be "int".

You don't need to use DllSTruct* as I mentioned before. From the site you gave a link for

Data within this structure should never be accessed directly, but only by using the fann_get_... and fann_set_... functions.

The fann structure is created using one of the fann_create_... functions and each of the functions which operates on the structure takes struct fann * ann as the first parameter.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
JRowe

Share this post


Link to post
Share on other sites
JRowe

Aaaaand... I'm back.

So, I've tried to convert the first example of usage, and while I'm not getting errors, I'm also not getting results.

; load dll
$fannDll = DllOpen(@ScriptDir & "fannfloat.dll")
   ;const unsigned int num_input = 2;
   ;const unsigned int num_output = 1;
   ;const unsigned int num_layers = 3;
   ;const unsigned int num_neurons_hidden = 3;
   ;const float desired_error = (const float) 0.001;
   ;const unsigned int max_epochs = 500000;
   ;const unsigned int epochs_between_reports = 1000;
$num_input = 2
$num_output = 1
$num_layers = 3
$num_neurons_hidden = 3
$desired_error = .001
$max_epochs = 500000
$epochs_between_reports = 1000

;struct fann *ann = fann_create_standard(num_layers, num_input, num_neurons_hidden, num_output);
$fannPtr = DllCall($fannDll, "ptr", "fann_create_standard", "uint", $num_layers ,"uint", $num_input ,"uint", $num_neurons_hidden, "uint", $num_output)

;fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
DllCall($fannDll, "none", "fann_set_activation_function_hidden", "ptr", $fannPtr, "str", "FANN_SIGMOID_SYMMETRIC")
;fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC);
DllCall($fannDll, "none", "fann_set_activation_function_output", "ptr", $fannPtr, "str", "FANN_SIGMOID_SYMMETRIC")
;fann_train_on_file(ann, "xor.data", max_epochs, epochs_between_reports, desired_error);
DllCall($fannDll, "none", "fann_train_on_file", "ptr", $fannPtr, "str", "xor.data", "uint", $max_epochs, "uint", $epochs_between_reports, "float", $desired_error)
;fann_save(ann, "xor_float.net");
DllCall($fannDll, "none", "fann_save", "ptr", $fannPtr, "str", "xor_float.net")
;fann_destroy(ann);
DllCall($fannDll, "none", "fann_destroy", "ptr", $fannPtr)

DllClose($fannDll)

I'm assuming I'm probably doing something wrong with the dllCalls. Anyone see anything wrong ?

Share this post


Link to post
Share on other sites
martin

Aaaaand... I'm back.

So, I've tried to convert the first example of usage, and while I'm not getting errors, I'm also not getting results.

; load dll
 $fannDll = DllOpen(@ScriptDir & "fannfloat.dll")
   ;const unsigned int num_input = 2;
   ;const unsigned int num_output = 1;
   ;const unsigned int num_layers = 3;
   ;const unsigned int num_neurons_hidden = 3;
   ;const float desired_error = (const float) 0.001;
   ;const unsigned int max_epochs = 500000;
   ;const unsigned int epochs_between_reports = 1000;
 $num_input = 2
 $num_output = 1
 $num_layers = 3
 $num_neurons_hidden = 3
 $desired_error = .001
 $max_epochs = 500000
 $epochs_between_reports = 1000
 
;struct fann *ann = fann_create_standard(num_layers, num_input, num_neurons_hidden, num_output);
 $fannPtr = DllCall($fannDll, "ptr", "fann_create_standard", "uint", $num_layers ,"uint", $num_input ,"uint", $num_neurons_hidden, "uint", $num_output)
 
;fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
 DllCall($fannDll, "none", "fann_set_activation_function_hidden", "ptr", $fannPtr, "str", "FANN_SIGMOID_SYMMETRIC")
;fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC);
 DllCall($fannDll, "none", "fann_set_activation_function_output", "ptr", $fannPtr, "str", "FANN_SIGMOID_SYMMETRIC")
;fann_train_on_file(ann, "xor.data", max_epochs, epochs_between_reports, desired_error);
 DllCall($fannDll, "none", "fann_train_on_file", "ptr", $fannPtr, "str", "xor.data", "uint", $max_epochs, "uint", $epochs_between_reports, "float", $desired_error)
;fann_save(ann, "xor_float.net");
 DllCall($fannDll, "none", "fann_save", "ptr", $fannPtr, "str", "xor_float.net")
;fann_destroy(ann);
 DllCall($fannDll, "none", "fann_destroy", "ptr", $fannPtr)
 
 DllClose($fannDll)

I'm assuming I'm probably doing something wrong with the dllCalls. Anyone see anything wrong ?

The error that is obvious to me is that you have used the return from a dll incorrectly. If successful DllCall returns an array and the return from the function called is in the first element.

So add a line

$fannPtr = DllCall($fannDll, "ptr", "fann_create_standard", "uint", $num_layers ,"uint", $num_input ,"uint", $num_neurons_hidden, "uint", $num_output);<--after this line

$fannPtr = $fannPtr[0];<--add this line


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
JRowe

I've actually gotten to there, and now I'm at:

$fannDll = DllOpen("fannfloat.dll")
MsgBox(0, "Does The DLL Get Loaded?", $fannDll & @CRLF & "If 1, Yes, it does.")
$fannPtr = DllCall($fannDll, "ptr:cdecl", "fann_create_standard", "uint", 3 ,"uint", 2 ,"uint", 3, "uint", 1)
MsgBox(0, "Test", $fannPtr[0])
$testCall = DllCall($fannDll, "none", "fann_set_activation_function_", "ptr", $fannPtr[0], "str", "FANN_SIGMOID_SYMMETRIC")
MsgBox(0, "Test", $testCall)
$testCall2 = DllCall($fannDll, "none", "fann_set_activation_function_output", "ptr", $fannPtr[0], "str", "FANN_SIGMOID_SYMMETRIC")
MsgBox(0, "Test", $testCall2)
$testCall3 = DllCall($fannDll, "none", "fann_train_on_file", "ptr", $fannPtr[0], "str", "xor.data", "uint", 500000, "uint", 1000, "float", .001)
MsgBox(0, "Test", $testCall3)
$fileTest = DllCall($fannDll, "int:cdecl", "fann_save", "ptr", $fannPtr[0], "char", "xor_float.net")
MsgBox(0, "Test", $fileTest)

That could should cause a file to be written to the script directory "xor_float.net"

Unfortunately, it's not doing anything, although it's not crashing or reporting errors.

Share this post


Link to post
Share on other sites
trancexx

You should really read all available documentation before trying anything.

Try this code as... something:

$hFannDll = DllOpen(@ScriptDir & "/fannfloat.dll") ; or wherever

$num_layers = 3
$num_input = 3
$num_neurons_hidden = 3
$num_output = 1

$aCall = DllCall($hFannDll, "hwnd:cdecl", "fann_create_standard", _
        "dword", $num_layers, _
        "dword", $num_input, _
        "dword", $num_neurons_hidden, _
        "dword", $num_output)

$hAnn = $aCall[0]

ConsoleWrite("$hAnn: " & $hAnn & @CRLF)

$desired_error = 0.001
$max_epochs = 500000
$epochs_between_reports = 1000

$aCall = DllCall($hFannDll, "int", "_fann_train_on_file@20", _
        "hwnd", $hAnn, _
        "str", "xor.data", _
        "dword", $max_epochs, _
        "dword", $epochs_between_reports, _
        "float", $desired_error)

$aCall = DllCall($hFannDll, "int", "_fann_destroy@4", "hwnd", $hAnn)
ConsoleWrite("fann destroyed: " & $aCall[0] & @CRLF)

DllClose($hFannDll)

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
JRowe

What are you pointing out? The c code examples used unsigned ints as the datatypes for the parameters, so I copied that over. You're using hWnd, which is... a handle to a process? Sorry if I'm missing something blazingly obvious, lol.

Thanks for that, and if you could go into a little more detail in why you used those datatypes, I would be grateful.

Share this post


Link to post
Share on other sites
trancexx

What are you pointing out? The c code examples used unsigned ints as the datatypes for the parameters, so I copied that over. You're using hWnd, which is... a handle to a process? Sorry if I'm missing something blazingly obvious, lol.

Thanks for that, and if you could go into a little more detail in why you used those datatypes, I would be grateful.

I'm using unsigned integers too and hwnd is a pointer.

As I see it "fann_create_standard" will get you pointer to something that you use later on as a handle. That's why I used "hwnd".

"dword" is the same as "uint"

This could be fann_save:

$sFile = @ScriptDir & "\xor_float.net"
$aCall = DllCall($hFannDll, "int", "_fann_save@8", _
        "hwnd", $hAnn, _
        "str", $sFile)
ConsoleWrite("fann saved return: " & $aCall[0] & @CRLF)

As for what I'm pointing out... I'm pointing out that you should read all available documentation before trying anything.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
JRowe
JRowe

Hmm, one thing that I'm not seeing, what do the additional underscores and the "@4" signifiy, within the dllCalls, such as:

DllCall($hFannDll, "int", "_fann_destroy@4", "hwnd", $hAnn)

I can't find any reference to the like within AutoIt docs, nor anything enlightening on the fann side.

edit: What I do see is that the number is 4 times the number of parameters passed to the function. I've gotten "_fann_set_activation_function_output" to work (at least superficially) on that method, so I'm going to assume that its a method of working with structs, allocating space for parameters. 4 bytes for each reference, or some such.

So, everything trancexx has put together works, apparently flawlessly. What's not working:

fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
    fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC);

I suspect, from my conversation with Smoke_N, and from experiments, that the problem lies with FANN_SIGMOID_SYMMETRIC, or specifying the correct value. using "str", "FANN_SIGMOID_SYMMETRIC" doesn't seem to be working, as all I'm getting are errors of 1.0000, and Bit Fail 4.

It's got something to do with setting one of the parameters as an an enumerated value (if I'm on the right trail.)

FANN_EXTERNAL void FANN_API fann_set_activation_function_output(
    struct  fann    *   ann,
    enum    fann_activationfunc_enum        activation_function
)

Edit again:

Ahh ha. Enum in c = macro that returns an int identifier, so im gonna be able to use an int as the activation function. Which is true. 0-5 are Activation functions.

Moving on, then, to fann_run, etc. :)

Edited by JRowe

Share this post


Link to post
Share on other sites
JRowe

So, here's a working recreation of the training example in c:

CODE
$hFannDll = DllOpen(@ScriptDir & "/fannfloat.dll") ; or wherever

$num_layers = 3

$num_input = 2

$num_neurons_hidden = 3

$num_output = 1

$aCall = DllCall($hFannDll, "hwnd:cdecl", "fann_create_standard", _

"dword", $num_layers, _

"dword", $num_input, _

"dword", $num_neurons_hidden, _

"dword", $num_output)

$hAnn = $aCall[0]

ConsoleWrite("$hAnn: " & $hAnn & @CRLF)

$aCall = DllCall($hFannDll, "none", "_fann_set_activation_function_hidden@8", _

"hwnd", $hAnn, _

"dword", 2)

ConsoleWrite("Activation Function Return: " & $aCall[0] & @CRLF)

$aCall = DllCall($hFannDll, "none", "_fann_set_activation_function_output@8", _

"hwnd", $hAnn, _

"dword", 2)

ConsoleWrite("Activation Function Return: " & $aCall[0] & @CRLF)

$desired_error = 0.0001

$max_epochs = 600000

$epochs_between_reports = 1000

$aCall = DllCall($hFannDll, "int", "_fann_train_on_file@20", _

"hwnd", $hAnn, _

"str", "xor.data", _

"dword", $max_epochs, _

"dword", $epochs_between_reports, _

"float", $desired_error)

$sFile = @ScriptDir & "\xor_float.net"

$a2Call = DllCall($hFannDll, "int", "_fann_save@8", _

"hwnd", $hAnn, _

"str", $sFile)

ConsoleWrite("fann saved as: " & $a2Call[2] & @CRLF)

$aCall = DllCall($hFannDll, "int", "_fann_destroy@4", "hwnd", $hAnn)

ConsoleWrite("fann destroyed: " & $aCall[0] & @CRLF)

DllClose($hFannDll)

Now, I'm struggling with loading from a file. Fortunately, I found a list of functions and the @ specifications, so this should be much smoother going.

Thank you very much, trancexx!

Edited by JRowe

Share this post


Link to post
Share on other sites
JRowe

Last bit for the night. I can load the neural net created from the training session, succesffuly (without crashing) execute fann_run, and get a result from it.

The results aren't what I'm expecting, though. :)

Here's the code:

$hFannDll = DllOpen(@ScriptDir & "/fannfloat.dll")

$sFile = @ScriptDir & "\xor_float.net"
$wheresThePointer = "???"; Some sort of dllStructCreate magic needed here, I think.

$aCall = DllCall($hFannDll, "hwnd", "_fann_create_from_file@4", _
        "str", $sFile)
        
$hAnn = $aCall[0]
ConsoleWrite("$hAnn: " & $hAnn & @CRLF)


$input = DllStructCreate("float inputs[2]")
DllStructSetData($input,"inputs", -1)
DllStructSetData($input,"inputs", 1,1)

$aCall = DllStructCreate("dword calc_out" , _ 
                DllCall($hFannDll, "float*", "_fann_run@8", _
                    "hwnd", $hAnn, _
                    "dword*", DllStructGetPtr($input)) _
            )
ConsoleWrite("fann run: " & DllStructGetData($aCall, "calc_out") & @CRLF)


$aCall = DllCall($hFannDll, "int", "_fann_destroy@4", "hwnd", $hAnn)

ConsoleWrite("fann destroyed: " & $aCall[0] & @CRLF)

DllClose($hFannDll)

What I want to do is create a struct for inputs, which should be an array of two integers. -1 and 1. According to XOR logic, that should return "1".

I think I lost myself somwhere, though. Passing a pointer to a dllStructCreate by passing a struct to a DllCall by a pointer in one of the parameters should return the pointer to a struct containing the result of the DllCall, correct?

*maniacal laughter*

Share this post


Link to post
Share on other sites
JRowe

Alright, I've tried many, many variations of the above, and tried to figure out how the function is being called. Because of the neural net loaded, it requires 2 inputs. fann_type = float, for the purposes of this dll. Therefore, I used dllStructCreate to make a struct array of 2 float inputs, -1 and 1. fann_run should return "1."

I get -1.#IND, instead, which i think is an indication of division by zero, or some similar error.

$hFannDll = DllOpen(@ScriptDir & "/fannfloat.dll")

$sFile = @ScriptDir & "\xor_float.net"

$aCall = DllCall($hFannDll, "hwnd", "_fann_create_from_file@4", _
        "str", $sFile)
        
$hAnn = $aCall[0]
ConsoleWrite("$hAnn: " & $hAnn & @CRLF)


$input = DllStructCreate("float inputs[2]")
DllStructSetData($input,"inputs", 1, 1)
DllStructSetData($input,"inputs", -1,2)

$aCall = DllCall($hFannDll, "dword", "_fann_run@8", _
                    "hwnd", $hAnn, _
                    "float*", DllStructGetPtr($input))
ConsoleWrite("fann run: " & $aCall[0] & @CRLF)


$aCall = DllCall($hFannDll, "int", "_fann_destroy@4", "hwnd", $hAnn)

ConsoleWrite("fann destroyed: " & $aCall[0] & @CRLF)

DllClose($hFannDll)

That's where I'm stuck at.

Edited by JRowe

Share this post


Link to post
Share on other sites
trancexx

What "float*", DllStructGetPtr($input) means?


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
JRowe

Err... wow. I think I was trying to pass the fann_type struct pointer to the fann_run function after building a DllStruct . It's supposed to take an array of two values as input, according to the source code I'm trying to reproduce:

#include "floatfann.h"

int main()
{
    fann_type *calc_out;
    fann_type input[2];

    struct fann *ann = fann_create_from_file("xor_float.net");

    input[0] = -1;
    input[1] = 1;
    calc_out = fann_run(ann, input);

    printf("xor test (%f,%f) -> %f\n", input[0], input[1], calc_out[0]);

    fann_destroy(ann);
    return 0;
}

I think I might have to create a calc_out struct, as well. Thanks for taking another peek, trancexx. I really appreciate the help!

Share this post


Link to post
Share on other sites
JRowe

Here's (I think) a good question: what tools or methods do you use to discover the datatypes needed for a function? How would I read a function's source code and determine what the AutoIt equivalent is?

I just discovered Monoceres' Dll Export Viewer, which enumerated all the functions for me, and I was wondering if there might be a tool that took things a step further and returned the parameter types in addition to the exports?

Share this post


Link to post
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
Sign in to follow this  

×