AI-Perceptron-Simple

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

    * &display_confusion_matrix
* improved the documentation

Version 1.01    24 AUGUST 2021
* Fixed some technical issues
    * fixed test scripts not run in correct sequence
        * must be creation -> train -> validate/test
    * local::lib issue should be fixed by now

Version 1.00    23 AUGUST 2021
* The following features were implemented over the course of time (see also My::Perceptron v0.04 on github):
    * create perceptron
    * process data: &train method
        * read csv - for training stage
    * save and load the perceptron

    * output algorithm for train
        * read and calculate data line by line
    * validate method
        * read csv bulk
        * write predicted values into original file

Changes  view on Meta::CPAN

            * accuracy
            * sensitivity
    * display confusion matrix data to console
        * use Text:Matrix

    * synonyms
        * synonyms MUST call actual subroutines and not copy pasting!
        * train: tame, exercise
        * validate: take_mock_exam, take_lab_test
        * test:  take_real_exam, work_in_real_world
        * generate_confusion_matrix: get_exam_results
        * display_confusion_matrix: display_exam_results
        * save_perceptron: preserve
        * load_perceptron: revive



LICENSE  view on Meta::CPAN

make of the Package, you should contact the Copyright Holder and seek
a different licensing arrangement. 

Definitions

    "Copyright Holder" means the individual(s) or organization(s)
    named in the copyright notice for the entire Package.

    "Contributor" means any party that has contributed code or other
    material to the Package, in accordance with the Copyright Holder's
    procedures.

    "You" and "your" means any person who would like to copy,
    distribute, or modify the Package.

    "Package" means the collection of files distributed by the
    Copyright Holder, and derivatives of that collection and/or of
    those files. A given Package may consist of either the Standard
    Version, or a Modified Version.

    "Distribute" means providing a copy of the Package or making it

LICENSE  view on Meta::CPAN

    Holder. 

    "Original License" means this Artistic License as Distributed with
    the Standard Version of the Package, in its current version or as
    it may be modified by The Perl Foundation in the future.

    "Source" form means the source code, documentation source, and
    configuration files for the Package.

    "Compiled" form means the compiled bytecode, object code, binary,
    or any other form resulting from mechanical transformation or
    translation of the Source form.


Permission for Use and Modification Without Distribution

(1)  You are permitted to use the Standard Version and create and use
Modified Versions for any purpose without restriction, provided that
you do not Distribute the Modified Version.


Permissions for Redistribution of the Standard Version

(2)  You may Distribute verbatim copies of the Source form of the
Standard Version of this Package in any medium without restriction,
either gratis or for a Distributor Fee, provided that you duplicate
all of the original copyright notices and associated disclaimers.  At
your discretion, such verbatim copies may or may not include a
Compiled form of the Package.

(3)  You may apply any bug fixes, portability changes, and other
modifications made available from the Copyright Holder.  The resulting
Package will still be considered the Standard Version, and as such
will be subject to the Original License.


Distribution of Modified Versions of the Package as Source 

(4)  You may Distribute your Modified Version as Source (either gratis
or for a Distributor Fee, and with or without a Compiled form of the
Modified Version) provided that you clearly document how it differs
from the Standard Version, including, but not limited to, documenting
any non-standard features, executables, or modules, and provided that
you do at least ONE of the following:

    (a)  make the Modified Version available to the Copyright Holder
    of the Standard Version, under the Original License, so that the
    Copyright Holder may include your modifications in the Standard
    Version.

    (b)  ensure that installation of your Modified Version does not
    prevent the user installing or running the Standard Version. In
    addition, the Modified Version must bear a name that is different

LICENSE  view on Meta::CPAN


    (c)  allow anyone who receives a copy of the Modified Version to
    make the Source form of the Modified Version available to others
    under
		
	(i)  the Original License or

	(ii)  a license that permits the licensee to freely copy,
	modify and redistribute the Modified Version using the same
	licensing terms that apply to the copy that the licensee
	received, and requires that the Source form of the Modified
	Version, and of any works derived from it, be made freely
	available in that license fees are prohibited but Distributor
	Fees are allowed.


Distribution of Compiled Forms of the Standard Version 
or Modified Versions without the Source

(5)  You may Distribute Compiled forms of the Standard Version without
the Source, provided that you include complete instructions on how to
get the Source of the Standard Version.  Such instructions must be
valid at the time of your distribution.  If these instructions, at any
time while you are carrying out such distribution, become invalid, you
must provide new instructions on demand or cease further distribution.
If you provide valid instructions or cease distribution within thirty
days after you become aware that the instructions are invalid, then
you do not forfeit any of your rights under this license.

(6)  You may Distribute a Modified Version in Compiled form without
the Source, provided that you comply with Section 4 with respect to
the Source of the Modified Version.


Aggregating or Linking the Package 

(7)  You may aggregate the Package (either the Standard Version or
Modified Version) with other packages and Distribute the resulting
aggregation provided that you do not charge a licensing fee for the
Package.  Distributor Fees are permitted, and licensing fees for other
components in the aggregation are permitted. The terms of this license
apply to the use and Distribution of the Standard or Modified Versions
as included in the aggregation.

(8) You are permitted to link Modified and Standard Versions with
other works, to embed the Package in a larger work of your own, or to
build stand-alone binary or bytecode versions of applications that
include the Package, and Distribute the result without restriction,
provided the result does not expose a direct interface to the Package.


Items That are Not Considered Part of a Modified Version 

(9) Works (including, but not limited to, modules and scripts) that
merely extend or make use of the Package, do not, by themselves, cause
the Package to be a Modified Version.  In addition, such works are not
considered parts of the Package itself, and are not subject to the
terms of this license.

LICENSE  view on Meta::CPAN

(11)  If your Modified Version has been derived from a Modified
Version made by someone other than you, you are nevertheless required
to ensure that your Modified Version complies with the requirements of
this license.

(12)  This license does not grant you the right to use any trademark,
service mark, tradename, or logo of the Copyright Holder.

(13)  This license includes the non-exclusive, worldwide,
free-of-charge patent license to make, have made, use, offer to sell,
sell, import and otherwise transfer the Package with respect to any
patent claims licensable by the Copyright Holder that are necessarily
infringed by the Package. If you institute patent litigation
(including a cross-claim or counterclaim) against any party alleging
that the Package constitutes direct or contributory patent
infringement, then this Artistic License to you shall terminate on the
date that such litigation is filed.

(14)  Disclaimer of Warranty:
THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED

META.json  view on Meta::CPAN

   },
   "name" : "AI-Perceptron-Simple",
   "no_index" : {
      "directory" : [
         "t",
         "inc"
      ]
   },
   "prereqs" : {
      "build" : {
         "requires" : {
            "ExtUtils::MakeMaker" : "0"
         }
      },
      "configure" : {
         "requires" : {
            "ExtUtils::MakeMaker" : "0"
         }
      },
      "runtime" : {
         "requires" : {
            "Carp" : "0",
            "File::Basename" : "0",
            "List::Util" : "0",
            "Storable" : "0",
            "Text::CSV" : "2.01",
            "Text::Matrix" : "1.00",
            "YAML" : "0",
            "local::lib" : "0",
            "perl" : "5.008001",
            "utf8" : "0"
         }
      },
      "test" : {
         "requires" : {
            "FindBin" : "0",
            "Test::More" : "0",
            "Test::Output" : "1.033"
         }
      }
   },
   "release_status" : "stable",
   "version" : "1.04",
   "x_serialization_backend" : "JSON::PP version 4.02"
}

META.yml  view on Meta::CPAN

---
abstract: unknown
author:
  - 'Raphael Jong Jun Jie <ellednera@cpan.org>'
build_requires:
  ExtUtils::MakeMaker: '0'
  FindBin: '0'
  Test::More: '0'
  Test::Output: '1.033'
configure_requires:
  ExtUtils::MakeMaker: '0'
dynamic_config: 1
generated_by: 'ExtUtils::MakeMaker version 7.62, CPAN::Meta::Converter version 2.150010'
license: artistic_2
meta-spec:
  url: http://module-build.sourceforge.net/META-spec-v1.4.html
  version: '1.4'
name: AI-Perceptron-Simple
no_index:
  directory:
    - t
    - inc
requires:
  Carp: '0'
  File::Basename: '0'
  List::Util: '0'
  Storable: '0'
  Text::CSV: '2.01'
  Text::Matrix: '1.00'
  YAML: '0'
  local::lib: '0'
  perl: '5.008001'
  utf8: '0'

Makefile.PL  view on Meta::CPAN

        'YAML' => '0',
        'File::Basename' => '0',
        'List::Util' => '0',
    },
    dist  => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
    clean => { FILES => 'AI-Perceptron-Simple-*' },
);

# Compatibility with old versions of ExtUtils::MakeMaker
unless (eval { ExtUtils::MakeMaker->VERSION('6.64'); 1 }) {
    my $test_requires = delete $WriteMakefileArgs{TEST_REQUIRES} || {};
    @{$WriteMakefileArgs{PREREQ_PM}}{keys %$test_requires} = values %$test_requires;
}

unless (eval { ExtUtils::MakeMaker->VERSION('6.55_03'); 1 }) {
    my $build_requires = delete $WriteMakefileArgs{BUILD_REQUIRES} || {};
    @{$WriteMakefileArgs{PREREQ_PM}}{keys %$build_requires} = values %$build_requires;
}

delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
    unless eval { ExtUtils::MakeMaker->VERSION('6.52'); 1 };
delete $WriteMakefileArgs{MIN_PERL_VERSION}
    unless eval { ExtUtils::MakeMaker->VERSION('6.48'); 1 };
delete $WriteMakefileArgs{LICENSE}
    unless eval { ExtUtils::MakeMaker->VERSION('6.31'); 1 };

