Machine learning algorithms in Dart programming language

Overview

Build Status Coverage Status pub package Gitter Chat

Machine learning algorithms for Dart developers

What is the ml_algo for?

The main purpose of the library is to give native Dart implementation of machine learning algorithms to those who are interested both in Dart language and data science. This library aims at Dart VM and Flutter, it's impossible to use it in the web applications.

The library's content

  • Model selection

    • CrossValidator. Factory that creates instances of cross validators. Cross validation allows researchers to fit different hyperparameters of machine learning algorithms assessing prediction quality on different parts of a dataset.
  • Classification algorithms

    • LogisticRegressor. A class that performs linear binary classification of data. To use this kind of classifier your data has to be linearly separable.

    • SoftmaxRegressor. A class that performs linear multiclass classification of data. To use this kind of classifier your data has to be linearly separable.

    • DecisionTreeClassifier A class that performs classification using decision trees. May work with data with non-linear patterns.

    • KnnClassifier A class that performs classification using k nearest neighbours algorithm - it makes prediction basing on the first k closest observations to the given one.

  • Regression algorithms

    • LinearRegressor. A class that finds a linear pattern in training data and predicts outcome as real numbers depending on the pattern.

    • KnnRegressor A class that makes prediction for each new observation basing on first k closest observations from training data. It may catch non-linear pattern of the data.

For more information on the library's API, please visit API reference

Examples

Let's classify records from well-known dataset - Pima Indians Diabets Database via Logistic regressor

Important note:

Please pay attention to problems which classifiers and regressors exposed by the library solve. E.g. Logistic regressor solves only binary classification problem, and that means that you can't use this classifier to deal with dataset with more than two classes, keep that in mind - in order to find out more about regresseors and classifiers, please refer to the api documentation of the package

Import all necessary packages. First, it's needed to ensure if you have ml_preprocessing and ml_dataframe packages in your dependencies:

dependencies:
  ml_dataframe: ^0.5.1
  ml_preprocessing: ^6.0.0

We need these repos to parse raw data in order to use it further. For more details, please visit ml_preprocessing repository page.

Important note:

Regressors and classifiers exposed by the library do not handle strings, booleans and nulls, they can only deal with numbers! You necessarily need to convert all the improper values of your dataset to numbers, please refer to ml_preprocessing library to find out more about data preprocessing.

import 'package:ml_algo/ml_algo.dart';
import 'package:ml_dataframe/ml_dataframe.dart';
import 'package:ml_preprocessing/ml_preprocessing.dart';

Read a dataset's file

Download dataset from Pima Indians Diabets Database.

For a desktop application:

Just provide a proper path to your downloaded file and use a function-factory fromCsv from ml_dataframe package to read the file:

final samples = await fromCsv('datasets/pima_indians_diabetes_database.csv');

For a flutter application:

Be sure that you have ml_dataframe package version at least 0.5.1 and ml_algo package version at least 16.0.0 in your pubspec.yaml:

dependencies:
  ...
  ml_algo: ^16.0.0
  ml_dataframe: ^0.5.1
  ...

Then it's needed to add a dataset to the flutter assets by adding the following config in the pubspec.yaml:

flutter:
  assets:
    - assets/datasets/pima_indians_diabetes_database.csv

Of course you need to create the assets directory in the file system and put the dataset's file there. After that you can access the dataset:

import 'package:flutter/services.dart' show rootBundle;
import 'package:ml_dataframe/ml_dataframe.dart';

final rawCsvContent = await rootBundle.loadString('assets/datasets/pima_indians_diabetes_database.csv');
final samples = DataFrame.fromRawCsv(rawCsvContent);

Prepare datasets for training and test

Data in this file is represented by 768 records and 8 features. 9th column is a label column, it contains either 0 or 1 on each row. This column is our target - we should predict a class label for each observation. The column's name is class variable (0 or 1). Let's store it:

final targetColumnName = 'class variable (0 or 1)';

Now it's the time to prepare data splits. Since we have a smallish dataset (only 768 records), we can't afford to split the data into just train and test sets and evaluate the model on them, the best approach in our case is Cross Validation. According to this, let's split the data in the following way using the library's splitData function:

final splits = splitData(samples, [0.7]);
final validationData = splits[0];
final testData = splits[1];

splitData accepts DataFrame instance as the first argument and ratio list as the second one. Now we have 70% of our data as a validation set and 30% as a test set for evaluating generalization error.

Set up a model selection algorithm

Then we may create an instance of CrossValidator class to fit hyperparameters of our model. We should pass validation data (our validationData variable), and a number of folds into CrossValidator constructor.

