Blog

Quick Deep Learning from CSV data

01/29/2021

Automation via Deep Learning is applicable to all data types. This is due to the excellent ability of neural networks that can be trained straight from raw data. Relevant data types range from images to videos, logs, texts, cloud points and graphs.

However, in practice, most data collected for industrial purposes are in the form of spreadsheets or CSV data files. This is because CSV is a simple and convenient readable format.

Working from CSV with Deep Learning is useful for several reasons:

  • Quick prototyping and training takes only a few minutes
  • CPU is enough, working on a laptop is fine, no GPU required
  • CSV can be used to store data for a large set of applications, including images

Whether it is for quick prototyping or go further and automate a complex task, ability to train deep neural models from CSV data is thus very convenient.

This small post is about quickly training deep neural networks from CSV data quickly with DeepDetect.

We use two public datasets on which we reach > 95% accuracy in minutes.

Whether you are a beginner with Deep Learning or need a quick prototype, below we detail two easily reproducible examples on public datasets. For more details on each of the parameters and options refer to the DeepDetect API.

CSV: predicting gender from voice statistics

Gender voice classification

Let us start with the dataset from https://www.kaggle.com/primaryobjects/voicegender and prepare the data:

mkdir gender_voice_model
cp voice.csv gender_voice_model/

The dataset has voice statistics and a label for male or female. We can train a small neural network that takes statistics in and classifies them as a voice coming from a male or a female, with 98% accuracy.

  • First step is to start an instance of DeepDetect server:

    ./dede
    
  • Second step is to create a service on the server with the right parameters to set the data connector and neural network architecture. Here we use a simple three-layer network.

    curl -X PUT "http://localhost:8080/services/voice" -d '{                 
       "mllib":"caffe",
       "description":"voice gender classification service",
       "type":"supervised",
       "parameters":{
         "input":{
           "connector":"csv"
         },
         "mllib":{
           "template":"mlp",
           "nclasses":2,
           "layers":[150,150,150],
           "activation":"prelu"
         }
       },
       "model":{
         "templates":"../templates/caffe/",
         "repository":"/path/to/gender_voice_model"
       }
     }'
    
    
  • Third step is to tell the server what CSV label and separator to use, and start training the neural network

    curl -X POST "http://localhost:8080/train" -d '{                          
       "service":"voice",
       "async":false,
       "parameters":{
         "mllib":{
           "gpu":true,
           "solver":{
             "iterations":30000,
             "test_interval":1000,
             "base_lr":0.0001
           },
           "net":{
             "batch_size":34
           },
           "solver":{
             "solver_type":"AMSGRAD",
             "rectified":true,
             "lookahead":true
           }
         },
         "input":{
         "label":"label",
         "separator":",",
         "shuffle":true,
         "test_split":0.05,
         "scale":true
         },
         "output":{
           "measure":["acc","mcll","f1"]
         }
       },
       "data":["/path/to/gender_voice_model/voice.csv"]
     }'
    

The server output should look something similar to:

[2021-01-27 15:38:20.650] [caffe] [info] Snapshotting to binary proto file /home/beniz/projects/deepdetect/models/gender_by_voice/model_iter_1000.caffemodel
[2021-01-27 15:38:20.652] [caffe] [info] Snapshotting solver state to binary proto file /home/beniz/projects/deepdetect/models/gender_by_voice/model_iter_1000.solverstate
[2021-01-27 15:38:20.652] [voice] [info] batch size=51
[2021-01-27 15:38:20.653] [voice] [info] learning_rate=0.0001
[2021-01-27 15:38:20.653] [voice] [info] iteration=1000
[2021-01-27 15:38:20.653] [voice] [info] train_loss=0.585991
[2021-01-27 15:38:20.653] [voice] [info] f1=0.760921
[2021-01-27 15:38:20.653] [voice] [info] accp=0.761006
[2021-01-27 15:38:20.653] [voice] [info] mcll=0.594265
[2021-01-27 15:38:20.653] [voice] [info] acc=0.761006
[2021-01-27 15:38:20.653] [voice] [info] precision=0.761155
[2021-01-27 15:38:20.653] [voice] [info] recall=0.761652
[2021-01-27 15:38:20.655] [voice] [info] Iteration 1000, lr = 0.0001, smoothed_loss=0.592172
[2021-01-27 15:38:20.854] [voice] [info] Iteration 1100, lr = 0.0001, smoothed_loss=0.597599
[2021-01-27 15:38:20.988] [voice] [info] Iteration 1200, lr = 0.0001, smoothed_loss=0.556927
[2021-01-27 15:38:21.169] [voice] [info] Iteration 1300, lr = 0.0001, smoothed_loss=0.550256
[2021-01-27 15:38:23.060] [voice] [info] Iteration 1400, lr = 0.0001, smoothed_loss=0.535919
[2021-01-27 15:38:23.191] [voice] [info] Iteration 1500, lr = 0.0001, smoothed_loss=0.532068
[2021-01-27 15:38:23.319] [voice] [info] Iteration 1600, lr = 0.0001, smoothed_loss=0.489731
[2021-01-27 15:38:23.449] [voice] [info] Iteration 1700, lr = 0.0001, smoothed_loss=0.558742
[2021-01-27 15:38:23.583] [voice] [info] Iteration 1800, lr = 0.0001, smoothed_loss=0.47495
[2021-01-27 15:38:23.722] [voice] [info] Iteration 1900, lr = 0.0001, smoothed_loss=0.40723

At the end of the training, the final metrics are reported:

{
    "body": {
        "measure": {
            "acc": 0.9748427672955975,
            "accp": 0.9748427672955975,
            "f1": 0.9747939073692261,
            "iteration": 29999.0,
            "learning_rate": 9.999999747378752e-05,
            "mcll": 0.0721548160513648,
            "precision": 0.9747939123692261,
            "recall": 0.9747939123692261,
            "train_loss": 0.0904836431145668
        },
        "model": {
            "repository": "/home/beniz/projects/deepdetect/models/gender_by_voice"
        },
        "parameters": {
            "input": {
                "connector": "csv",
                "max_vals": [
		  ...
                ],
                "min_vals": [
                  ...
                ]
            },
            "mllib": {
                "batch_size": 51
            }
        }
    },
    "head": {
        "method": "/train",
        "time": 92.0
    },
    "status": {
        "code": 201,
        "msg": "Created"
    }
}

We see that without any detailed adjustment or tweaking the model reaches over 97% accuracy in 1min30sec of processing on an XPS 13 core i7 laptop.

To delete the model and start over, e.g. with new parameters, you can clean the model directory up via the API:

curl -X DELETE http://localhost:8080/services/voice\?clear\=lib

CSV: classifying activity from smartphone sensor data

Smartphone human activity recognition

We use the dataset from https://www.kaggle.com/uciml/human-activity-recognition-with-smartphones, and prepare the data as follows:

mkdir activity_recog_model
cd activity_recog_model
cp train.csv test.csv activity_recog_model/

The dataset has smartphone sensor inputs and a label for one of six activities. Below we train a small neural network that detects the correct activity out of the signals with XX% accuracy.

  • Service creation is as follows:

    curl -X PUT "http://localhost:8080/services/activity" -d '{                 
       "mllib":"caffe",
       "description":"activity classification service",
       "type":"supervised",
       "parameters":{
         "input":{
           "connector":"csv"
         },
         "mllib":{
           "template":"mlp",
           "nclasses":6,
           "layers":[150,150,150],
    	   "dropout": 0.5,
           "activation":"prelu"
         }
       },
       "model":{
         "templates":"../templates/caffe/",
         "repository":"/path/to/activity_recog_model"
       }
     }'
    
  • Train the small network, note that we tell the server to ignore the Subject column from the CSV. This makes the model independent of the smartphone owner.

    curl -X POST "http://localhost:8080/train" -d '{                          
       "service":"activity",
       "async":false,
       "parameters":{
         "mllib":{
           "gpu":true,
           "solver":{
             "iterations":200000,
             "test_interval":5000,
             "base_lr":0.0001
           },
           "net":{
             "batch_size":34
           },
           "solver":{
             "solver_type":"AMSGRAD",
             "rectified":true,
             "lookahead":true
           }
         },
         "input":{
         "label":"Activity",
    	 "ignore":["Subject"],
         "separator":",",
         "shuffle":true,
         "scale":true
         },
         "output":{
           "measure":["acc","mcll","f1"]
         }
       },
       "data":["/path/to/activity_recog_model/train.csv",
       "/path/to/activity_recog_model/test.csv"]
     }'
    