WriteMakefile(%WriteMakefileArgs);

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

      <li><a href="#shuffle_data-original_data-shuffled_1-shuffled_2">shuffle_data ( $original_data =&gt; $shuffled_1, $shuffled_2, ... )</a></li>
      <li><a href="#shuffle_data-ORIGINAL_DATA-shuffled_1-shuffled_2">shuffle_data ( ORIGINAL_DATA, $shuffled_1, $shuffled_2, ... )</a></li>
    </ul>
  </li>
  <li><a href="#CREATION-RELATED-SUBROUTINES-METHODS">CREATION RELATED SUBROUTINES/METHODS</a>
    <ul>
      <li><a href="#new-options">new ( \%options )</a></li>
      <li><a href="#get_attributes">get_attributes</a></li>
      <li><a href="#learning_rate-value">learning_rate ( $value )</a></li>
      <li><a href="#learning_rate">learning_rate</a></li>
      <li><a href="#threshold-value">threshold ( $value )</a></li>
      <li><a href="#threshold">threshold</a></li>
    </ul>
  </li>
  <li><a href="#TRAINING-RELATED-SUBROUTINES-METHODS">TRAINING RELATED SUBROUTINES/METHODS</a>
    <ul>
      <li><a href="#tame">tame ( ... )</a></li>
      <li><a href="#exercise">exercise ( ... )</a></li>
      <li><a href="#train-stimuli_train_csv-expected_output_header-save_nerve_to_file">train ( $stimuli_train_csv, $expected_output_header, $save_nerve_to_file )</a></li>
      <li><a href="#train-stimuli_train_csv-expected_output_header-save_nerve_to_file-display_stats-identifier">train ( $stimuli_train_csv, $expected_output_header, $save_nerve_to_file, $display_stats, $identifier )</a></li>
      <li><a href="#calculate_output-self-stimuli_hash">&amp;_calculate_output( $self, \%stimuli_hash )</a></li>
      <li><a href="#tune-self-stimuli_hash-tune_up_or_down">&amp;_tune( $self, \%stimuli_hash, $tune_up_or_down )</a></li>

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

    <ul>
      <li><a href="#take_real_exam">take_real_exam (...)</a></li>
      <li><a href="#work_in_real_world">work_in_real_world (...)</a></li>
      <li><a href="#test-options">test ( \%options )</a></li>
      <li><a href="#real_validate_or_test-data_hash_ref">_real_validate_or_test ( $data_hash_ref )</a></li>
      <li><a href="#fill_predicted_values-self-stimuli_validate-predicted_index-aoa">&amp;_fill_predicted_values ( $self, $stimuli_validate, $predicted_index, $aoa )</a></li>
    </ul>
  </li>
  <li><a href="#RESULTS-RELATED-SUBROUTINES-METHODS">RESULTS RELATED SUBROUTINES/METHODS</a>
    <ul>
      <li><a href="#get_exam_results">get_exam_results ( ... )</a></li>
      <li><a href="#get_confusion_matrix-options">get_confusion_matrix ( \%options )</a></li>
      <li><a href="#collect_stats-options">&amp;_collect_stats ( \%options )</a></li>
      <li><a href="#calculate_total_entries-c_matrix_ref">&amp;_calculate_total_entries ( $c_matrix_ref )</a></li>
      <li><a href="#calculate_accuracy-c_matrix_ref">&amp;_calculate_accuracy ( $c_matrix_ref )</a></li>
      <li><a href="#calculate_sensitivity-c_matrix_ref">&amp;_calculate_sensitivity ( $c_matrix_ref )</a></li>
      <li><a href="#calculate_precision-c_matrix_ref">&amp;_calculate_precision ( $c_matrix_ref )</a></li>
      <li><a href="#calculate_specificity-c_matrix_ref">&amp;_calculate_specificity ( $c_matrix_ref )</a></li>
      <li><a href="#calculate_f1_score-c_matrix_ref">&amp;_calculate_f1_score ( $c_matrix_ref )</a></li>
      <li><a href="#calculate_negative_predicted_value-c_matrix_ref">&amp;_calculate_negative_predicted_value( $c_matrix_ref )</a></li>
      <li><a href="#calculate_false_negative_rate-c_matrix_ref">&amp;_calculate_false_negative_rate( $c_matrix_ref )</a></li>
      <li><a href="#calculate_false_positive_rate-c_matrix_ref">&amp;_calculate_false_positive_rate( $c_matrix_ref )</a></li>
      <li><a href="#calculate_false_discovery_rate-c_matrix_ref">&amp;_calculate_false_discovery_rate( $c_matrix_ref )</a></li>
      <li><a href="#calculate_false_omission_rate-c_matrix_ref">&amp;_calculate_false_omission_rate( $c_matrix_ref )</a></li>
      <li><a href="#calculate_balanced_accuracy-c_matrix_ref">&amp;_calculate_balanced_accuracy( $c_matrix_ref )</a></li>
      <li><a href="#display_exam_results">display_exam_results ( ... )</a></li>
      <li><a href="#display_confusion_matrix-confusion_matrix-labels">display_confusion_matrix ( \%confusion_matrix, \%labels )</a></li>
      <li><a href="#build_matrix-c_matrix-labels">&amp;_build_matrix ( $c_matrix, $labels )</a></li>
      <li><a href="#print_extended_matrix-matrix-c_matrix">&amp;_print_extended_matrix ( $matrix, $c_matrix )</a></li>
    </ul>
  </li>
  <li><a href="#NERVE-DATA-RELATED-SUBROUTINES">NERVE DATA RELATED SUBROUTINES</a>
    <ul>
      <li><a href="#preserve">preserve ( ... )</a></li>
      <li><a href="#save_perceptron-nerve-nerve_file">save_perceptron ( $nerve, $nerve_file )</a></li>
      <li><a href="#revive">revive (...)</a></li>
      <li><a href="#load_perceptron-nerve_file_to_load">load_perceptron ( $nerve_file_to_load )</a></li>
    </ul>
  </li>
  <li><a href="#NERVE-PORTABILITY-RELATED-SUBROUTINES">NERVE PORTABILITY RELATED SUBROUTINES</a>
    <ul>
      <li><a href="#preserve_as_yaml">preserve_as_yaml ( ... )</a></li>
      <li><a href="#save_perceptron_yaml-nerve-yaml_nerve_file">save_perceptron_yaml ( $nerve, $yaml_nerve_file )</a></li>
      <li><a href="#revive_from_yaml">revive_from_yaml (...)</a></li>
      <li><a href="#load_perceptron_yaml-yaml_nerve_file">load_perceptron_yaml ( $yaml_nerve_file )</a></li>
    </ul>
  </li>
  <li><a href="#TO-DO">TO DO</a></li>
  <li><a href="#KNOWN-ISSUES">KNOWN ISSUES</a>
    <ul>
      <li><a href="#Portability-of-Nerve-Data">Portability of Nerve Data</a></li>
    </ul>

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

<h1 id="SYNOPSIS">SYNOPSIS</h1>

<pre><code>    #!/usr/bin/perl

    use AI::Perceptron::Simple qw(...);

    # create a new nerve / neuron / perceptron
    $nerve = AI::Perceptron::Simple-&gt;new( {
        initial_value =&gt; $size_of_each_dendrite,
        learning_rate =&gt; 0.3, # optional
        threshold =&gt; 0.85, # optional
        attribs =&gt; \@dendrites,
    } );

    # train
    $nerve-&gt;tame( ... );
    $nerve-&gt;exercise( ... );
    $nerve-&gt;train( $training_data_csv, $expected_column_name, $save_nerve_to );
    # or
    $nerve-&gt;train(
        $training_data_csv, $expected_column_name, $save_nerve_to, 
        $show_progress, $identifier); # these two parameters must go together


    # validate
    $nerve-&gt;take_lab_test( ... );
    $nerve-&gt;take_mock_exam( ... );

    # fill results to original file
    $nerve-&gt;validate( { 
        stimuli_validate =&gt; $validation_data_csv, 
        predicted_column_index =&gt; 4,
     } );
    # or        
    # fill results to a new file
    $nerve-&gt;validate( {
        stimuli_validate =&gt; $validation_data_csv,
        predicted_column_index =&gt; 4,
        results_write_to =&gt; $new_csv
    } );


    # test - see &quot;validate&quot; method, same usage
    $nerve-&gt;take_real_exam( ... );
    $nerve-&gt;work_in_real_world( ... );
    $nerve-&gt;test( ... );


    # confusion matrix

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

        zero_as =&gt; &quot;bad apples&quot;, # cat  milk   green  etc.
        one_as =&gt; &quot;good apples&quot;, # dog  honey  pink   etc.
    } );


    # saving and loading data of perceptron locally
    # NOTE: nerve data is automatically saved after each trainning process
    use AI::Perceptron::Simple &quot;:local_data&quot;;

    my $nerve_file = &quot;apples.nerve&quot;;
    preserve( ... );
    save_perceptron( $nerve, $nerve_file );

    # load data of percpetron for use in actual program
    my $apple_nerve = revive( ... );
    my $apple_nerve = load_perceptron( $nerve_file );


    # for portability of nerve data
    use AI::Perceptron::Simple &quot;:portable_data&quot;;

    my $yaml_nerve_file = &quot;pearls.yaml&quot;;
    preserve_as_yaml ( ... );
    save_perceptron_yaml ( $nerve, $yaml_nerve_file );

    # load nerve data on the other computer
    my $pearl_nerve = revive_from_yaml ( ... );
    my $pearl_nerve = load_perceptron_yaml ( $yaml_nerve_file );


    # processing data
    use AI::Perceptron::Simple &quot;:process_data&quot;;
    shuffle_stimuli ( ... )

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

</dl>

<p>Most of the stuff are OO.</p>

<h1 id="DESCRIPTION">DESCRIPTION</h1>

<p>This module provides methods to build, train, validate and test a perceptron. It can also save the data of the perceptron for future use for any actual AI programs.</p>

<p>This module is also aimed to help newbies grasp hold of the concept of perceptron, training, validation and testing as much as possible. Hence, all the methods and subroutines in this module are decoupled as much as possible so that the actual scr...

<p>The implementation here is super basic as it only takes in input of the dendrites and calculate the output. If the output is higher than the threshold, the final result (category) will be 1 aka perceptron is activated. If not, then the result will...

<p>Depending on how you view or categorize the final result, the perceptron will fine tune itself (aka train) based on the learning rate until the desired result is met. Everything from here on is all mathematics and numbers which only makes sense to...

<p>Whenever the perceptron fine tunes itself, it will increase/decrease all the dendrites that is significant (attributes labelled 1) for each input. This means that even when the perceptron successfully fine tunes itself to suite all the data in you...

<h1 id="CONVENTIONS-USED">CONVENTIONS USED</h1>

<p>Please take note that not all subroutines/method must be used to make things work. All the subroutines and methods are listed out for the sake of writing the documentation.</p>

<p>Private methods/subroutines are prefixed with <code>_</code> or <code>&amp;_</code> and they aren&#39;t meant to be called directly. You can if you want to. There are quite a number of them to be honest, just ignore them if you happen to see them ...

<p>Synonyms are placed before the actual ie. technical subroutines/methods. You will see <code>...</code> as the parameters if they are synonyms. Move to the next subroutine/method until you find something like <code>\%options</code> as the parameter...

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

<dt id="learning_rate-decimal">learning_rate =&gt; $decimal</dt>
<dd>

<p>Optional. The default is <code>0.05</code>.</p>

<p>The learning rate of the perceptron for the fine-tuning process.</p>

<p>This value is usually between 0 and 1. However, it all depends on your combination of numbers for the other options.</p>

</dd>
<dt id="threshold-decimal">threshold =&gt; $decimal</dt>
<dd>

<p>Optional. The default is <code>0.5</code></p>

<p>This is the passing rate to determine the neuron output (<code>0</code> or <code>1</code>).</p>

<p>Generally speaking, this value is usually between <code>0</code> and <code>1</code>. However, it all depend on your combination of numbers for the other options.</p>

</dd>
</dl>

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

<h2 id="get_attributes">get_attributes</h2>

<p>Obtains a hash of all the attributes of the perceptron</p>

<h2 id="learning_rate-value">learning_rate ( $value )</h2>

<h2 id="learning_rate">learning_rate</h2>

<p>If <code>$value</code> is given, sets the learning rate to <code>$value</code>. If not, then it returns the learning rate.</p>

<h2 id="threshold-value">threshold ( $value )</h2>

<h2 id="threshold">threshold</h2>

<p>If <code>$value</code> is given, sets the threshold / passing rate to <code>$value</code>. If not, then it returns the passing rate.</p>

<h1 id="TRAINING-RELATED-SUBROUTINES-METHODS">TRAINING RELATED SUBROUTINES/METHODS</h1>

<p>All the training methods here have the same parameters as the two actual <code>train</code> method and they all do the same stuff. They are also used in the same way.</p>

<h2 id="tame">tame ( ... )</h2>

<h2 id="exercise">exercise ( ... )</h2>

<h2 id="train-stimuli_train_csv-expected_output_header-save_nerve_to_file">train ( $stimuli_train_csv, $expected_output_header, $save_nerve_to_file )</h2>

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN


<p>Indicates the nerve was tuned up, down or no tuning needed</p>

</dd>
<dt id="old-sum">old sum</dt>
<dd>

<p>The original sum of all <code>weightage * input</code> or <code>dendrite_size * binary_input</code></p>

</dd>
<dt id="threshold1">threshold</dt>
<dd>

<p>The threshold of the nerve</p>

</dd>
<dt id="new-sum">new sum</dt>
<dd>

<p>The new sum of all <code>weightage * input</code> after fine-tuning the nerve</p>

</dd>
</dl>

<p>If <code>$display_stats</code> is specified ie. set to <code>1</code>, then you <b>MUST</b> specify the <code>$identifier</code>. <code>$identifier</code> is the column / header name that is used to identify a specific row of data in <code>$stimul...

<h2 id="calculate_output-self-stimuli_hash">&amp;_calculate_output( $self, \%stimuli_hash )</h2>