final validator = CrossValidator.kFold(validationData, numberOfFolds: 5);

Let's create a factory for the classifier with desired hyperparameters. We have to decide after the cross validation, if the selected hyperparametrs are good enough or not:

final createClassifier = (DataFrame samples) =>
  LogisticRegressor(
    samples
    targetColumnName,
    optimizerType: LinearOptimizerType.gradient,
    iterationsLimit: 90,
    learningRateType: LearningRateType.timeBased,
    batchSize: samples.rows.length,
    probabilityThreshold: 0.7,
  );

Let's describe our hyperparameters:

  • optimizerType - type of optimization algorithm that will be used to learn coefficients of our model, this time we decided to use vanilla gradient ascent algorithm
  • iterationsLimit - number of learning iterations. Selected optimization algorithm (gradient ascent in our case) will be run this amount of times
  • learningRateType - a strategy for learning rate update. In our case the learning rate will decrease after every iteration
  • batchSize - size of data (in rows) that will be used per each iteration. As we have a really small dataset we may use full-batch gradient ascent, that's why we used samples.rows.length here - the total amount of data.
  • probabilityThreshold - lower bound for positive label probability

If we want to evaluate the learning process more thoroughly, we may pass collectLearningData argument to the classifier constructor:

final createClassifier = (DataFrame samples) =>
  LogisticRegressor(
    ...,
    collectLearningData: true,
  );

This argument activates collecting costs per each optimization iteration, and you can see the cost values right after the model creation.

Evaluate performance of the model

Assume, we chose really good hyperprameters. In order to validate this hypothesis let's use CrossValidator instance created before:

final scores = await validator.evaluate(createClassifier, MetricType.accuracy);

Since the CrossValidator instance returns a Vector of scores as a result of our predictor evaluation, we may choose any way to reduce all the collected scores to a single number, for instance we may use Vector's mean method:

final accuracy = scores.mean();

Let's print the score:

print('accuracy on k fold validation: ${accuracy.toStringAsFixed(2)}');

We can see something like this:

accuracy on k fold validation: 0.65

Let's assess our hyperparameters on test set in order to evaluate the model's generalization error:

final testSplits = splitData(testData, [0.8]);
final classifier = createClassifier(testSplits[0]);
final finalScore = classifier.assess(testSplits[1], MetricType.accuracy);

The final score is like:

print(finalScore.toStringAsFixed(2)); // approx. 0.75

If we specified collectLearningData parameter, we may see costs per each iteration in order to evaluate how our cost changed from iteration to iteration during the learning process:

print(classifier.costPerIteration);

Write the model to a json file

Seems, our model has a good generalization ability, and that means we may use it in the future. To do so we may store the model to a file as JSON:

await classifier.saveAsJson('diabetes_classifier.json');

After that we can simply read the model from the file and make predictions:

import 'dart:io';

final fileName = 'diabetes_classifier.json';
final file = File(fileName);
final encodedModel = await file.readAsString();
final classifier = LogisticRegressor.fromJson(encodedModel);
final unlabelledData = await fromCsv('some_unlabelled_data.csv');
final prediction = classifier.predict(unlabelledData);

print(prediction.header); // ('class variable (0 or 1)')
print(prediction.rows); // [ 
                        //   (1),
                        //   (0),
                        //   (0),
                        //   (1),
                        //   ...,
                        //   (1),
                        // ]

Please note that all the hyperparameters that we used to generate the model are persisted as the model's readonly fields, and we can access it anytime:

print(classifier.iterationsLimit);
print(classifier.probabilityThreshold);
// and so on
All the code above all together for a desktop application:
import 'package:ml_algo/ml_algo.dart';
import 'package:ml_dataframe/ml_dataframe.dart';
import 'package:ml_preprocessing/ml_preprocessing.dart';

void main() async {
  final samples = await fromCsv('datasets/pima_indians_diabetes_database.csv', headerExists: true);
  final targetColumnName = 'class variable (0 or 1)';
  final splits = splitData(samples, [0.7]);
  final validationData = splits[0];
  final testData = splits[1];
  final validator = CrossValidator.kFold(validationData, numberOfFolds: 5);
  final createClassifier = (DataFrame samples) =>
    LogisticRegressor(
      samples
      targetColumnName,
      optimizerType: LinearOptimizerType.gradient,
      iterationsLimit: 90,
      learningRateType: LearningRateType.timeBased,
      batchSize: samples.rows.length,
      probabilityThreshold: 0.7,
    );
  final scores = await validator.evaluate(createClassifier, MetricType.accuracy);
  final accuracy = scores.mean();
  
  print('accuracy on k fold validation: ${accuracy.toStringAsFixed(2)}');

  final testSplits = splitData(testData, [0.8]);
  final classifier = createClassifier(testSplits[0], targetNames);
  final finalScore = classifier.assess(testSplits[1], targetNames, MetricType.accuracy);
  
  print(finalScore.toStringAsFixed(2));

  await classifier.saveAsJson('diabetes_classifier.json');
}
All the code above all together for a flutter application:
import 'package:flutter/services.dart' show rootBundle;
import 'package:ml_algo/ml_algo.dart';
import 'package:ml_dataframe/ml_dataframe.dart';
import 'package:ml_preprocessing/ml_preprocessing.dart';