The server output should look similar to this:

[2021-01-28 06:06:27.399] [caffe] [info] Snapshotting solver state to binary proto file /home/beniz/projects/deepdetect/models/activity_recog/model_iter_5000.solverstate
[2021-01-28 06:06:27.401] [activity] [info] batch size=8
[2021-01-28 06:06:27.401] [activity] [info] learning_rate=0.0001
[2021-01-28 06:06:27.401] [activity] [info] iteration=5000
[2021-01-28 06:06:27.401] [activity] [info] train_loss=0.56961
[2021-01-28 06:06:27.401] [activity] [info] f1=0.778501
[2021-01-28 06:06:27.401] [activity] [info] accp=0.790295
[2021-01-28 06:06:27.401] [activity] [info] mcll=0.672717
[2021-01-28 06:06:27.401] [activity] [info] acc=0.790295
[2021-01-28 06:06:27.401] [activity] [info] precision=0.824434
[2021-01-28 06:06:27.401] [activity] [info] recall=0.7784
[2021-01-28 06:06:27.401] [activity] [info] Iteration 5000, lr = 0.0001, smoothed_loss=0.935313
[2021-01-28 06:06:27.507] [activity] [info] Iteration 5100, lr = 0.0001, smoothed_loss=0.902551
[2021-01-28 06:06:27.614] [activity] [info] Iteration 5200, lr = 0.0001, smoothed_loss=0.598573
[2021-01-28 06:06:27.720] [activity] [info] Iteration 5300, lr = 0.0001, smoothed_loss=0.911433
[2021-01-28 06:06:27.829] [activity] [info] Iteration 5400, lr = 0.0001, smoothed_loss=0.712529
[2021-01-28 06:06:27.991] [activity] [info] Iteration 5500, lr = 0.0001, smoothed_loss=0.524583
[2021-01-28 06:06:28.298] [activity] [info] Iteration 5600, lr = 0.0001, smoothed_loss=0.54077
[2021-01-28 06:06:28.666] [activity] [info] Iteration 5700, lr = 0.0001, smoothed_loss=0.510589

And the report on final accuracies:

{
    "body": {
        "measure": {
            "acc": 0.9514760773668137,
            "accp": 0.9514760773668137,
            "f1": 0.9506585488448627,
            "iteration": 199999.0,
            "learning_rate": 9.999999747378752e-05,
            "mcll": 0.13310640335157187,
            "precision": 0.9512485948752646,
            "recall": 0.9505450630442133,
            "test_id": 0,
            "test_name": "",
            "train_loss": 0.025191251188516617
        },
        "measures": [
            {
                "acc": 0.9514760773668137,
                "accp": 0.9514760773668137,
                "f1": 0.9506585488448627,
                "iteration": 199999.0,
                "learning_rate": 9.999999747378752e-05,
                "mcll": 0.13310640335157187,
                "precision": 0.9512485948752646,
                "recall": 0.9505450630442133,
                "test_id": 0,
                "test_name": "",
                "train_loss": 0.025191251188516617
            }
        ],
        "model": {
            "repository": "/home/beniz/projects/deepdetect/models/activity_recog"
        },
        "parameters": {
            "input": {
                "connector": "csv",
                "max_vals": [
                   ...
                ],
                "min_vals": [
                   ...
                ]
            },
            "mllib": {
                "batch_size": 8
            }
        }
    },
    "head": {
        "method": "/train",
        "time": 412.0
    },
    "status": {
        "code": 201,
        "msg": "Created"
    }
}