<p>Calculates and returns the <code>sum(weightage*input)</code> for each individual row of data. Actually, it justs add up all the existing weight since the <code>input</code> is always 1 for now :)</p>

<p><code>%stimuli_hash</code> is the actual data to be used for training. It might contain useless columns.</p>

<p>This will get all the avaible dendrites using the <code>get_attributes</code> method and then use all the keys ie. headers to access the corresponding values.</p>

<p>This subroutine should be called in the procedural way for now.</p>

<h2 id="tune-self-stimuli_hash-tune_up_or_down">&amp;_tune( $self, \%stimuli_hash, $tune_up_or_down )</h2>

<p>Fine tunes the nerve. This will directly alter the attributes values in <code>$self</code> according to the attributes / dendrites specified in <code>new</code>.</p>

<p>The <code>%stimuli_hash</code> here is the same as the one in the <code>_calculate_output</code> method.</p>

<p><code>%stimuli_hash</code> will be used to determine which dendrite in <code>$self</code> needs to be fine-tuned. As long as the value of any key in <code>%stimuli_hash</code> returns true (1) then that dendrite in <code>$self</code> will be tuned...

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

<p>All the validation methods here have the same parameters as the actual <code>validate</code> method and they all do the same stuff. They are also used in the same way.</p>

<h2 id="take_mock_exam">take_mock_exam (...)</h2>

<h2 id="take_lab_test">take_lab_test (...)</h2>

<h2 id="validate-options">validate ( \%options )</h2>

<p>This method validates the perceptron against another set of data after it has undergone the training process.</p>

<p>This method calculates the output of each row of data and write the result into the predicted column. The data begin written into the new file or the original file will maintain it&#39;s sequence.</p>

<p>Please take note that this method will load all the data of the validation stimuli, so please split your stimuli into multiple files if possible and call this method a few more times.</p>

<p>For <code>%options</code>, the followings are needed unless mentioned:</p>

<dl>

<dt id="stimuli_validate-csv_file">stimuli_validate =&gt; $csv_file</dt>
<dd>

<p>This is the CSV file containing the validation data, make sure that it contains a column with the predicted values as it is needed in the next key mentioned: <code>predicted_column_index</code></p>

</dd>
<dt id="predicted_column_index-column_number">predicted_column_index =&gt; $column_number</dt>
<dd>

<p>This is the index of the column that contains the predicted output values. <code>$index</code> starts from <code>0</code>.</p>

<p>This column will be filled with binary numbers and the full new data will be saved to the file specified in the <code>results_write_to</code> key.</p>

</dd>
<dt id="results_write_to-new_csv_file">results_write_to =&gt; $new_csv_file</dt>
<dd>

<p>Optional.</p>

<p>The default behaviour will write the predicted output back into <code>stimuli_validate</code> ie the original data. The sequence of the data will be maintained.</p>

</dd>
</dl>

<p><i>*This method will call <code>_real_validate_or_test</code> to do the actual work.</i></p>

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

<h2 id="fill_predicted_values-self-stimuli_validate-predicted_index-aoa">&amp;_fill_predicted_values ( $self, $stimuli_validate, $predicted_index, $aoa )</h2>

<p>This is where the filling in of the predicted values takes place. Take note that the parameters naming are the same as the ones used in the <code>validate</code> and <code>test</code> method.</p>

<p>This subroutine should be called in the procedural way.</p>

<h1 id="RESULTS-RELATED-SUBROUTINES-METHODS">RESULTS RELATED SUBROUTINES/METHODS</h1>

<p>This part is related to generating the confusion matrix.</p>

<h2 id="get_exam_results">get_exam_results ( ... )</h2>

<p>The parameters and usage are the same as <code>get_confusion_matrix</code>. See the next method.</p>

<h2 id="get_confusion_matrix-options">get_confusion_matrix ( \%options )</h2>

<p>Returns the confusion matrix in the form of a hash. The hash will contain these keys: <code>true_positive</code>, <code>true_negative</code>, <code>false_positive</code>, <code>false_negative</code>, <code>accuracy</code>, <code>sensitivity</code>...

<p>If you are trying to manipulate the confusion matrix hash or something, take note that all the stats are in percentage (%) in decimal (if any) except the total entries.</p>

<p>For <code>%options</code>, the followings are needed unless mentioned:</p>

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

<p>Calculates and adds the data for the <code>false_discovery_rate</code> key in the confusion matrix hash.</p>

<h2 id="calculate_false_omission_rate-c_matrix_ref">&amp;_calculate_false_omission_rate( $c_matrix_ref )</h2>

<p>Calculates and adds the data for the <code>false_omission_rate</code> key in the confusion matrix hash.</p>

<h2 id="calculate_balanced_accuracy-c_matrix_ref">&amp;_calculate_balanced_accuracy( $c_matrix_ref )</h2>

<p>Calculates and adds the data for the <code>balanced_accuracy</code> key in the confusion matrix hash.</p>

<h2 id="display_exam_results">display_exam_results ( ... )</h2>

<p>The parameters are the same as <code>display_confusion_matrix</code>. See the next method.</p>

<h2 id="display_confusion_matrix-confusion_matrix-labels">display_confusion_matrix ( \%confusion_matrix, \%labels )</h2>

<p>Display the confusion matrix. If <code>%confusion_matrix</code> has <code>more_stats</code> elements, it will display them if they exists. The default elements ie <code>accuracy</code> and <code>sensitivity</code> must be present, while the rest c...

<p><code>%confusion_matrix</code> is the same confusion matrix returned by the <code>get_confusion_matrix</code> method.</p>

<p>For <code>%labels</code>, since <code>0</code>&#39;s and <code>1</code>&#39;s won&#39;t make much sense as the output labels in most cases, therefore, the following keys must be specified:</p>

<dl>

<dt id="zero_as-category_zero_name">zero_as =&gt; $category_zero_name</dt>
<dd>

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

</dl>

<p>Please take note that non-ascii characters ie. non-English alphabets <b>might</b> cause the output to go off :)</p>

<p>For the <code>%labels</code>, there is no need to enter &quot;actual X&quot;, &quot;predicted X&quot; etc. It will be prefixed with <code>A: </code> for actual and <code>P: </code> for the predicted values by default.</p>

<h2 id="build_matrix-c_matrix-labels">&amp;_build_matrix ( $c_matrix, $labels )</h2>

<p>Builds the matrix using <code>Text::Matrix</code> module.</p>

<p><code>$c_matrix</code> and <code>$labels</code> are the same as the ones passed to <code>display_exam_results</code> and <code></code>display_confusion_matrix.</p>

<p>Returns a list <code>( $matrix, $c_matrix )</code> which can directly be passed to <code>_print_extended_matrix</code>.</p>

<h2 id="print_extended_matrix-matrix-c_matrix">&amp;_print_extended_matrix ( $matrix, $c_matrix )</h2>

<p>Extends and outputs the matrix on the screen.</p>

<p><code>$matrix</code> and <code>$c_matrix</code> are the same as returned by <code>&amp;_build_matrix</code>.</p>

<h1 id="NERVE-DATA-RELATED-SUBROUTINES">NERVE DATA RELATED SUBROUTINES</h1>

<p>This part is about saving the data of the nerve. These subroutines can be imported using the <code>:local_data</code> tag.</p>

<p><b>The subroutines are to be called in the procedural way</b>. No checking is done currently.</p>

<p>See <code>PERCEPTRON DATA</code> and <code>KNOWN ISSUES</code> sections for more details on the subroutines in this section.</p>

<h2 id="preserve">preserve ( ... )</h2>

<p>The parameters and usage are the same as <code>save_perceptron</code>. See the next subroutine.</p>

<h2 id="save_perceptron-nerve-nerve_file">save_perceptron ( $nerve, $nerve_file )</h2>

<p>Saves the <code>AI::Perceptron::Simple</code> object into a <code>Storable</code> file. There shouldn&#39;t be a need to call this method manually since after every training process this will be called automatically.</p>

<h2 id="revive">revive (...)</h2>

<p>The parameters and usage are the same as <code>load_perceptron</code>. See the next subroutine.</p>

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

<h2 id="load_perceptron-nerve_file_to_load">load_perceptron ( $nerve_file_to_load )</h2>

<p>Loads the data and turns it into a <code>AI::Perceptron::Simple</code> object as the return value.</p>

<h1 id="NERVE-PORTABILITY-RELATED-SUBROUTINES">NERVE PORTABILITY RELATED SUBROUTINES</h1>

<p>These subroutines can be imported using the <code>:portable_data</code> tag.</p>

<p>The file type currently supported is YAML. Please be careful with the data as you won&#39;t want the nerve data accidentally modified.</p>

<h2 id="preserve_as_yaml">preserve_as_yaml ( ... )</h2>

<p>The parameters and usage are the same as <code>save_perceptron_yaml</code>. See the next subroutine.</p>

<h2 id="save_perceptron_yaml-nerve-yaml_nerve_file">save_perceptron_yaml ( $nerve, $yaml_nerve_file )</h2>

<p>Saves the <code>AI::Perceptron::Simple</code> object into a <code>YAML</code> file.</p>

<h2 id="revive_from_yaml">revive_from_yaml (...)</h2>

<p>The parameters and usage are the same as <code>load_perceptron</code>. See the next subroutine.</p>

docs/AI-Perceptron-Simple-1.04.html  view on Meta::CPAN

<h1 id="KNOWN-ISSUES">KNOWN ISSUES</h1>

<h2 id="Portability-of-Nerve-Data">Portability of Nerve Data</h2>

<p>Take note that the <code>Storable</code> nerve data is not compatible across different versions.</p>

<p>If you really need to send the nerve data to different computers with different versions of <code>Storable</code> module, see the docs of the following subroutines:</p>

<ul>

<li><p><code>&amp;preserve_as_yaml</code> or <code>&amp;save_perceptron_yaml</code> for storing data.</p>

</li>
<li><p><code>&amp;revive_from_yaml</code> or <code>&amp;load_perceptron_yaml</code> for retrieving the data.</p>

</li>
</ul>

<h1 id="AUTHOR">AUTHOR</h1>

<p>Raphael Jong Jun Jie, <code>&lt;ellednera at cpan.org&gt;</code></p>

<h1 id="BUGS">BUGS</h1>

<p>Please report any bugs or feature requests to <code>bug-ai-perceptron-simple at rt.cpan.org</code>, or through the web interface at <a href="https://rt.cpan.org/NoAuth/ReportBug.html?Queue=AI-Perceptron-Simple">https://rt.cpan.org/NoAuth/ReportBug...

<h1 id="SUPPORT">SUPPORT</h1>

<p>You can find documentation for this module with the perldoc command.</p>

<pre><code>    perldoc AI::Perceptron::Simple</code></pre>

<p>You can also look for information at:</p>

<ul>

docs/book_list.csv  view on Meta::CPAN

number,random_num,book_name,brand,predicted,glossy_cover,has_plastic_layer_on_cover,male_present,female_present,total_people_1,total_people_2,total_people_3,total_people_4,total_people_5_n_above,has_flowers,flower_coverage_more_than_half,has_leaves,l...
1,0.58791179017655,恰好你在我身边,0,,1,1,1,1,0,1,0,0,0,0,0,1,1,0,0,0,1,1,0,1,1,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0
2,0.649068484746357,冬天该多好,你若尚在场,0,,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0
3,0.220366332373427,蔷薇少女馆 5,1,,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,0,1,1,1,0,1,1,1,1,1,1,0,0,0,1,0,0,0,0,0,0
4,0.444389989381647,我能听到你的心吗,0,,1,1,1,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0
5,0.006112690516032,花之小镇1 新月卷耳,1,,0,1,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0
6,0.939476914181751,哭泣的琴海,0,,1,1,1,1,0,0,1,0,0,1,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0
7,0.684324925799031,悠莉宠物店 4,1,,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0
8,0.813627896668929,蔷薇色梦幻美瞳,0,,1,1,1,1,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0
9,0.160919980737874,爱的天空下雨了,0,,1,1,1,1,0,1,0,0,0,1,0,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0
10,0.052243285735559,安娜不明国王心,0,,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,0,0,0,1,0,0,0