void main() async {
  final rawCsvContent = await rootBundle.loadString('assets/datasets/pima_indians_diabetes_database.csv');
  final samples = DataFrame.fromRawCsv(rawCsvContent);
  final targetColumnName = 'class variable (0 or 1)';
  final splits = splitData(samples, [0.7]);
  final validationData = splits[0];
  final testData = splits[1];
  final validator = CrossValidator.kFold(validationData, numberOfFolds: 5);
  final createClassifier = (DataFrame samples) =>
    LogisticRegressor(
      samples
      targetColumnName,
      optimizerType: LinearOptimizerType.gradient,
      iterationsLimit: 90,
      learningRateType: LearningRateType.timeBased,
      batchSize: samples.rows.length,
      probabilityThreshold: 0.7,
    );
  final scores = await validator.evaluate(createClassifier, MetricType.accuracy);
  final accuracy = scores.mean();
  
  print('accuracy on k fold validation: ${accuracy.toStringAsFixed(2)}');

  final testSplits = splitData(testData, [0.8]);
  final classifier = createClassifier(testSplits[0], targetNames);
  final finalScore = classifier.assess(testSplits[1], targetNames, MetricType.accuracy);
  
  print(finalScore.toStringAsFixed(2));

  await classifier.saveAsJson('diabetes_classifier.json');
}

Models retraining

Someday our previously shining model can degrade in terms of prediction accuracy - in this case we can retrain it. Retraining means simply re-running the same learning algorithm that was used to generate our current model keeping the same hyperparameters but using a new data set with the same features:

import 'dart:io';

final fileName = 'diabetes_classifier.json';
final file = File(fileName);
final encodedModel = await file.readAsString();
final classifier = LogisticRegressor.fromJson(encodedModel);

// ... 
// here we do something and realize that our classifier performance is not so good
// ...

final newData = await fromCsv('path/to/dataset/with/new/data/to/retrain/the/classifier');
final retrainedClassifier = classifier.retrain(newData);

The workflow with other predictors (SoftmaxRegressor, DecisionTreeClassifier and so on) is quite similar to the described above for LogisticRegressor, feel free to experiment with other models.

A couple of words about linear models which use gradient optimisation methods

Sometimes you may get NaN or Infinity as a value of your score, or it may be equal to some inconceivable value (extremely big or extremely low). To prevent so, you need to find a proper value of the initial learning rate, and also you may choose between two learning rate strategies, decreasing adaptive or constant:

final createClassifier = (DataFrame samples) =>
    LogisticRegressor(
      ...,
      initialLearningRate: 1e-5, // The bigger the number of records in dataset, the lower should be the learning rate
      learningRateType: LearningRateType.timeBased,
      ...,
    );

Contacts

If you have questions, feel free to write me on