docs/specifications.t  view on Meta::CPAN

#   [v] remove the return value for "train" method
#   [v] display confusion matrix data to console
#       [v] use Text:Matrix
#
# Version 0.04 / Version 1.0 - completed on 23 AUGUST 2021
#   [v] add synonyms
#       [v] synonyms MUST call actual subroutines and not copy pasting!
#       train: [v] tame  [v] exercise
#       validate: [v] take_mock_exam  [v] take_lab_test
#       test: [v] take_real_exam  [v] work_in_real_world
#       generate_confusion_matrix: [v] get_exam_results
#       display_confusion_matrix: [v] display_exam_results
#       save_perceptron: [v] preserve
#       load_perceptron: [v] revive
#
# Version 1.01
#   [v] fixed currently known issues as much as possible (see 'Changes')
#       - "long size integer" === "byte order not compatible"
#
# Version 1.02
#   [v] minimum perl version changed to 5.8 due to Test::Output
#   [v] YAML (nerve file) for portability
#       [v] make subroutines exportable, the names are too long

docs/specifications.t  view on Meta::CPAN

# Version 1.04
#   [v] fix docs
#   [v] change die to croak for file opening
#   [v] fixed yaml nerve not loading back as an AI::Perceptron::Simple object
#
# Version 1.05
#   -colorise the confusion matrix if option is enabled
#       - sum: green
#       - etc
#   -add public function:
#       -predict result from non-csv input (single row), might be useful when gui is involved
#
# Version 1.06
#   -add a simple tutorial
#   -smart tuning feature: automatically increase/decrease learning_rate in multiples in training stage
#
# Version ?.??
#   ? implement shuffling system into training stage, bulk data processing   
#   ? Data processing: splitting data, k-fold
#   -...
#

docs/specifications.t  view on Meta::CPAN

            #                       );
            # and then check the confusion matrix, if not satisfied, run the loop again :)
$perceptron->validate( $stimuli_validate, $nerve_data_to_read );
$perceptron->test( $stimuli_test ); # loads nerve data from data file, turn into a object, then do the following:
    # reads from csv :
        # validation stimuli
        # testing stimuli
    # both will call the same subroutine to do calculation
    # both will write predicted data into the original data file

# show results ie confusion matrix (TP-true positive, TN-true negative, FP-false positive, FN-false negative)
# this should only be done during validation and testing
$perceptron->generate_confusion_matrix( { 1 => $csv_header_true, 0 => $csv_header_false } );
    # calculates the 4 thingy based on the current data on hand (RAM), don't read from file again, it shouldn't be a problem
        # returns a hash
    # ie it must be used together with validate() and test() to avoid problems
        # ie validate() and test() must be in different scripts, which makes sense
        # unless, create 3 similar objects to do the work in one go
        
# save data of the trained perceptron
$perceptron->save_data( $data_file );

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

=head1 SYNOPSIS

    #!/usr/bin/perl

    use AI::Perceptron::Simple qw(...);

    # create a new nerve / neuron / perceptron
    $nerve = AI::Perceptron::Simple->new( {
        initial_value => $size_of_each_dendrite,
        learning_rate => 0.3, # optional
        threshold => 0.85, # optional
        attribs => \@dendrites,
    } );

    # train
    $nerve->tame( ... );
    $nerve->exercise( ... );
    $nerve->train( $training_data_csv, $expected_column_name, $save_nerve_to );
    # or
    $nerve->train(
        $training_data_csv, $expected_column_name, $save_nerve_to, 
        $show_progress, $identifier); # these two parameters must go together


    # validate
    $nerve->take_lab_test( ... );
    $nerve->take_mock_exam( ... );

    # fill results to original file
    $nerve->validate( { 
        stimuli_validate => $validation_data_csv, 
        predicted_column_index => 4,
     } );
    # or        
    # fill results to a new file
    $nerve->validate( {
        stimuli_validate => $validation_data_csv,
        predicted_column_index => 4,
        results_write_to => $new_csv
    } );


    # test - see "validate" method, same usage
    $nerve->take_real_exam( ... );
    $nerve->work_in_real_world( ... );
    $nerve->test( ... );


    # confusion matrix

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

        zero_as => "bad apples", # cat  milk   green  etc.
        one_as => "good apples", # dog  honey  pink   etc.
    } );


    # saving and loading data of perceptron locally
    # NOTE: nerve data is automatically saved after each trainning process
    use AI::Perceptron::Simple ":local_data";

    my $nerve_file = "apples.nerve";
    preserve( ... );
    save_perceptron( $nerve, $nerve_file );

    # load data of percpetron for use in actual program
    my $apple_nerve = revive( ... );
    my $apple_nerve = load_perceptron( $nerve_file );


    # for portability of nerve data
    use AI::Perceptron::Simple ":portable_data";

    my $yaml_nerve_file = "pearls.yaml";
    preserve_as_yaml ( ... );
    save_perceptron_yaml ( $nerve, $yaml_nerve_file );

    # load nerve data on the other computer
    my $pearl_nerve = revive_from_yaml ( ... );
    my $pearl_nerve = load_perceptron_yaml ( $yaml_nerve_file );


    # processing data
    use AI::Perceptron::Simple ":process_data";
    shuffle_stimuli ( ... )

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN


=back

Most of the stuff are OO.

=cut

use Exporter qw( import );
our @EXPORT_OK = qw( 
    shuffle_data shuffle_stimuli
    preserve save_perceptron revive load_perceptron
    preserve_as_yaml save_perceptron_yaml revive_from_yaml load_perceptron_yaml
);
our %EXPORT_TAGS = ( 
    process_data => [ qw( shuffle_data shuffle_stimuli ) ],
    local_data => [ qw( preserve save_perceptron revive load_perceptron ) ],
    portable_data => [ qw( preserve_as_yaml save_perceptron_yaml revive_from_yaml load_perceptron_yaml ) ],
);

=head1 DESCRIPTION

This module provides methods to build, train, validate and test a perceptron. It can also save the data of the perceptron for future use for any actual AI programs.

This module is also aimed to help newbies grasp hold of the concept of perceptron, training, validation and testing as much as possible. Hence, all the methods and subroutines in this module are decoupled as much as possible so that the actual script...

The implementation here is super basic as it only takes in input of the dendrites and calculate the output. If the output is higher than the threshold, the final result (category) will 
be 1 aka perceptron is activated. If not, then the result will be 0 (not activated).

Depending on how you view or categorize the final result, the perceptron will fine tune itself (aka train) based on the learning rate until the desired result is met. Everything from 
here on is all mathematics and numbers which only makes sense to the computer and not humans anymore.

Whenever the perceptron fine tunes itself, it will increase/decrease all the dendrites that is significant (attributes labelled 1) for each input. This means that even when the 
perceptron successfully fine tunes itself to suite all the data in your file for the first round, the perceptron might still get some of the things wrong for the next round of training. 
Therefore, the perceptron should be trained for as many rounds as possible. The more "confusion" the perceptron is able to correctly handle, the more "mature" the perceptron is. 
No one defines how "mature" it is except the programmer himself/herself :)

=head1 CONVENTIONS USED

Please take note that not all subroutines/method must be used to make things work. All the subroutines and methods are listed out for the sake of writing the documentation. 

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

An array reference containing all the attributes / dendrites names. Yes, give them some names :)

=item learning_rate => $decimal

Optional. The default is C<0.05>.

The learning rate of the perceptron for the fine-tuning process.

This value is usually between 0 and 1. However, it all depends on your combination of numbers for the other options.

=item threshold => $decimal

Optional. The default is C<0.5>

This is the passing rate to determine the neuron output (C<0> or C<1>).

Generally speaking, this value is usually between C<0> and C<1>. However, it all depend on your combination of numbers for the other options.

=back

=cut

sub new {
    my $class = shift;
    
    my $data_ref = shift;
    my %data = %{ $data_ref };
    
    # check keys
    $data{ learning_rate } = LEARNING_RATE if not exists $data{ learning_rate };
    $data{ threshold } = THRESHOLD if not exists $data{ threshold };
    
    #####
    # don't pack this key checking process into a subroutine for now
    # this is also used in &_real_validate_or_test
    my @missing_keys;
    for ( qw( initial_value attribs ) ) {
        push @missing_keys, $_ unless exists $data{ $_ };
    }
    
    croak "Missing keys: @missing_keys" if @missing_keys;
    #####
    
    # continue to process the rest of the data
    my %attributes;
    for ( @{ $data{ attribs } } ) {
        $attributes{ $_ } = $data{ initial_value };
    }
    
    my %processed_data = (
        learning_rate => $data{ learning_rate },
        threshold => $data{ threshold },
        attributes_hash_ref => \%attributes,
    );
    
    bless \%processed_data, $class;
}

=head2 get_attributes

Obtains a hash of all the attributes of the perceptron

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN


sub learning_rate {
    my $self = shift;
    if ( @_ ) {
        $self->{learning_rate} = shift;
    } else {
        $self->{learning_rate}
    }
}

=head2 threshold ( $value )

=head2 threshold

If C<$value> is given, sets the threshold / passing rate to C<$value>. If not, then it returns the passing rate.

=cut

sub threshold {
    my $self = shift;
    if ( @_ ) {
        $self->{ threshold } = shift;
    } else {
        $self->{ threshold };
    }
}

=head1 TRAINING RELATED SUBROUTINES/METHODS

All the training methods here have the same parameters as the two actual C<train> method and they all do the same stuff. They are also used in the same way.

=head2 tame ( ... )

=head2 exercise ( ... )

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

=over 4

=item tuning status

Indicates the nerve was tuned up, down or no tuning needed

=item old sum

The original sum of all C<weightage * input> or C<dendrite_size * binary_input>

=item threshold

The threshold of the nerve

=item new sum

The new sum of all C<weightage * input> after fine-tuning the nerve

=back

If C<$display_stats> is specified ie. set to C<1>, then you B<MUST> specify the C<$identifier>. C<$identifier> is the column / header name that is used to identify a specific row of data in C<$stimuli_train_csv>.

=cut

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

        # print $row->{book_name}, " -> ";
        # print $row->{$expected_output_header} ? "意林\n" : "魅丽优品\n";

        # calculate the output and fine tune parameters if necessary
        while (1) {
            my $output = _calculate_output( $self, $row );
            
            #print "Sum = ", $output, "\n";
            
            # $expected_output_header to be checked together over here
            # if output >= threshold
            #    then category/result aka output is considered 1
            # else output considered 0
            
            # output expected/actual tuning
            #    0       0             -
            #    1       0             down
            #    0       1             up
            #    1       1             -
            if ( ($output >= $self->threshold) and ( $row->{$expected_output_header} eq 0 ) ) {
                _tune( $self, $row, TUNE_DOWN );

                if ( $display_stats ) {
                    print $row->{$identifier}, "\n";
                    print "   -> TUNED DOWN";
                    print "   Old sum = ", $output;
                    print "   Threshold = ", $self->threshold;
                    print "   New Sum = ", _calculate_output( $self, $row ), "\n";                
                }
                
            } elsif ( ($output < $self->threshold) and ( $row->{$expected_output_header} eq 1 ) ) {
                _tune( $self, $row, TUNE_UP );
                
                if ( $display_stats ) {
                    print $row->{$identifier}, "\n";
                    print "   -> TUNED UP";
                    print "   Old sum = ", $output;
                    print "   Threshold = ", $self->threshold;
                    print "   New Sum = ", _calculate_output( $self, $row ), "\n";
                }

            } elsif ( ($output < $self->threshold) and ( $row->{$expected_output_header} eq 0 ) ) {
            
                if ( $display_stats ) {
                    print $row->{$identifier}, "\n";
                    print "   -> NO TUNING NEEDED";
                    print "   Sum = ", _calculate_output( $self, $row );
                    print "   Threshold = ", $self->threshold, "\n";
                }
                
                next ROW;
                
            } elsif ( ($output >= $self->threshold) and ( $row->{$expected_output_header} eq 1 ) ) {
            
                if ( $display_stats ) {
                    print $row->{$identifier}, "\n";
                    print "   -> NO TUNING NEEDED";
                    print "   Sum = ", _calculate_output( $self, $row );
                    print "   Threshold = ", $self->threshold, "\n";
                }
                
                next ROW;
            } #else { print "Something's not right\n'" }
        }
    }

    close $data_fh;
    
    save_perceptron( $self, $save_nerve_to_file ); # this doesn't return anything
    
}