Comments
  • Blank invalid exception while creating classifier

    Blank invalid exception while creating classifier

    Here is my data :

    (src, day, time, dest)
    (0, 0, 450, 4)
    (1, 0, 110, 5)
    (0, 1, 450, 4)
    (1, 1, 110, 5)
    (0, 2, 450, 4)
    (1, 2, 110, 5)
    (0, 3, 450, 4)
    (1, 3, 110, 5)
    (0, 4, 450, 4)
    (1, 4, 110, 5)
    (0, 5, 450, 4)
    (1, 5, 110, 5)
    (2, 6, 660, 6)
    (3, 6, 1170, 7)
    (0, 0, 450, 4)
    (1, 0, 110, 5)
    (0, 1, 450, 4)
    (1, 1, 110, 5)
    (0, 2, 450, 4)
    (1, 2, 110, 5)
    (0, 3, 450, 4)
    (1, 3, 110, 5)
    (0, 4, 450, 4)
    (1, 4, 110, 5)
    (0, 5, 450, 4)
    (1, 5, 110, 5)
    (2, 6, 660, 6)
    (3, 6, 1170, 8)
    

    And it then throws this exception while trying try to create the classifier:

    Unhandled exception:
    Invalid argument(s)
    #0      _TypedList._setFloat32 (dart:typed_data-patch/typed_data_patch.dart:2126:36)
    #1      _Float32ArrayView.[]= (dart:typed_data-patch/typed_data_patch.dart:4461:16)
    #2      new Float32MatrixDataManager.fromList
    package:ml_linalg/…/data_manager/float32_matrix_data_manager.dart:37
    
    #3      MatrixFactoryImpl.fromList
    package:ml_linalg/…/matrix/matrix_factory_impl.dart:21
    #4      new Matrix.fromList
    package:ml_linalg/matrix.dart:42
    #5      DataFrameImpl.toMatrix
    package:ml_dataframe/…/data_frame/data_frame_impl.dart:143
    #6      createLogLikelihoodOptimizer
    package:ml_algo/…/_helpers/create_log_likelihood_optimizer.dart:46
    
    #7      LogisticRegressorFactoryImpl.create
    package:ml_algo/…/logistic_regressor/logistic_regressor_factory_impl.dart:58
    #8      new LogisticRegressor
    package:ml_algo/…/logistic_regressor/logistic_regressor.dart:153
    #9      main.<anonymous closure>
    bin\knn.dart:41
    #10     main
    bin\knn.dart:53
    <asynchronous suspension>
    

    Classifier is constructed this way :

     final createClassifier = (DataFrame samples) => LogisticRegressor(
            samples,
            targetColumnName,
            optimizerType: LinearOptimizerType.gradient,
            iterationsLimit: 90,
            learningRateType: LearningRateType.decreasingAdaptive,
            batchSize: samples.rows.length,
            probabilityThreshold: 0.7,
          );
    
    opened by gaetschwartz 13
  • LinearRegressor with OrdinaryLeastSquares

    LinearRegressor with OrdinaryLeastSquares

    I see we can only choose between Gradient and Coordinate. I believe this is why the data I'm getting back isn't what I expect. If that's not the reason, please let me know, thanks!

    For example, if I have the data

    Grind, RoastLevel, Time
    5.5, 5, 20
    5.25, 5, 22
    

    And I make RoastLevel and Time independent variables, and Grind dependent, I can get an expected prediction with Python using Sklearn out of the box.

    data_minus_grind = []
    grind_data = []
    for row in floats:
        data_minus_grind.append(row[1:3])
        grind_data.append(row[0])
    
    model = LinearRegression().fit(data_minus_grind, grind_data)
    prediction_data = [[5,25]]
    prediction = model.predict(prediction_data)
    

    This prediction, trying to predict the Grind for the Time 25, I receive 4.875, which sounds about right. Grind should go down while Time goes up.

    However, if I try to use this library, my slope is always in the wrong direction, with the two variables moving in the same direction for some reason.

    If I try

    final samples = DataFrame.fromRawCsv(rawCsvContent, headerExists: true);
    const targetColName = "Grind";
    final defaultRegressor = LinearRegressor(
        samples,
        targetColName
    );
    final dataToPredict = [
        // Roast level, time
        [ 5, 25.0 ]
    ];
    final dataframeToPredict = DataFrame(dataToPredict, headerExists: false);
    final prediction = regressor.predict(dataframeToPredict);
    

    Then the result for Grind with a Time of 25.0 is 6.79. As I move up the time, Grind should decrease, but instead it increases. I've tried tweaking many of the parameters but haven't found a fix.

    Thanks!

    opened by WaylonBrown 6
  • Examples of configuration for LinearRegressor?

    Examples of configuration for LinearRegressor?

    Hey,

    Thanks a lot for the library. Really impressed with how much you can do with dart!

    Trying to run a linear regression for a simple line y(x) = x, found following issues which I suppose are due to configuration of the regressor. Please help to configure

    The code below gives my expected result for most of the cases, with k around 1.00. However in some cases, i.e.

    a=1 n=10 -> k (0.9994153380393982) rows ((9.994153022766113))
    a=0 n=10 -> k (0.3038938045501709) rows ((3.038938045501709))
    a=-10 n=10 -> k (0.5980027318000793) rows ((5.980027198791504))
    a=1 n=100 -> k (NaN) rows ((0.0))  
    

    the result is different. Is this because of the configuration?

    Also is there a way to retrieve b from y(x) = kx + b?

    Thank you!

    import 'package:ml_algo/ml_algo.dart';
    import 'package:ml_dataframe/ml_dataframe.dart';
    import 'package:xrange/xrange.dart';
    
    main() {
     var a = 1;
     var n = 100;
    
     var _data = NumRange.closed(a, n).values().map((it) => [it, it]) ;
    
     final data = [['x', 'y'], ..._data];
    
     print(data);
    
     final samples = DataFrame(data, headerExists: true);
     final regressor = LinearRegressor(samples, 'y');
    
     var prediction = regressor.predict(DataFrame([['x', 'y'], [10.0,]],));
    
     print("a=$a n=$n -> k ${regressor.coefficients} rows ${prediction.rows}");
    }
    
    opened by chaschev 5
  • Data persistence for Knn model

    Data persistence for Knn model

    Hi, what would be the best way to persist a knn model without recreating it every time? Is this also serializable, or does this model always need data to compute predictions lazily?

    enhancement 
    opened by jurrdb 5
  • Random forest implementation

    Random forest implementation

    Hello ! I have been using flutter on my free time and found out about this interesting library. As a side project, I would like to add an implementation of the random forest to the library via a pull request. Would you be interested ?

    opened by Maro1F431 3
  • Integrate python algorithms like xgboost using ffi

    Integrate python algorithms like xgboost using ffi

    This is a great project. I started to hate Python after using Dart with Flutter. I realized that I am still googling every basic stuff when using Python whereas with Dart it just takes microseconds to find the right method after putting dot. I wonder if it is possible to integrate popular machine learning algorithms like xgboost in Dart using FFI.

    Thanks a lot for creating this library.

    opened by deadsoul44 3
  • Compatibility problems with other packages

    Compatibility problems with other packages

    I'm facing a problem with ml_algo. The package requires > 3.0.1 for json_annotation, but I also use build_runner that requires > 4.0.1. This stop my development because pub get doesn't work with this incompatibility. If it won't be a problem please update all json_annotation to 4.0.1 from the packages.

    opened by jose-almir 3
  • How to persist DTree?

    How to persist DTree?

    Hi, when I made a DecisionTreeClassification how can I presist it's model so we can reuse it in my next sessions because training in DTree takes a lot of time?

    enhancement 
    opened by mohas 3
  • 'diabetes_classifier.json' (OS Error: Read-only file system, errno = 30)

    'diabetes_classifier.json' (OS Error: Read-only file system, errno = 30)

    Hi, I have been trying to replicate the example here, but I cannot write the json classifier model due to the following error:

    Running "flutter pub get" in logistic_regressor...
    Launching lib\main.dart on sdk gphone x86 in debug mode...
    Running Gradle task 'assembleDebug'...
    √  Built build\app\outputs\flutter-apk\app-debug.apk.
    Installing build\app\outputs\flutter-apk\app.apk...
    Debug service listening on ws://127.0.0.1:64760/6bAEB-pabM4=/ws
    Syncing files to device sdk gphone x86...
    I/flutter ( 7530): accuracy on k fold validation: 0.63
    I/flutter ( 7530): 0.76
    E/flutter ( 7530): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: FileSystemException: Cannot create file, path = 'diabetes_classifier.json' (OS Error: Read-only file system, errno = 30)
    E/flutter ( 7530): #0      _File.create.<anonymous closure> (dart:io/file_impl.dart:255:9)
    E/flutter ( 7530): #1      _rootRunUnary (dart:async/zone.dart:1362:47)
    E/flutter ( 7530): #2      _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    E/flutter ( 7530): <asynchronous suspension>
    E/flutter ( 7530): #3      SerializableMixin.saveAsJson (package:ml_algo/src/common/serializable/serializable_mixin.dart:9:18)
    E/flutter ( 7530): <asynchronous suspension>
    E/flutter ( 7530): #4      _MyHomePageState.trainModel (package:logistic_regressor/main.dart:99:5)
    E/flutter ( 7530): <asynchronous suspension>
    E/flutter ( 7530): 
    

    I have tried using permission in android/app/src/main/AndroidManifest.xml

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.logistic_regressor">
        <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    

    and also requested the permission via Permission.manageExternalStorage.request() in my main.dart:

    import 'dart:io';
    import 'package:flutter/material.dart';
    import 'package:ml_algo/ml_algo.dart';
    import 'package:ml_dataframe/ml_dataframe.dart';
    import 'package:ml_preprocessing/ml_preprocessing.dart';
    import 'package:flutter/services.dart' show rootBundle;
    
    import 'package:permission_handler/permission_handler.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key? key, required this.title}) : super(key: key);
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      void trainModel() async {
        final rawCsvContent = await rootBundle.loadString('datasets/pima_indians_diabetes_database.csv');
        final samples = DataFrame.fromRawCsv(rawCsvContent);
    
        // === Prepare Dataset ===
        final targetColumnName = 'class variable (0 or 1)';
    
        final splits = splitData(samples, [0.7]);
        final validationData = splits[0];
        final testData = splits[1];
    
        // === Setup model selection algorithm ===
        final validator = CrossValidator.kFold(validationData, numberOfFolds: 5);
    
        final createClassifier = (DataFrame samples) =>
            LogisticRegressor(
              samples,
              targetColumnName,
              optimizerType: LinearOptimizerType.gradient,
              iterationsLimit: 90,
              learningRateType: LearningRateType.decreasingAdaptive,
              batchSize: samples.rows.length,
              probabilityThreshold: 0.7,
              collectLearningData: true,
            );
    
        // === Evaluate model performance ===
        final scores = await validator.evaluate(createClassifier, MetricType.accuracy);
        final accuracy = scores.mean();
        print('accuracy on k fold validation: ${accuracy.toStringAsFixed(2)}');
    
        final testSplits = splitData(testData, [0.8]);
        final classifier = createClassifier(testSplits[0]);
        final finalScore = classifier.assess(testSplits[1], MetricType.accuracy);
    
        print(finalScore.toStringAsFixed(2)); // approx. 0.75
    
        // === Write the model to JSON file ===
        var status = await Permission.manageExternalStorage.status;
        if (status.isDenied) {
          await Permission.manageExternalStorage.request();
        }
    
        await classifier.saveAsJson('diabetes_classifier.json');
      }
    
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        trainModel();
      }
    
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          home: new Scaffold(
            appBar: new AppBar(
              title: new Text('Plugin example app'),
            ),
            body: new Center(
              child: new Column(children: <Widget>[
                new Text('Running'),
              ]),
            ),
          ),
        );
      }
    }
    

    If anyone got insight on what the problem is, I would really appreciate if you could help. Cheers!

    opened by stephentandjiria 2
  • Exception: The dimension of the vector and the columns number of the matrix mismatch

    Exception: The dimension of the vector and the columns number of the matrix mismatch

    Hello, I have a chart with many data points in my Flutter app and I am trying to draw a trend line in it as you can see in this example: https://google.github.io/charts/flutter/example/combo_charts/scatter_plot_line To do so, I have programmed the class seen below and implemented the LinearRegressor in it. I want to display the line by determining the y-values for two values on the x-axis of my chart using my predict function and then drawing a line through those points. However, it seems that there is a bug in my predict function which you can see below and I can't quite figure it out. I can say, that in the train function I have two columns, in the first column are the x values and in the second column are the corresponding y values of the points in the chart. I then use this data to train the LinearRegressor. The predict function takes an x-value, which is why the ySeries, the second column, is empty there. With one row and two columns, the second of which is empty, I then try to predict this empty space, which is the y-value. I assume that something is wrong here in my implementation of the prediction, but unfortunately I don't understand what. I hope the error description is sufficient.

    This is the error I get:

    E/flutter ( 8937): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Exception: The dimension of the vector and the columns number of the matrix mismatch
    E/flutter ( 8937): #0      MatrixImpl._matrixVectorMul (package:ml_linalg/src/matrix/matrix_impl.dart:500:7)
    E/flutter ( 8937): #1      MatrixImpl.* (package:ml_linalg/src/matrix/matrix_impl.dart:89:14)
    E/flutter ( 8937): #2      LinearRegressorImpl.predict (package:ml_algo/src/regressor/linear_regressor/linear_regressor_impl.dart:152:11)
    E/flutter ( 8937): #3      AnalyticsLinearRegression.predict (package:trimlog/services/ml/analytics_linear_regression.dart:87:35)
    E/flutter ( 8937): <asynchronous suspension>
    E/flutter ( 8937): #4      _AnalyticGraphState.build.<anonymous closure>.<anonymous closure>.<anonymous closure>._predict.<anonymous closure> (package:trimlog/screens/analytics/analytics_graphs.dart:143:49)
    E/flutter ( 8937): <asynchronous suspension>
    E/flutter ( 8937):
    

    This is the class used for the linear regression:

    class AnalyticsLinearRegression {
      List<Trim> trims;
      final String xCategory;
      final String xParameter;
      final String yCategory;
      final String yParameter;
    
      AnalyticsLinearRegression(this.trims, this.xCategory, this.xParameter, this.yCategory, this.yParameter);
    
      List<Series> _prepareData() {
        // Remove trims which do not contain the parameter shown in this analytic
        List<Trim> temp = new List.from(trims);
        trims.forEach((trim) {
          Map<String, dynamic> map = trim.toMap();
          if ((!(map[xCategory] as Map).containsKey(xParameter)) || (map[xCategory][xParameter] == null) || (!(map[yCategory] as Map).containsKey(yParameter)) || (map[yCategory][yParameter] == null))
            temp.remove(trim);
        });
        trims = temp;
        // Extract the parameters shown in the analytic from the trims
        List x = [];
        List y = [];
        trims.forEach((trim) {
          Map<String, dynamic> map = trim.toMap();
          x.add((map[xCategory][xParameter] is List ? map[xCategory][xParameter].first : map[xCategory][xParameter]) * 1.0);
          y.add((map[yCategory][yParameter] is List ? map[yCategory][yParameter].first : map[yCategory][yParameter]) * 1.0);
        });
        Series xSeries = Series(xParameter, x); // First column, given parameter
        Series ySeries = Series(yParameter, y); // Second column, predicted parameter
        return [xSeries, ySeries];
      }
    
      Future train() async {
        final Iterable<Series> data = _prepareData();
        final dataFrame = DataFrame.fromSeries(data);
        if (dataFrame.rows.length <= 2) return; // <= 2 datapoints results in errors
        final targetColumnName = yParameter; // The second column (y) contains the parameter that I later want to predict
        final splits = splitData(dataFrame, [0.7]);
        final validationData = splits[0];
        // final testData = splits[1];
        final validator = CrossValidator.kFold(validationData, numberOfFolds: validationData.rows.length - 1);
        final createClassifier = (DataFrame samples) => LinearRegressor(
              samples,
              targetColumnName,
              optimizerType: LinearOptimizerType.gradient,
              iterationsLimit: 90,
              learningRateType: LearningRateType.decreasingAdaptive,
              batchSize: samples.rows.length,
            );
        final scores = await validator.evaluate(createClassifier, MetricType.rmse);
        final accuracy = scores.mean();
        print('Accuracy on root mean squared error (RMSE) validation: ${accuracy.toStringAsFixed(2)}');
        // final testSplits = splitData(testData, [1.00]);
        // final classifier = createClassifier(testSplits[0]);
        // final finalScore = classifier.assess(testSplits[1], MetricType.rmse);
        // print(finalScore.toStringAsFixed(2));
        // await classifier.saveAsJson(xParameter + '_' + yParameter + '_classifier.json');
        final classifier = createClassifier(dataFrame);
        await classifier.saveAsJson(await _classifierPath);
      }
    
      Future retrain(List<Trim> newData) async {
        final classifier = await _linearRegressor;
        trims = newData;
        final Iterable<Series> data = _prepareData();
        final dataFrame = DataFrame.fromSeries(data);
        final retrainedClassifier = classifier.retrain(dataFrame);
        await retrainedClassifier.saveAsJson(await _classifierPath);
      }
    
      /// Predicts the y value (seceond column) of a given x value (double)
      /// Can be used / Is used to get to points and draw a line through these points as a trendline (like here: https://google.github.io/charts/flutter/example/combo_charts/scatter_plot_line)
      Future<double> predict(double x) async {
        final classifier = await _linearRegressor;
        Series xSeries = Series(xParameter, [x]); // First column value (x)
        Series ySeries = Series(yParameter, []); // Second column value (y) should get predicted and returned, therefore this is empty
        final data = DataFrame.fromSeries([xSeries, ySeries]);
        final prediction = classifier.predict(data); // Predict the corresponding y value to the given x value
        return prediction.rows.first.first; // Prediction should only contain one row and this row should contain the predicted y value
      }
    
      Future<String> get _classifierPath async => (await getTemporaryDirectory()).path + "/" + xParameter + '_' + yParameter + '_classifier.json'; // Path where the classifier is saved
      Future<File> get _file async => File(await _classifierPath); // File containing the classifier (JSON)
      Future<String> get _encodedModel async => (await _file).readAsString(); // Classifier as JSON
      Future<LinearRegressor> get _linearRegressor async => LinearRegressor.fromJson(await _encodedModel); // Linear regressor from file
    }
    
    opened by PlutoHDDev 2
  • Persistence for LogisticRegressor

    Persistence for LogisticRegressor

    Hello, At the moment I have to retrain the model each time I use it. Fortunately, this does not take a lot of time, but because of that all sample data has to be present anywhere the model is used. One workaround that I found is to manually initialize a LinearRegressorImpl object with coefficients obtained from a trained LogisticRegressor model. However, this requires importing package private files which is not ideal. Adding a way to persist regressor models would be a great improvement!

    Best regards.

    enhancement 
    opened by jurrdb 2
  • Path down decision tree

    Path down decision tree

    Is there a way to get the path down the tree for a prediction from the decision tree? I can import the implementation, copy/paste the predict method and add nodes to a list, but that's not ideal.

    opened by elioBen 1
Owner
Ilya Gyrdymov
Frontend developer (ExtJs4, AngularDart, React+Redux, Vue+Vuex). Besides frontend development interested in Machine Learning.
Ilya Gyrdymov
A cross platform todo list app using flutter and dart programming language

Flutter Todos A cross platform todo list app using flutter and dart programming language. In this application, I used SQLite3 to persist data. The app

Mahmud Ahsan 61 Dec 29, 2022
Weather-application - A weather application based on dart programming language

weather based mobile app A new Flutter project with dart programmingg language S

Munem Sarker 5 Nov 13, 2022
null 357 Dec 27, 2022
Algorithm Toolbox is an Android app for C++, Python and DART algorithms. It shows the codes as well as its explanation with various examples.

AlgoKing Algorithm Toolbox is an Android app for C++, Python and DART algorithms. It shows the codes as well as its explanation with various examples.

Hash Studios 5 Sep 13, 2022
All Algorithms implemented in Dart

The Algorithms - Dart All algorithms implemented in Dart (for education) These implementations are for learning purposes. They may be less efficient t

The Algorithms 1.2k Dec 29, 2022
Flutter UI challenge (with Box2D physic)- Smart washing machine app

Flutter UI Challenge- SMART Washing Machine About project The application was written based on this great UI concept: https://dribbble.com/shots/11018