=head2 &_calculate_output( $self, \%stimuli_hash )

Calculates and returns the C<sum(weightage*input)> for each individual row of data. Actually, it justs add up all the existing weight since the C<input> is always 1 for now :)

C<%stimuli_hash> is the actual data to be used for training. It might contain useless columns.

This will get all the avaible dendrites using the C<get_attributes> method and then use all the keys ie. headers to access the corresponding values.

This subroutine should be called in the procedural way for now.

=cut

sub _calculate_output {
    my $self = shift; 
    my $stimuli_hash_ref = shift;
    
    my %dendrites = $self->get_attributes;

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

All the validation methods here have the same parameters as the actual C<validate> method and they all do the same stuff. They are also used in the same way.

=head2 take_mock_exam (...)

=head2 take_lab_test (...)

=head2 validate ( \%options )

This method validates the perceptron against another set of data after it has undergone the training process.

This method calculates the output of each row of data and write the result into the predicted column. The data begin written into the new file or the original file will maintain it's sequence.

Please take note that this method will load all the data of the validation stimuli, so please split your stimuli into multiple files if possible and call this method a few more times.

For C<%options>, the followings are needed unless mentioned:

=over 4

=item stimuli_validate => $csv_file

This is the CSV file containing the validation data, make sure that it contains a column with the predicted values as it is needed in the next key mentioned: C<predicted_column_index>

=item predicted_column_index => $column_number

This is the index of the column that contains the predicted output values. C<$index> starts from C<0>.

This column will be filled with binary numbers and the full new data will be saved to the file specified in the C<results_write_to> key.

=item results_write_to => $new_csv_file

Optional.

The default behaviour will write the predicted output back into C<stimuli_validate> ie the original data. The sequence of the data will be maintained.

=back

I<*This method will call C<_real_validate_or_test> to do the actual work.>

=cut

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

        push @missing_keys, $_ unless exists $data_hash_ref->{ $_ };
    }
    
    croak "Missing keys: @missing_keys" if @missing_keys;
    #####
    
    my $stimuli_validate = $data_hash_ref->{ stimuli_validate };
    my $predicted_index = $data_hash_ref->{ predicted_column_index };
    
    # actual processing starts here
    my $output_file = defined $data_hash_ref->{ results_write_to } 
                        ? $data_hash_ref->{ results_write_to }
                        : $stimuli_validate;
    
    # open for writing results
    my $aoa = csv (in => $stimuli_validate, encoding => ":encoding(utf-8)");
    
    my $attrib_array_ref = shift @$aoa; # 'remove' the header, it's annoying :)

    $aoa = _fill_predicted_values( $self, $stimuli_validate, $predicted_index, $aoa );

    # put back the array of headers before saving file
    unshift @$aoa, $attrib_array_ref;

    print "Saving data to $output_file\n";

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

    my $csv = Text::CSV->new( {auto_diag => 1, binary => 1} );
    
    my $attrib = $csv->getline($data_fh);
    
    $csv->column_names( $attrib );

    # individual row
    my $row = 0;
    while ( my $data = $csv->getline_hr($data_fh) ) {
        
        if ( _calculate_output( $self, $data )  >= $self->threshold ) {
            # write 1 into aoa
            $aoa->[ $row ][ $predicted_index ] = 1;
        } else {
            #write 0 into aoa
            $aoa->[ $row ][ $predicted_index ] = 0;
        }
        
        $row++;
    }
    
    close $data_fh;
    
    $aoa;
}

=head1 RESULTS RELATED SUBROUTINES/METHODS

This part is related to generating the confusion matrix.

=head2 get_exam_results ( ... )

The parameters and usage are the same as C<get_confusion_matrix>. See the next method.

=head2 get_confusion_matrix ( \%options )

Returns the confusion matrix in the form of a hash. The hash will contain these keys: C<true_positive>, C<true_negative>, C<false_positive>, C<false_negative>, C<accuracy>, C<sensitivity>. More stats like C<precision>, C<specificity> and C<F1_Score> ...

If you are trying to manipulate the confusion matrix hash or something, take note that all the stats are in percentage (%) in decimal (if any) except the total entries.

For C<%options>, the followings are needed unless mentioned:

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

=item more_stats => 1

Optional.

Setting it to C<1> will process more stats that are usually not so important eg. C<precision>, C<specificity> and C<F1_Score>

=back

=cut

sub get_exam_results {

    my ( $self, $info ) = @_;
    
    $self->get_confusion_matrix( $info );
}

sub get_confusion_matrix {

    my ( $self, $info ) = @_;

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN


sub _calculate_balanced_accuracy {
    my $c_matrix = shift;
    
    my $numerator = $c_matrix->{ sensitivity } + $c_matrix->{ specificity };
    my $denominator = 2;
    
    $c_matrix->{ balanced_accuracy } = $numerator / $denominator; # numerator already in %
}

=head2 display_exam_results ( ... )

The parameters are the same as C<display_confusion_matrix>. See the next method.

=head2 display_confusion_matrix ( \%confusion_matrix, \%labels ) 

Display the confusion matrix. If C<%confusion_matrix> has C<more_stats> elements, it will display them if they exists. The default elements ie C<accuracy> and C<sensitivity> must be present, while the rest can be absent.

C<%confusion_matrix> is the same confusion matrix returned by the C<get_confusion_matrix> method.

For C<%labels>, since C<0>'s and C<1>'s won't make much sense as the output labels in most cases, therefore, the following keys must be specified:

=over 4

=item zero_as => $category_zero_name

=item one_as => $category_one_name

=back

Please take note that non-ascii characters ie. non-English alphabets B<might> cause the output to go off :)

For the C<%labels>, there is no need to enter "actual X", "predicted X" etc. It will be prefixed with C<A: > for actual and C<P: > for the predicted values by default.

=cut

sub display_exam_results {

    my ( $self, $c_matrix, $labels ) = @_;
    
    $self->display_confusion_matrix( $c_matrix, $labels );
}

sub display_confusion_matrix {
    my ( $self, $c_matrix, $labels ) = @_;
    
    #####

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

    #####
    
    _print_extended_matrix ( _build_matrix( $c_matrix, $labels ) );

}

=head2 &_build_matrix ( $c_matrix, $labels )

Builds the matrix using C<Text::Matrix> module.

C<$c_matrix> and C<$labels> are the same as the ones passed to C<display_exam_results> and C<>display_confusion_matrix.

Returns a list C<( $matrix, $c_matrix )> which can directly be passed to C<_print_extended_matrix>.

=cut

sub _build_matrix {

    my ( $c_matrix, $labels ) = @_;

    my $predicted_columns = [ "P: ".$labels->{ zero_as }, "P: ".$labels->{ one_as }, "Sum" ];

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

}

=head1 NERVE DATA RELATED SUBROUTINES

This part is about saving the data of the nerve. These subroutines can be imported using the C<:local_data> tag.

B<The subroutines are to be called in the procedural way>. No checking is done currently.

See C<PERCEPTRON DATA> and C<KNOWN ISSUES> sections for more details on the subroutines in this section.

=head2 preserve ( ... )

The parameters and usage are the same as C<save_perceptron>. See the next subroutine.

=head2 save_perceptron ( $nerve, $nerve_file )

Saves the C<AI::Perceptron::Simple> object into a C<Storable> file. There shouldn't be a need to call this method manually since after every training 
process this will be called automatically.

=cut

sub preserve {
    save_perceptron( @_ );
}

sub save_perceptron {
    my $self = shift;
    my $nerve_file = shift;
    use Storable;
    store $self, $nerve_file;
    no Storable;
}

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

    
    $loaded_nerve;
}

=head1 NERVE PORTABILITY RELATED SUBROUTINES

These subroutines can be imported using the C<:portable_data> tag.

The file type currently supported is YAML. Please be careful with the data as you won't want the nerve data accidentally modified.

=head2 preserve_as_yaml ( ... )

The parameters and usage are the same as C<save_perceptron_yaml>. See the next subroutine.

=head2 save_perceptron_yaml ( $nerve, $yaml_nerve_file )

Saves the C<AI::Perceptron::Simple> object into a C<YAML> file.

=cut

sub preserve_as_yaml {
    save_perceptron_yaml( @_ );
}

sub save_perceptron_yaml {
    my $self = shift;
    my $nerve_file = shift;
    use YAML;
    YAML::DumpFile( $nerve_file, $self );
    no YAML;
}

lib/AI/Perceptron/Simple.pm  view on Meta::CPAN

=head1 KNOWN ISSUES

=head2 Portability of Nerve Data

Take note that the C<Storable> nerve data is not compatible across different versions.

If you really need to send the nerve data to different computers with different versions of C<Storable> module, see the docs of the following subroutines: 

=over 4

=item * C<&preserve_as_yaml> or C<&save_perceptron_yaml> for storing data.

=item * C<&revive_from_yaml> or C<&load_perceptron_yaml> for retrieving the data.

=back

=head1 AUTHOR

Raphael Jong Jun Jie, C<< <ellednera at cpan.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-ai-perceptron-simple at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=AI-Perceptron-Simple>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc AI::Perceptron::Simple


You can also look for information at:

t/02-creation.t  view on Meta::CPAN

# print AI::Perceptron::Simple::LEARNING_RATE;

# all important parameter test
my $perceptron = AI::Perceptron::Simple->new( {
    initial_value => $initial_value,
    attribs => \@attributes
} );

is( ref $perceptron, $module_name, "Correct object" );

# default learning_rate() threshold()
is( $perceptron->learning_rate, 0.05, "Correct default learning rate -> ".$perceptron->learning_rate );
is( $perceptron->threshold, 0.5, "Correct default passing rate -> ".$perceptron->threshold );

# new learning_rate() threshold()
# direct invocation is seldom used, but might be useful in some ways if there's a loop
$perceptron->learning_rate(0.123);
is( $perceptron->learning_rate, 0.123, "Correct new learning_rate -> ".$perceptron->learning_rate );

$perceptron->threshold(0.4);
is( $perceptron->threshold, 0.4, "Correct new passing rate -> ".$perceptron->threshold );

$perceptron = AI::Perceptron::Simple->new( {
    initial_value => $initial_value,
    learning_rate => 0.3,
    threshold => 0.85,
    attribs => \@attributes
} );
is( $perceptron->learning_rate, 0.3, "Correct custom learning_rate -> ".$perceptron->learning_rate );
is( $perceptron->threshold, 0.85, "Correct custom passing rate -> ".$perceptron->threshold );

# get_attributes()
my %attributes = $perceptron->get_attributes;
for ( @attributes ) {
    ok( $attributes{ $_ }, "Attribute \'$_\' present" );
    is( $attributes{ $_ }, $initial_value, "Correct initial value (".$attributes{$_}.") for  \'$_\'" );
}

# don't try to use Test::Carp, it won't work, it only tests for direct calling of carp and croak etc
subtest "Caught missing mandatory parameters" => sub {
    eval {
        my $no_attribs = AI::Perceptron::Simple->new( { initial_value => $initial_value} );
    };
    like( $@, qr/attribs/, "Caught missing attribs" );
    

t/02-state_portable.t  view on Meta::CPAN


my $total_headers = scalar @attributes;

my $perceptron = AI::Perceptron::Simple->new( {
    initial_value => 0.01,
    attribs => \@attributes
} );

subtest "All data related subroutines found" => sub {
    # this only checks if the subroutines are contained in the package
    ok( AI::Perceptron::Simple->can("preserve_as_yaml"), "&preserve_as_yaml is present" );
    ok( AI::Perceptron::Simple->can("save_perceptron_yaml"), "&save_perceptron_yaml is persent" );

    ok( AI::Perceptron::Simple->can("revive_from_yaml"), "&revive_from_yaml is present" );
    ok( AI::Perceptron::Simple->can("load_perceptron_yaml"), "&load_perceptron_yaml is present" );

};

my $yaml_nerve_file = $FindBin::Bin . "/portable_nerve.yaml";

# save file
save_perceptron_yaml( $perceptron, $yaml_nerve_file );
ok( -e $yaml_nerve_file, "Found the YAML perceptron." );
# load and check
ok( my $transfered_nerve = load_perceptron_yaml( $yaml_nerve_file ), "&loaded_perceptron_from_YAML" );

is_deeply( $transfered_nerve, $perceptron, "&load_perceptron_yaml - correct data after loading" );
is ( ref ($transfered_nerve), "AI::Perceptron::Simple", "Loaded back as a blessed object" );

# test synonyms
AI::Perceptron::Simple::preserve_as_yaml( $perceptron, $yaml_nerve_file );
ok( -e $yaml_nerve_file, "Synonym - Found the YAML perceptron." );

ok( $transfered_nerve = AI::Perceptron::Simple::revive_from_yaml( $yaml_nerve_file ), "&revive_from_yaml is working correctly" );

is_deeply( $transfered_nerve, $perceptron, "&revive_from_yaml - correct data after loading" );
is ( ref ($transfered_nerve), "AI::Perceptron::Simple", "Loaded back as a blessed object" );

done_testing();

# besiyata d'shmaya

t/02-state_synonyms.t  view on Meta::CPAN

use warnings;
use Test::More;

use AI::Perceptron::Simple;

use FindBin;
use constant MODULE_NAME => "AI::Perceptron::Simple";

# 36 headers
my @attributes = qw ( 
    glossy_cover	has_plastic_layer_on_cover	male_present	female_present	total_people_1	total_people_2	total_people_3
	total_people_4	total_people_5_n_above	has_flowers	flower_coverage_more_than_half	has_leaves	leaves_coverage_more_than_half	has_trees
	trees_coverage_more_than_half	has_other_living_things	has_fancy_stuff	has_obvious_inanimate_objects	red_shades	blue_shades	yellow_shades
	orange_shades	green_shades	purple_shades	brown_shades	black_shades	overall_red_dominant	overall_green_dominant
	overall_yellow_dominant	overall_pink_dominant	overall_purple_dominant	overall_orange_dominant	overall_blue_dominant	overall_brown_dominant
	overall_black_dominant	overall_white_dominant );

my $total_headers = scalar @attributes;

my $perceptron = AI::Perceptron::Simple->new( {
    initial_value => 0.01,
    attribs => \@attributes
} );

ok( AI::Perceptron::Simple->can("preserve"), "&preserve is persent" );
ok( AI::Perceptron::Simple->can("revive"), "&revive is present" );

my $nerve_file = $FindBin::Bin . "/perceptron_state_synonyms.nerve";
ok( AI::Perceptron::Simple::preserve( $perceptron, $nerve_file ), "preserve is working good so far" );
ok( -e $nerve_file, "Found the perceptron file" );

ok( AI::Perceptron::Simple::revive( $nerve_file ), "Perceptron loaded" );
my $loaded_perceptron = AI::Perceptron::Simple::revive( $nerve_file );
is( ref $loaded_perceptron, MODULE_NAME, "Correct class after loading" );

done_testing();

# besiyata d'shmaya

t/04-train.t  view on Meta::CPAN

# pwd is the actual .pm module in blib
# ie. My-Perceptron/blib/lib/My/Perceptron.pm
use FindBin;
use constant TRAINING_DATA => $FindBin::Bin . "/book_list_train.csv";
use constant MODULE_NAME => "AI::Perceptron::Simple";
use constant WANT_STATS => 1;
use constant IDENTIFIER => "book_name";

# 36 headers
my @attributes = qw ( 
    glossy_cover	has_plastic_layer_on_cover	male_present	female_present	total_people_1	total_people_2	total_people_3
	total_people_4	total_people_5_n_above	has_flowers	flower_coverage_more_than_half	has_leaves	leaves_coverage_more_than_half	has_trees
	trees_coverage_more_than_half	has_other_living_things	has_fancy_stuff	has_obvious_inanimate_objects	red_shades	blue_shades	yellow_shades
	orange_shades	green_shades	purple_shades	brown_shades	black_shades	overall_red_dominant	overall_green_dominant
	overall_yellow_dominant	overall_pink_dominant	overall_purple_dominant	overall_orange_dominant	overall_blue_dominant	overall_brown_dominant
	overall_black_dominant	overall_white_dominant );

my $total_headers = scalar @attributes;

my $perceptron = AI::Perceptron::Simple->new( {
    initial_value => 0.01,

t/04-train.t  view on Meta::CPAN

is ( $@, "", "No problem with \'train\' method (verbose) so far" );
}

ok ( $perceptron->train( TRAINING_DATA, "brand", $nerve_file), "No problem with \'train\' method (non-verbose) so far" );

# no longer returns the file anymore since v0.03
# is ( $perceptron->train( TRAINING_DATA, "brand", $nerve_file), $nerve_file, "\'train\' method returns the correct value" );

subtest "Data related subroutine found" => sub {
    ok( AI::Perceptron::Simple->can("save_perceptron"), "&save_perceptron is persent" );
    ok( AI::Perceptron::Simple->can("load_perceptron"), "&loaded_perceptron is present" );
};


ok( save_perceptron( $perceptron, $nerve_file ), "save_perceptron is working good so far" );
ok( -e $nerve_file, "Found the perceptron file" );

ok( load_perceptron( $nerve_file ), "Perceptron loaded" );
my $loaded_perceptron = load_perceptron( $nerve_file );
is( ref $loaded_perceptron, MODULE_NAME, "Correct class after loading" );

t/04-train_synonyms_exercise.t  view on Meta::CPAN

use AI::Perceptron::Simple;

use FindBin;
use constant TRAINING_DATA => $FindBin::Bin . "/book_list_train.csv";
use constant MODULE_NAME => "AI::Perceptron::Simple";
use constant WANT_STATS => 1;
use constant IDENTIFIER => "book_name";

# 36 headers
my @attributes = qw ( 
    glossy_cover	has_plastic_layer_on_cover	male_present	female_present	total_people_1	total_people_2	total_people_3
	total_people_4	total_people_5_n_above	has_flowers	flower_coverage_more_than_half	has_leaves	leaves_coverage_more_than_half	has_trees
	trees_coverage_more_than_half	has_other_living_things	has_fancy_stuff	has_obvious_inanimate_objects	red_shades	blue_shades	yellow_shades
	orange_shades	green_shades	purple_shades	brown_shades	black_shades	overall_red_dominant	overall_green_dominant
	overall_yellow_dominant	overall_pink_dominant	overall_purple_dominant	overall_orange_dominant	overall_blue_dominant	overall_brown_dominant
	overall_black_dominant	overall_white_dominant );

my $total_headers = scalar @attributes;

my $perceptron = AI::Perceptron::Simple->new( {
    initial_value => 0.01,

t/04-train_synonyms_exercise.t  view on Meta::CPAN

eval { $perceptron->train( TRAINING_DATA, "brand", $nerve_file, WANT_STATS, IDENTIFIER) };
is ( $@, "", "No problem with \'train\' method (verbose) so far" );
}

ok ( $perceptron->train( TRAINING_DATA, "brand", $nerve_file), "No problem with \'train\' method (non-verbose) so far" );

# no longer returns the file anymore since v0.03
# is ( $perceptron->train( TRAINING_DATA, "brand", $nerve_file), $nerve_file, "\'train\' method returns the correct value" );

ok( AI::Perceptron::Simple->can("save_perceptron"), "&save_perceptron is persent" );
ok( AI::Perceptron::Simple->can("load_perceptron"), "&loaded_perceptron is present" );

ok( AI::Perceptron::Simple::save_perceptron( $perceptron, $nerve_file ), "save_perceptron is working good so far" );
ok( -e $nerve_file, "Found the perceptron file" );

ok( AI::Perceptron::Simple::load_perceptron( $nerve_file ), "Perceptron loaded" );
my $loaded_perceptron = AI::Perceptron::Simple::load_perceptron( $nerve_file );
is( ref $loaded_perceptron, MODULE_NAME, "Correct class after loading" );

done_testing();

t/04-train_synonyms_tame.t  view on Meta::CPAN

use AI::Perceptron::Simple;

use FindBin;
use constant TRAINING_DATA => $FindBin::Bin . "/book_list_train.csv";
use constant MODULE_NAME => "AI::Perceptron::Simple";
use constant WANT_STATS => 1;
use constant IDENTIFIER => "book_name";

# 36 headers
my @attributes = qw ( 
    glossy_cover	has_plastic_layer_on_cover	male_present	female_present	total_people_1	total_people_2	total_people_3
	total_people_4	total_people_5_n_above	has_flowers	flower_coverage_more_than_half	has_leaves	leaves_coverage_more_than_half	has_trees
	trees_coverage_more_than_half	has_other_living_things	has_fancy_stuff	has_obvious_inanimate_objects	red_shades	blue_shades	yellow_shades
	orange_shades	green_shades	purple_shades	brown_shades	black_shades	overall_red_dominant	overall_green_dominant
	overall_yellow_dominant	overall_pink_dominant	overall_purple_dominant	overall_orange_dominant	overall_blue_dominant	overall_brown_dominant
	overall_black_dominant	overall_white_dominant );

my $total_headers = scalar @attributes;

my $perceptron = AI::Perceptron::Simple->new( {
    initial_value => 0.01,

t/04-train_synonyms_tame.t  view on Meta::CPAN

eval { $perceptron->train( TRAINING_DATA, "brand", $nerve_file, WANT_STATS, IDENTIFIER) };
is ( $@, "", "No problem with \'train\' method (verbose) so far" );
}

ok ( $perceptron->train( TRAINING_DATA, "brand", $nerve_file), "No problem with \'train\' method (non-verbose) so far" );

# no longer returns the file anymore since v0.03
# is ( $perceptron->train( TRAINING_DATA, "brand", $nerve_file), $nerve_file, "\'train\' method returns the correct value" );

ok( AI::Perceptron::Simple->can("save_perceptron"), "&save_perceptron is persent" );
ok( AI::Perceptron::Simple->can("load_perceptron"), "&loaded_perceptron is present" );

ok( AI::Perceptron::Simple::save_perceptron( $perceptron, $nerve_file ), "save_perceptron is working good so far" );
ok( -e $nerve_file, "Found the perceptron file" );

ok( AI::Perceptron::Simple::load_perceptron( $nerve_file ), "Perceptron loaded" );
my $loaded_perceptron = AI::Perceptron::Simple::load_perceptron( $nerve_file );
is( ref $loaded_perceptron, MODULE_NAME, "Correct class after loading" );

done_testing();

t/06-validate.t  view on Meta::CPAN

use constant VALIDATION_DATA => $FindBin::Bin . "/book_list_validate.csv";


use constant VALIDATION_DATA_OUTPUT_FILE => $FindBin::Bin . "/book_list_validate-filled.csv";
use constant MODULE_NAME => "AI::Perceptron::Simple";
use constant WANT_STATS => 1;
use constant IDENTIFIER => "book_name";

# 36 headers
my @attributes = qw ( 
    glossy_cover	has_plastic_layer_on_cover	male_present	female_present	total_people_1	total_people_2	total_people_3
	total_people_4	total_people_5_n_above	has_flowers	flower_coverage_more_than_half	has_leaves	leaves_coverage_more_than_half	has_trees
	trees_coverage_more_than_half	has_other_living_things	has_fancy_stuff	has_obvious_inanimate_objects	red_shades	blue_shades	yellow_shades
	orange_shades	green_shades	purple_shades	brown_shades	black_shades	overall_red_dominant	overall_green_dominant
	overall_yellow_dominant	overall_pink_dominant	overall_purple_dominant	overall_orange_dominant	overall_blue_dominant	overall_brown_dominant
	overall_black_dominant	overall_white_dominant );

my $total_headers = scalar @attributes;

my $perceptron = AI::Perceptron::Simple->new( {
    initial_value => 0.01,
    learning_rate => 0.001,
    threshold => 0.8,
    attribs => \@attributes
} );

my $nerve_file = $FindBin::Bin . "/perceptron_1.nerve";

for ( 0..5 ) {
    print "Round $_\n";
    $perceptron->train( TRAINING_DATA, "brand", $nerve_file, WANT_STATS, IDENTIFIER );
    print "\n";
}

t/06-validate.t  view on Meta::CPAN

                predicted_column_index => 4,
            } ), 
            "Validate succedded!" );
} qr/book_list_validate\.csv/, "Correct output for validate when saving file";