Tomasz Pawlikowski 754 Dec 27, 2022
Aplikasi Android konsultasi dokter dan vending machine

doctor_apps A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if t

Heri Nur Alim 1 Nov 11, 2021
A library for finite state machine realization

A library for finite state machine realization in Dart. Inspired by Tinder StateMachine library. Usage A simple usage example (using dfunc library for

Kirill Bubochkin 6 Dec 6, 2021
UI design for mobile, create using visual studio code & flutter dart programming languange

HCIProjectLab A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if

null 1 Oct 13, 2021
Upper is a open source back-end framework based on the Dart language.

What is Upper? Upper is a open source back-end framework based on the Dart language. With it, it is possible to automatically generate a gRPC API for

Andriws Luna 40 Sep 5, 2022
Routinger is a task scheduler app that is made to make you a better person at no extra cost. The code is open-source. Dart language and Flutter framework are used extensively.

Routinger This is a simple app that will allow you to schedule your tasks, create a simple to-do, and also make recurring tasks. The app ends you noti

Routinger 16 Dec 17, 2022
An open source task manager (todo list) app, developed using Dart language and Flutter framework.

Tasker An open source task manager (todo list) app, developed using Dart language and Flutter framework. Screenrecords     Screenshots                

Erfan Rahmati 42 Dec 29, 2022
The official sdk for the user-friendly API of Mega services on the Dart language.

megasdkdart The official sdk for the user-friendly API of Mega services in the Dart language. Example: import 'package:megasdkdart/megasdkdart.dart';

meg4cyberc4t 4 Mar 30, 2022
A modern voice chat application. The project has been written solely in Dart Language.

VChat A modern voice chat application. The application welcomes the user with the login screen. After a simple registration process, an empty "Home" s

Bulent Baris Kilic 6 Aug 18, 2022
A API integrated 5 day weather forecast and prediction application created using flutter framework and Dart language.

A API integrated 5 day weather forecast and prediction application created using flutter framework and Dart language. This API used here is OPEN WEATHER API, which specializes in predicting the weather of any city in this world.

Nitin Verma 0 Dec 26, 2021
Task List application developed in Dart language with SDK Flutter for Android, iOS and Web

Task List application developed in Dart language with SDK (Software Development Kit) Flutter for Android, iOS and Web.

João Bruno 2 Jun 2, 2022
This is a mobile application that goals to build a quiz about programming subjects writter with Flutter.

❓ DevQuiz A mobile application being built with NLW5 (an event from Rockeatseat - https://app.rocketseat.com.br/). This application goals to build a q

Samilly Nunes 18 Dec 23, 2022
Memo is an open-source, programming-oriented spaced repetition software (SRS) written in Flutter.

English | Portuguese Memo Monorepo for Memo. Memo is an open-source, programming-oriented spaced repetition software (SRS) written in Flutter. As of n

Olympus 1.7k Dec 30, 2022
OOTP (Open One-time Password) is a supports multiple programming languages.

OOTP (Open One-time Password) is a supports multiple programming languages. The generated one-time passwords are fully compliant with HOTP (HMAC-based One-time Password) and TOTP (Time-based One-time Password).

Odroe 16 Nov 20, 2022