# with new output file
stdout_like {
    ok ( $perceptron->validate( {
            stimuli_validate => VALIDATION_DATA,
            predicted_column_index => 4,
            results_write_to => VALIDATION_DATA_OUTPUT_FILE
        } ), 
        "Validate succedded!" );

} qr/book_list_validate\-filled\.csv/, "Correct output for validate when saving to NEW file";

ok( -e VALIDATION_DATA_OUTPUT_FILE, "New validation file found" );
isnt( -s VALIDATION_DATA_OUTPUT_FILE, 0, "New output file is not empty" );

done_testing;
# besiyata d'shmaya

t/06-validate_synonyms_lab.t  view on Meta::CPAN

use constant VALIDATION_DATA => $FindBin::Bin . "/book_list_validate.csv";


use constant VALIDATION_DATA_OUTPUT_FILE => $FindBin::Bin . "/book_list_validate_lab-filled.csv";
use constant MODULE_NAME => "AI::Perceptron::Simple";
use constant WANT_STATS => 1;
use constant IDENTIFIER => "book_name";

# 36 headers
my @attributes = qw ( 
    glossy_cover	has_plastic_layer_on_cover	male_present	female_present	total_people_1	total_people_2	total_people_3
	total_people_4	total_people_5_n_above	has_flowers	flower_coverage_more_than_half	has_leaves	leaves_coverage_more_than_half	has_trees
	trees_coverage_more_than_half	has_other_living_things	has_fancy_stuff	has_obvious_inanimate_objects	red_shades	blue_shades	yellow_shades
	orange_shades	green_shades	purple_shades	brown_shades	black_shades	overall_red_dominant	overall_green_dominant
	overall_yellow_dominant	overall_pink_dominant	overall_purple_dominant	overall_orange_dominant	overall_blue_dominant	overall_brown_dominant
	overall_black_dominant	overall_white_dominant );

my $total_headers = scalar @attributes;

my $perceptron = AI::Perceptron::Simple->new( {
    initial_value => 0.01,
    learning_rate => 0.001,
    threshold => 0.8,
    attribs => \@attributes
} );

my $nerve_file = $FindBin::Bin . "/perceptron_1.nerve";

for ( 0..5 ) {
    print "Round $_\n";
    $perceptron->train( TRAINING_DATA, "brand", $nerve_file, WANT_STATS, IDENTIFIER );
    print "\n";
}

t/06-validate_synonyms_lab.t  view on Meta::CPAN

                predicted_column_index => 4,
            } ), 
            "Validate succedded!" );
} qr/book_list_validate\.csv/, "Correct output for take_lab_test when saving file";

# with new output file
stdout_like {
    ok ( $perceptron->take_lab_test( {
            stimuli_validate => VALIDATION_DATA,
            predicted_column_index => 4,
            results_write_to => VALIDATION_DATA_OUTPUT_FILE
        } ), 
        "Validate succedded!" );

} qr/book_list_validate_lab\-filled\.csv/, "Correct output for take_lab_test when saving to NEW file";

ok( -e VALIDATION_DATA_OUTPUT_FILE, "New validation file found" );
isnt( -s VALIDATION_DATA_OUTPUT_FILE, 0, "New output file is not empty" );

done_testing;
# besiyata d'shmaya

t/06-validate_synonyms_mock.t  view on Meta::CPAN

use constant VALIDATION_DATA => $FindBin::Bin . "/book_list_validate.csv";


use constant VALIDATION_DATA_OUTPUT_FILE => $FindBin::Bin . "/book_list_validate_mock-filled.csv";
use constant MODULE_NAME => "AI::Perceptron::Simple";
use constant WANT_STATS => 1;
use constant IDENTIFIER => "book_name";

# 36 headers
my @attributes = qw ( 
    glossy_cover	has_plastic_layer_on_cover	male_present	female_present	total_people_1	total_people_2	total_people_3
	total_people_4	total_people_5_n_above	has_flowers	flower_coverage_more_than_half	has_leaves	leaves_coverage_more_than_half	has_trees
	trees_coverage_more_than_half	has_other_living_things	has_fancy_stuff	has_obvious_inanimate_objects	red_shades	blue_shades	yellow_shades
	orange_shades	green_shades	purple_shades	brown_shades	black_shades	overall_red_dominant	overall_green_dominant
	overall_yellow_dominant	overall_pink_dominant	overall_purple_dominant	overall_orange_dominant	overall_blue_dominant	overall_brown_dominant
	overall_black_dominant	overall_white_dominant );

my $total_headers = scalar @attributes;

my $perceptron = AI::Perceptron::Simple->new( {
    initial_value => 0.01,
    learning_rate => 0.001,
    threshold => 0.8,
    attribs => \@attributes
} );

my $nerve_file = $FindBin::Bin . "/perceptron_1.nerve";

for ( 0..5 ) {
    print "Round $_\n";
    $perceptron->train( TRAINING_DATA, "brand", $nerve_file, WANT_STATS, IDENTIFIER );
    print "\n";
}

t/06-validate_synonyms_mock.t  view on Meta::CPAN

                predicted_column_index => 4,
            } ), 
            "Validate succedded!" );
} qr/book_list_validate\.csv/, "Correct output for take_mock_exam when saving file";

# with new output file
stdout_like {
    ok ( $perceptron->take_mock_exam( {
            stimuli_validate => VALIDATION_DATA,
            predicted_column_index => 4,
            results_write_to => VALIDATION_DATA_OUTPUT_FILE
        } ), 
        "Validate succedded!" );

} qr/book_list_validate_mock\-filled\.csv/, "Correct output for take_mock_exam when saving to NEW file";

ok( -e VALIDATION_DATA_OUTPUT_FILE, "New validation file found" );
isnt( -s VALIDATION_DATA_OUTPUT_FILE, 0, "New output file is not empty" );

done_testing;
# besiyata d'shmaya

t/08-confusion_matrix.t  view on Meta::CPAN


    like ( $@, qr/Something\'s wrong\!/, "Croaked! Found non-binary values in file");
}

my $piece;
my @pieces = ('A: ', 'P: ', 'actual', 'predicted', 'entries', 'Accuracy', 'Sensitivity', 'MP520', 'Yi Lin');

for $piece ( @pieces ) {
    stdout_like {
    
        ok ( $perceptron->display_exam_results( \%c_matrix, { zero_as => "MP520", one_as => "Yi Lin"  } ),
            "display_exam_results is working");
        
    } qr /(?:$piece)/, "$piece displayed";

}

{
    local $@;
    
    eval {
        $perceptron->display_confusion_matrix( \%c_matrix, { one_as => "Yi Lin" } );
    };
    
    like ( $@, qr/zero_as/, "Missing keys found: zero_as!" );
    unlike ( $@, qr/one_as/, "Confirmed one_as is present but not zero_as" );
}

{
    local $@;
    
    eval {
        $perceptron->display_confusion_matrix( \%c_matrix, { zero_as => "MP520" } );
    };
    
    like ( $@, qr/one_as/, "Missing keys found: one_as!" );
    unlike ( $@, qr/zero_as/, "Confirmed zero_as is present but not one_as" );
}

{
    local $@;
    
    eval {
        $perceptron->display_confusion_matrix( \%c_matrix );
    };
    
    like ( $@, qr/zero_as one_as/, "Both keys not found" );

t/08-confusion_matrix.t  view on Meta::CPAN

    like ( $c_matrix_more_stats{ false_omission_rate }, qr/42.85/, "False Omission Rate seems correct to me" );
    is ( $c_matrix_more_stats{ balanced_accuracy }, 60, "Balanced Acuracy seems correct to me" );


    my $piece;
    my @pieces = ('A: ', 'P: ', 'actual', 'predicted', 'entries', 'Accuracy', 'Sensitivity', 'MP520', 'Yi Lin', "Precision", "Specificity", "F1 Score", "Negative Predicted Value", "False Negative Rate", "False Positive Rate", "False Discovery Rate", ...

    for $piece ( @pieces ) {
        stdout_like {
        
            ok ( $perceptron->display_exam_results( \%c_matrix_more_stats, { zero_as => "MP520", one_as => "Yi Lin"  } ),
                "display_exam_results is working");
            
        } qr /(?:$piece)/, "$piece displayed";

    }
    $perceptron->display_exam_results( \%c_matrix_more_stats, { 
        zero_as => "MP520", 
        one_as => "Yi Lin"  } );
};

done_testing;

# besiyata d'shmaya



t/08-confusion_matrix_synonyms.t  view on Meta::CPAN

use Text::Matrix;

use FindBin;

use constant TEST_FILE => $FindBin::Bin . "/book_list_test-filled.csv";
use constant NON_BINARY_FILE => $FindBin::Bin . "/book_list_test-filled-non-binary.csv";

my $nerve_file = $FindBin::Bin . "/perceptron_1.nerve";
my $perceptron = AI::Perceptron::Simple::load_perceptron( $nerve_file );

ok ( my %c_matrix = $perceptron->get_exam_results( { 
        full_data_file => TEST_FILE, 
        actual_output_header => "brand",
        predicted_output_header => "predicted",
    } ), 
    "get_exam_results method is working");

is ( ref \%c_matrix, ref {}, "Confusion matrix in correct data structure" );

is ( $c_matrix{ true_positive }, 2, "Correct true_positive" );
is ( $c_matrix{ true_negative }, 4, "Correct true_negative" );
is ( $c_matrix{ false_positive }, 1, "Correct false_positive" );
is ( $c_matrix{ false_negative }, 3, "Correct false_negative" );

is ( $c_matrix{ total_entries }, 10, "Total entries is correct" );
ok ( AI::Perceptron::Simple::_calculate_total_entries( \%c_matrix ), 

t/08-confusion_matrix_synonyms.t  view on Meta::CPAN

like ( $c_matrix{ accuracy }, qr/60/, "'illegal' calculation of accuracy seems correct to me" );

like ( $c_matrix{ sensitivity }, qr/40/, "Accuracy seems correct to me" );
ok ( AI::Perceptron::Simple::_calculate_sensitivity( \%c_matrix ), 
    "Testing the 'untestable' &_calculate_sensitivity" );
like ( $c_matrix{ accuracy }, qr/60/, "'illegal' calculation of sensitivity seems correct to me" );

{
    local $@;
    eval {
        $perceptron->get_exam_results( { 
            full_data_file => NON_BINARY_FILE,
            actual_output_header => "brand",
            predicted_output_header => "predicted",
        } );
    };

    like ( $@, qr/Something\'s wrong\!/, "Croaked! Found non-binary values in file");
}


my $piece;
my @pieces = ('A: ', 'P: ', 'actual', 'predicted', 'entries', 'Accuracy', 'Sensitivity', 'MP520', 'Yi Lin');

for $piece ( @pieces ) {
    stdout_like {
    
        ok ( $perceptron->display_exam_results( \%c_matrix, { zero_as => "MP520", one_as => "Yi Lin"  } ),
            "display_exam_results is working");
        
    } qr /(?:$piece)/, "$piece displayed";

}


{
    local $@;
    
    eval {
        $perceptron->display_exam_results( \%c_matrix, { one_as => "Yi Lin" } );
    };
    
    like ( $@, qr/zero_as/, "Missing keys found: zero_as!" );
    unlike ( $@, qr/one_as/, "Confirmed one_as is present but not zero_as" );
}

{
    local $@;
    
    eval {
        $perceptron->display_exam_results( \%c_matrix, { zero_as => "MP520" } );
    };
    
    like ( $@, qr/one_as/, "Missing keys found: one_as!" );
    unlike ( $@, qr/zero_as/, "Confirmed zero_as is present but not one_as" );
}

{
    local $@;
    
    eval {
        $perceptron->display_exam_results( \%c_matrix );
    };
    
    like ( $@, qr/zero_as one_as/, "Both keys not found" );
}
# more_stats enabled

subtest "More stats" => sub {

    my %c_matrix_more_stats = $perceptron->get_confusion_matrix( { 
            full_data_file => TEST_FILE, 

t/08-confusion_matrix_synonyms.t  view on Meta::CPAN

    like ( $c_matrix_more_stats{ false_omission_rate }, qr/42.85/, "False Omission Rate seems correct to me" );
    is ( $c_matrix_more_stats{ balanced_accuracy }, 60, "Balanced Acuracy seems correct to me" );


    my $piece;
    my @pieces = ('A: ', 'P: ', 'actual', 'predicted', 'entries', 'Accuracy', 'Sensitivity', 'MP520', 'Yi Lin', "Precision", "Specificity", "F1 Score", "Negative Predicted Value", "False Negative Rate", "False Positive Rate", "False Discovery Rate", ...

    for $piece ( @pieces ) {
        stdout_like {
        
            ok ( $perceptron->display_exam_results( \%c_matrix_more_stats, { zero_as => "MP520", one_as => "Yi Lin"  } ),
                "display_exam_results is working");
            
        } qr /(?:$piece)/, "$piece displayed";

    }
    $perceptron->display_exam_results( \%c_matrix_more_stats, { 
        zero_as => "MP520", 
        one_as => "Yi Lin"  } );
};
done_testing;

# besiyata d'shmaya




t/10-test.t  view on Meta::CPAN

        "Testing stage succedded!" );

} qr/book_list_test\.csv/, "Correct output for testing when saving back to original file";


# with new output file
stdout_like {
    ok ( $mature_nerve->test( {
            stimuli_validate => TEST_DATA,
            predicted_column_index => 4,
            results_write_to => TEST_DATA_NEW_FILE
        } ), 
        "Testing stage succedded!" );

} qr/book_list_test\-filled\.csv/, "Correct output for testing when saving to NEW file";

ok( -e TEST_DATA_NEW_FILE, "New testing file found" );
isnt( -s TEST_DATA_NEW_FILE, 0, "New output file is not empty" );

done_testing;
# besiyata d'shmaya

t/10-test_synonyms_exam.t  view on Meta::CPAN

        "Testing stage succedded!" );

} qr/book_list_test\.csv/, "Correct output for testing when saving back to original file";


# with new output file
stdout_like {
    ok ( $mature_nerve->take_real_exam( {
            stimuli_validate => TEST_DATA,
            predicted_column_index => 4,
            results_write_to => TEST_DATA_NEW_FILE
        } ), 
        "Testing stage succedded!" );

} qr/book_list_test_exam\-filled\.csv/, "Correct output for testing when saving to NEW file";

ok( -e TEST_DATA_NEW_FILE, "New testing file found" );
isnt( -s TEST_DATA_NEW_FILE, 0, "New output file is not empty" );

done_testing;
# besiyata d'shmaya

t/10-test_synonyms_work.t  view on Meta::CPAN

        "Testing stage succedded!" );

} qr/book_list_test\.csv/, "Correct output for testing when saving back to original file";


# with new output file
stdout_like {
    ok ( $mature_nerve->work_in_real_world( {
            stimuli_validate => TEST_DATA,
            predicted_column_index => 4,
            results_write_to => TEST_DATA_NEW_FILE
        } ), 
        "Testing stage succedded!" );

} qr/book_list_test_work\-filled\.csv/, "Correct output for testing when saving to NEW file";

ok( -e TEST_DATA_NEW_FILE, "New testing file found" );
isnt( -s TEST_DATA_NEW_FILE, 0, "New output file is not empty" );

done_testing;
# besiyata d'shmaya

t/12-shuffle_data.t  view on Meta::CPAN


{
local $@;
eval { shuffle_data };
like( $@, qr/^Please specify/, "Croaked at invocation with any arguements" )
}

{
local $@;
eval { shuffle_data($original_stimuli) };
like( $@, qr/output files/, "Croaked when new file names not present" )
}

shuffle_data( $original_stimuli => $shuffled_data_1, $shuffled_data_2, $shuffled_data_3 );

stdout_like {
    shuffle_data( ORIGINAL_STIMULI, $shuffled_data_1, $shuffled_data_2, $shuffled_data_3 );
} qr/^Saved/, "Correct output after saving file";


ok( -e $shuffled_data_1, "Found the first shuffled file" );

t/12-shuffle_data_synonym.t  view on Meta::CPAN


{
local $@;
eval { shuffle_stimuli };
like( $@, qr/^Please specify/, "Croaked at invocation with any arguements" )
}

{
local $@;
eval { shuffle_stimuli($original_stimuli) };
like( $@, qr/output files/, "Croaked when new file names not present" )
}

shuffle_stimuli( $original_stimuli => $shuffled_data_1, $shuffled_data_2, $shuffled_data_3 );

stdout_like {
    shuffle_stimuli( ORIGINAL_STIMULI, $shuffled_data_1, $shuffled_data_2, $shuffled_data_3 );
} qr/^Saved/, "Correct output after saving file";


ok( -e $shuffled_data_1, "Found the first shuffled file" );

t/book_list_test-filled-non-binary.csv  view on Meta::CPAN

number,random_num,book_name,brand,predicted,glossy_cover,has_plastic_layer_on_cover,male_present,female_present,total_people_1,total_people_2,total_people_3,total_people_4,total_people_5_n_above,has_flowers,flower_coverage_more_than_half,has_leaves,l...
1,0.38530014464677,蔷薇少女馆 5,1,1,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,0,1,1,1,0,1,1,1,1,1,1,0,0,0,1,0,0,0,0,0,0
2,0.88386784655411,恰好你在我身边,5,0,1,1,1,1,0,1,0,0,0,0,0,1,1,0,0,0,1,1,0,1,1,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0
3,0.482162411665931,蝴蝶飞过旧时光,1,1,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0
4,0.234902885736616,花之小镇1 新月卷耳,1,1,0,1,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0
5,0.183325343579563,冬天该多好,你若尚在场,0,9,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0

t/book_list_test-filled.csv  view on Meta::CPAN

number,random_num,book_name,brand,predicted,glossy_cover,has_plastic_layer_on_cover,male_present,female_present,total_people_1,total_people_2,total_people_3,total_people_4,total_people_5_n_above,has_flowers,flower_coverage_more_than_half,has_leaves,l...
1,0.417522248963749,"悠莉宠物店 4",1,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0
2,0.224038175730797,"蔷薇色梦幻美瞳",0,0,1,1,1,1,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0
3,0.323147737886061,"爱的天空下雨了",0,0,1,1,1,1,0,1,0,0,0,1,0,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0
4,0.580112146332982,"安娜不明国王心",0,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,0,0,0,1,0,0,0
5,0.84919477537331,"风走过森林",1,1,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,1,0,0
6,0.516378068835505,"琥珀青春",1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1
7,0.264807238500381,"蔷薇少女馆 1",1,1,0,1,0,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0
8,0.136196854429181,"萌淑女驾到之美女训练营",1,0,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0
9,0.755023161812434,"千零一夜美梦恋",0,0,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0
10,0.242905525403648,"我能听到你的心吗",0,1,1,1,1,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0

t/book_list_test.csv  view on Meta::CPAN

number,random_num,book_name,brand,predicted,glossy_cover,has_plastic_layer_on_cover,male_present,female_present,total_people_1,total_people_2,total_people_3,total_people_4,total_people_5_n_above,has_flowers,flower_coverage_more_than_half,has_leaves,l...
1,0.417522248963749,"悠莉宠物店 4",1,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0
2,0.224038175730797,"蔷薇色梦幻美瞳",0,0,1,1,1,1,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0
3,0.323147737886061,"爱的天空下雨了",0,0,1,1,1,1,0,1,0,0,0,1,0,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0
4,0.580112146332982,"安娜不明国王心",0,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,0,0,0,1,0,0,0
5,0.84919477537331,"风走过森林",1,1,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,1,0,0
6,0.516378068835505,"琥珀青春",1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1
7,0.264807238500381,"蔷薇少女馆 1",1,1,0,1,0,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0
8,0.136196854429181,"萌淑女驾到之美女训练营",1,0,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0
9,0.755023161812434,"千零一夜美梦恋",0,0,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0
10,0.242905525403648,"我能听到你的心吗",0,1,1,1,1,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0

t/book_list_test_exam-filled.csv  view on Meta::CPAN

number,random_num,book_name,brand,predicted,glossy_cover,has_plastic_layer_on_cover,male_present,female_present,total_people_1,total_people_2,total_people_3,total_people_4,total_people_5_n_above,has_flowers,flower_coverage_more_than_half,has_leaves,l...
1,0.417522248963749,"悠莉宠物店 4",1,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0
2,0.224038175730797,"蔷薇色梦幻美瞳",0,0,1,1,1,1,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0
3,0.323147737886061,"爱的天空下雨了",0,0,1,1,1,1,0,1,0,0,0,1,0,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0
4,0.580112146332982,"安娜不明国王心",0,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,0,0,0,1,0,0,0
5,0.84919477537331,"风走过森林",1,1,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,1,0,0
6,0.516378068835505,"琥珀青春",1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1
7,0.264807238500381,"蔷薇少女馆 1",1,1,0,1,0,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0
8,0.136196854429181,"萌淑女驾到之美女训练营",1,0,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0
9,0.755023161812434,"千零一夜美梦恋",0,0,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0
10,0.242905525403648,"我能听到你的心吗",0,1,1,1,1,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0

t/book_list_test_work-filled.csv  view on Meta::CPAN

number,random_num,book_name,brand,predicted,glossy_cover,has_plastic_layer_on_cover,male_present,female_present,total_people_1,total_people_2,total_people_3,total_people_4,total_people_5_n_above,has_flowers,flower_coverage_more_than_half,has_leaves,l...
1,0.417522248963749,"悠莉宠物店 4",1,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0
2,0.224038175730797,"蔷薇色梦幻美瞳",0,0,1,1,1,1,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0
3,0.323147737886061,"爱的天空下雨了",0,0,1,1,1,1,0,1,0,0,0,1,0,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0
4,0.580112146332982,"安娜不明国王心",0,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,0,0,0,1,0,0,0
5,0.84919477537331,"风走过森林",1,1,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,1,0,0
6,0.516378068835505,"琥珀青春",1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1
7,0.264807238500381,"蔷薇少女馆 1",1,1,0,1,0,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0
8,0.136196854429181,"萌淑女驾到之美女训练营",1,0,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0
9,0.755023161812434,"千零一夜美梦恋",0,0,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0
10,0.242905525403648,"我能听到你的心吗",0,1,1,1,1,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0



( run in 0.807 second using v1.01-cache-2.11-cpan-49f99fa48dc )