6928 lines · 220.6 KB · C++
RawDownload
/*----------------------------------------------------------------------------  ChucK Concurrent, On-the-fly Audio Programming Language    Compiler and Virtual Machine   Copyright (c) 2004 Ge Wang and Perry R. Cook.  All rights reserved.    http://chuck.stanford.edu/    http://chuck.cs.princeton.edu/   This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 2 of the License, or  (at your option) any later version.   This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.   You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: ulib_ai.cpp// desc: Music and AI class library; part of ChAI (ChucK for AI)//// date: Fall 2022 -- present// authors: Ge Wang (ge@ccrma.stanford.edu)//          Yikai Li (yikaili@stanford.edu)//// (HISTORICAL NOTE)// Much of ChAI and its ways of thinking and doing can be foundationally// attributed to the work of Dr. Rebecca Fiebrink, her landmark Ph.D. Thesis,// /Real-time Human Interaction With Supervised Learning Algorithms for Music// Composition and Performance/ (2011) [1], the Wekinator framework [2], her// teaching at the intersections of AI, HCI, and Music [3], as well as earlier// collaborations between Rebecca and Ge [4,5] including SMIRK [6] (Small Musical// Information Retrieval toolKit; 2008; MARSYAS and the MIR work of Dr. George// Tzanetakis; early efforts in on-the-fly learning), the unit analyzer// framework [7] (2007; afford real-time audio feature extraction). All of// these have directly or indirectly contributed the creation of ChAI.// Additionally, ChAI benefitted from the teaching and design philosophy of// Dr. Perry R. Cook (Ph.D. advisor to Rebecca, George, and Ge at Princeton,// and ChucK co-author), who argued for real-time human interaction, parametric// sound synthesis, and the importance of play in the design of musical tools.//// [1] Fiebrink, Rebecca. 2011. /Real-time Human Interaction With Supervised// Learning Algorithms for Music Composition and Performance/ Ph.D. Thesis.// Princeton University. https://www.cs.princeton.edu/techreports/2010/891.pdf//// [2] http://www.wekinator.org/// Wekinator | Software for real-time, interactive machine learning//// [3] Fiebrink, Rebecca. "Machine Learning for Musicians and Artists" MOOC// https://www.kadenze.com/courses/machine-learning-for-musicians-and-artists/info//// [4] Fiebrink, R., G. Wang, P. R. Cook. 2008. "Foundations for On-the-fly// Learning in the ChucK Programming Language." /International Computer Music// Conference/. https://mcd.stanford.edu/publish/files/2008-icmc-learning.pdf//// [5] Fiebrink, R., G. Wang, P. R. Cook. 2008. "Support for Music Information// Retrieval in the ChucK Programming Language." /International Conference// on Music Information Retrieval/ (ISMIR).// https://mcd.stanford.edu/publish/files/2008-ismir-proto.pdf//// [6] http://smirk.cs.princeton.edu/// sMIRk | Small Music Information Retrieval toolKit//// [7] Tzanetakis, G. and P. R. Cook. 2000 "MARSYAS: A Framework for Audio// Analysis." Organised Sound. 4:(3)//// [8] Tzanetakis, G. and P. R. Cook. 2002 "Musical Genre Classification of// Audio Signals." IEEE Transaction on Speech and Audio Processing. 10(5).//// [9] Wang, G., R. Fiebrink, P. R. Cook. 2007. "Combining Analysis and// Synthesis in the ChucK Programming Language." /International Computer// Music Conference/. https://mcd.stanford.edu/publish/files/2007-icmc-uana.pdf//-----------------------------------------------------------------------------#include "ulib_ai.h"#include "chuck_type.h"#include "chuck_instr.h"#include "chuck_vm.h"#include "chuck_errmsg.h"#include "util_string.h"#include <math.h> #include <string>#include <vector>#include <map>#include <iostream>#include <fstream>using namespace std; // global model typestatic t_CKINT g_mt_mlp = 0;static t_CKINT g_mt_knn = 1;static t_CKINT g_mt_svm = 2;static t_CKINT g_mt_lr = 3;static t_CKINT g_mt_pr = 4;static t_CKINT g_mt_dt = 5;static t_CKINT g_mt_boost = 6;static t_CKINT g_mt_naivebayes = 7;// global activation typestatic t_CKINT g_at_linear = 0;static t_CKINT g_at_sigmoid = 1;static t_CKINT g_at_relu = 2;static t_CKINT g_at_tanh = 3;static t_CKINT g_at_softmax = 4;// global task typestatic t_CKINT g_tt_regression = -1;static t_CKINT g_tt_classification = -2;   // 1.4.2.0 (yikai) added SVMCK_DLL_CTOR( SVM_ctor );CK_DLL_DTOR( SVM_dtor );CK_DLL_MFUN( SVM_train );CK_DLL_MFUN( SVM_predict );// offsetstatic t_CKUINT SVM_offset_data = 0; // 1.4.2.0 (yikai) added KNNCK_DLL_CTOR( KNN_ctor );CK_DLL_DTOR( KNN_dtor );CK_DLL_MFUN( KNN_train );CK_DLL_MFUN( KNN_search );CK_DLL_MFUN( KNN_search2 );CK_DLL_MFUN( KNN_weigh );// 1.4.2.1 (yikai) added KNN2CK_DLL_CTOR( KNN2_ctor );CK_DLL_DTOR( KNN2_dtor );CK_DLL_MFUN( KNN2_train );CK_DLL_MFUN( KNN2_predict );CK_DLL_MFUN( KNN2_search );CK_DLL_MFUN( KNN2_search2 );CK_DLL_MFUN( KNN2_search3 );CK_DLL_MFUN( KNN2_weigh );// offsetstatic t_CKUINT KNN_offset_data = 0;static t_CKUINT KNN2_offset_data = 0; // 1.4.2.0 (yikai) added HMMCK_DLL_CTOR( HMM_ctor );CK_DLL_DTOR( HMM_dtor );CK_DLL_MFUN( HMM_init );CK_DLL_MFUN( HMM_train );CK_DLL_MFUN( HMM_generate );// offsetstatic t_CKUINT HMM_offset_data = 0; // 1.4.2.1 (yikai) added Word2VecCK_DLL_CTOR( Word2Vec_ctor );CK_DLL_DTOR( Word2Vec_dtor );CK_DLL_MFUN( Word2Vec_load );CK_DLL_MFUN( Word2Vec_load2 );CK_DLL_MFUN( Word2Vec_getMostSimilarByWord );CK_DLL_MFUN( Word2Vec_getMostSimilarByVector );CK_DLL_MFUN( Word2Vec_getVector );CK_DLL_MFUN( Word2Vec_getDictionarySize );CK_DLL_MFUN( Word2Vec_getDictionaryDim );CK_DLL_MFUN( Word2Vec_getUseKDTree );CK_DLL_MFUN( Word2Vec_getDimMinMax );CK_DLL_MFUN( Word2Vec_contains );// offsetstatic t_CKUINT Word2Vec_offset_data = 0; // 1.4.2.0 (yikai) added PCACK_DLL_CTOR( PCA_ctor );CK_DLL_DTOR( PCA_dtor );CK_DLL_SFUN( PCA_reduce );// offsetstatic t_CKUINT PCA_offset_data = 0; // 1.4.2.1 (yikai) added WekinatorCK_DLL_CTOR( Wekinator_ctor );CK_DLL_DTOR( Wekinator_dtor );CK_DLL_MFUN( Wekinator_set_num_inputs );CK_DLL_MFUN( Wekinator_get_num_inputs );CK_DLL_MFUN( Wekinator_set_num_outputs );CK_DLL_MFUN( Wekinator_get_num_outputs );CK_DLL_MFUN( Wekinator_set_task_type );CK_DLL_MFUN( Wekinator_get_task_type );CK_DLL_MFUN( Wekinator_get_task_type_name );CK_DLL_MFUN( Wekinator_set_property );CK_DLL_MFUN( Wekinator_set_property1 );CK_DLL_MFUN( Wekinator_get_property_int );CK_DLL_MFUN( Wekinator_get_property_float );CK_DLL_MFUN( Wekinator_set_model_type );CK_DLL_MFUN( Wekinator_get_model_type );CK_DLL_MFUN( Wekinator_get_model_type_name );CK_DLL_MFUN( Wekinator_set_output_property );CK_DLL_MFUN( Wekinator_get_output_property_int );CK_DLL_MFUN( Wekinator_set_output_property1 );CK_DLL_MFUN( Wekinator_set_output_property2 );CK_DLL_MFUN( Wekinator_get_output_property_int1 );CK_DLL_MFUN( Wekinator_get_output_property_float );CK_DLL_MFUN( Wekinator_set_output_property3 );CK_DLL_MFUN( Wekinator_get_output_property );CK_DLL_MFUN( Wekinator_set_inputs );CK_DLL_MFUN( Wekinator_set_outputs );CK_DLL_MFUN( Wekinator_randomize_outputs );CK_DLL_MFUN( Wekinator_get_num_obs );CK_DLL_MFUN( Wekinator_get_num_obs1 );CK_DLL_MFUN( Wekinator_get_obs );CK_DLL_MFUN( Wekinator_get_obs1 );CK_DLL_MFUN( Wekinator_clear_obs );CK_DLL_MFUN( Wekinator_clear_obs1 );CK_DLL_MFUN( Wekinator_save );CK_DLL_MFUN( Wekinator_load );CK_DLL_MFUN( Wekinator_export_obs );CK_DLL_MFUN( Wekinator_export_obs1 );CK_DLL_MFUN( Wekinator_import_obs );CK_DLL_MFUN( Wekinator_clear_all_obs );CK_DLL_MFUN( Wekinator_clear_all_obs1 );CK_DLL_MFUN( Wekinator_set_all_record_status );CK_DLL_MFUN( Wekinator_set_output_record_status );CK_DLL_MFUN( Wekinator_get_output_record_status );CK_DLL_MFUN( Wekinator_set_all_run_status );CK_DLL_MFUN( Wekinator_set_output_run_status );CK_DLL_MFUN( Wekinator_get_output_run_status );CK_DLL_MFUN( Wekinator_add );CK_DLL_MFUN( Wekinator_add1 );CK_DLL_MFUN( Wekinator_add2 );CK_DLL_MFUN( Wekinator_next_round );CK_DLL_MFUN( Wekinator_train );CK_DLL_MFUN( Wekinator_predict );CK_DLL_MFUN( Wekinator_delete_last_round );CK_DLL_MFUN( Wekinator_clear );CK_DLL_MFUN( Wekinator_get_round );CK_DLL_MFUN( Wekinator_get_all_record_status );CK_DLL_MFUN( Wekinator_get_all_run_status );// offsetstatic t_CKUINT Wekinator_offset_data = 0; // 1.4.2.0 (yikai) added MLPCK_DLL_CTOR( MLP_ctor );CK_DLL_DTOR( MLP_dtor );CK_DLL_MFUN( MLP_init );CK_DLL_MFUN( MLP_init2 );CK_DLL_MFUN( MLP_init3 );CK_DLL_MFUN( MLP_train );CK_DLL_MFUN( MLP_train2 );CK_DLL_MFUN( MLP_predict );CK_DLL_MFUN( MLP_get_weights );CK_DLL_MFUN( MLP_get_biases );CK_DLL_MFUN( MLP_get_gradients );CK_DLL_MFUN( MLP_get_activations );CK_DLL_MFUN( MLP_forward );CK_DLL_MFUN( MLP_backprop );CK_DLL_MFUN( MLP_save );CK_DLL_MFUN( MLP_load );CK_DLL_SFUN( MLP_shuffle );// offsetstatic t_CKUINT MLP_offset_data = 0;   //-----------------------------------------------------------------------------// name: libai_query()// desc: add class definition to chuck internal type system//-----------------------------------------------------------------------------DLL_QUERY libai_query( Chuck_DL_Query * QUERY ){    // get environment reference    Chuck_Env * env = QUERY->env();    // set module name    QUERY->setname( QUERY, "AI" );    // model type    // add class    QUERY->begin_class( QUERY, "AI", "Object" );    // add documentatiopn    QUERY->doc_class( QUERY, "AI class library." );    // add svar    QUERY->add_svar( QUERY, "int", "MLP", TRUE, &g_mt_mlp );    QUERY->doc_var( QUERY, "Model type: Multi-layer perceptron" );    QUERY->add_svar( QUERY, "int", "KNN", TRUE, &g_mt_knn );    QUERY->doc_var( QUERY, "Model type: K-nearest neighbor" );    QUERY->add_svar( QUERY, "int", "SVM", TRUE, &g_mt_svm );    QUERY->doc_var( QUERY, "Model type: Support vector machine" );    QUERY->add_svar( QUERY, "int", "LR", TRUE, &g_mt_lr );    QUERY->doc_var( QUERY, "Model type: Logistic regression" );    QUERY->add_svar( QUERY, "int", "PR", TRUE, &g_mt_pr );    QUERY->doc_var( QUERY, "Model type: Polynomial regression" );    QUERY->add_svar( QUERY, "int", "DT", TRUE, &g_mt_dt );    QUERY->doc_var( QUERY, "Model type: Decision tree" );    QUERY->add_svar( QUERY, "int", "BOOST", TRUE, &g_mt_boost );    QUERY->doc_var( QUERY, "Model type: Boosting" );    QUERY->add_svar( QUERY, "int", "NAIVEBAYES", TRUE, &g_mt_naivebayes );    QUERY->doc_var( QUERY, "Model type: Naive Bayes" );    QUERY->add_svar( QUERY, "int", "ReLU", TRUE, &g_at_relu );    QUERY->doc_var( QUERY, "Activation type: ReLU" );    QUERY->add_svar( QUERY, "int", "Sigmoid", TRUE, &g_at_sigmoid );    QUERY->doc_var( QUERY, "Activation type: Sigmoid" );    QUERY->add_svar( QUERY, "int", "Tanh", TRUE, &g_at_tanh );    QUERY->doc_var( QUERY, "Activation type: Tanh" );    QUERY->add_svar( QUERY, "int", "Softmax", TRUE, &g_at_softmax );    QUERY->doc_var( QUERY, "Activation type: Softmax" );    QUERY->add_svar( QUERY, "int", "Linear", TRUE, &g_at_linear );    QUERY->doc_var( QUERY, "Activation type: Linear" );    QUERY->add_svar( QUERY, "int", "Regression", TRUE, &g_tt_regression );    QUERY->doc_var( QUERY, "Task type: Regression" );    QUERY->add_svar( QUERY, "int", "Classification", TRUE, &g_tt_classification );    QUERY->doc_var( QUERY, "Task type: Classification" );    // done    QUERY->end_class( QUERY );      // function    Chuck_DL_Func * func = NULL;    // documentation string    std::string doc;     //---------------------------------------------------------------------    // init as base class: SVM    // 1.4.1.2 added by Yikai Li, Fall 2022    //---------------------------------------------------------------------    // doc string    doc = "a support vector machine (SVM) utility trains a model and predicts output based on new input";     // begin class definition    if( !type_engine_import_class_begin( env, "SVM", "Object", env->global(), SVM_ctor, SVM_dtor, doc.c_str() ) )        return FALSE;     // data offset    SVM_offset_data = type_engine_import_mvar( env, "int", "@SVM_data", FALSE );    if( SVM_offset_data == CK_INVALID_OFFSET ) goto error;     // train    func = make_new_mfun( "int", "train", SVM_train );    func->add_arg( "float[][]", "x" );    func->add_arg( "float[][]", "y" );    func->doc = "Train the SVM model with the given samples 'x' and 'y'.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // predict    func = make_new_mfun( "int", "predict", SVM_predict );    func->add_arg( "float[]", "x" );    func->add_arg( "float[]", "y" );    func->doc = "Predict the output 'y' given the input 'x'.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // end the class import    type_engine_import_class_end( env );     //---------------------------------------------------------------------    // init as base class: KNN    // 1.4.1.2 added by Yikai Li, Fall 2022    //---------------------------------------------------------------------    // doc string    doc =        "a basic k-NN utility that searches for k nearest neighbors from a set of observations / feature vectors. (Also see KNN2. The differrence between KNN and KNN2 is that KNN does not deal with labels whereas KNN2 is designed to work with labels.)";     // begin class definition    if( !type_engine_import_class_begin( env, "KNN", "Object", env->global(), KNN_ctor, KNN_dtor, doc.c_str() ) )        return FALSE;     // data offset    KNN_offset_data = type_engine_import_mvar( env, "int", "@KNN_data", FALSE );    if( KNN_offset_data == CK_INVALID_OFFSET ) goto error;     // train    func = make_new_mfun( "int", "train", KNN_train );    func->add_arg( "float[][]", "x" );    func->doc = "Train the KNN model with the given observations 'x'";    if( !type_engine_import_mfun( env, func ) ) goto error;     // search    func = make_new_mfun( "void", "search", KNN_search );    func->add_arg( "float[]", "query" );    func->add_arg( "int", "k" );    func->add_arg( "int[]", "indices" );    func->doc = "Search for the 'k' nearest neighbors of 'query' and return their corresponding indices.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // search    func = make_new_mfun( "void", "search", KNN_search2 );    func->add_arg( "float[]", "query" );    func->add_arg( "int", "k" );    func->add_arg( "int[]", "indices" );    func->add_arg( "float[][]", "observations" );    func->doc =        "Search for the 'k' nearest neighbors of 'query' and return their corresponding indices and observations";    if( !type_engine_import_mfun( env, func ) ) goto error;     // weigh    func = make_new_mfun( "void", "weigh", KNN_weigh );    func->add_arg( "float[]", "weights" );    func->doc = "Set the weights for each dimension in the data.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // end the class import    type_engine_import_class_end( env );     //---------------------------------------------------------------------    // init as base class: KNN2    // 1.4.1.2 added by Yikai Li, Fall 2022    //---------------------------------------------------------------------    // doc string    doc =        "a k-NN utility that predicts probabilities of class membership based on distances from a test input to its k nearest neighbors. (Also see KNN. The differrence between KNN and KNN2 is that KNN does not deal with labels whereas KNN2 is designed to work with labels.)";     // begin class definition    if( !type_engine_import_class_begin( env, "KNN2", "Object", env->global(), KNN2_ctor, KNN2_dtor, doc.c_str() ) )        return FALSE;     // data offset    KNN_offset_data = type_engine_import_mvar( env, "int", "@KNN2_data", FALSE );    if( KNN_offset_data == CK_INVALID_OFFSET ) goto error;     // train    func = make_new_mfun( "int", "train", KNN2_train );    func->add_arg( "float[][]", "x" );    func->add_arg( "int[]", "labels" );    func->doc = "Train the KNN model with the given observations 'x' and corresponding labels.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // predict    func = make_new_mfun( "int", "predict", KNN2_predict );    func->add_arg( "float[]", "query" );    func->add_arg( "int", "k" );    func->add_arg( "float[]", "prob" );    func->doc =        "Predict the output probabilities 'prob' given unlabeled test input 'query' based on distances to 'k' nearest neighbors.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // search    func = make_new_mfun( "void", "search", KNN2_search );    func->add_arg( "float[]", "query" );    func->add_arg( "int", "k" );    func->add_arg( "int[]", "labels" );    func->doc = "Search for the 'k' nearest neighbors of 'query' and return their labels.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // search    func = make_new_mfun( "void", "search", KNN2_search2 );    func->add_arg( "float[]", "query" );    func->add_arg( "int", "k" );    func->add_arg( "int[]", "labels" );    func->add_arg( "int[]", "indices" );    func->doc =        "Search for the 'k' nearest neighbors of 'query' and return their labels and indices.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // search    func = make_new_mfun( "void", "search", KNN2_search3 );    func->add_arg( "float[]", "query" );    func->add_arg( "int", "k" );    func->add_arg( "int[]", "labels" );    func->add_arg( "int[]", "indices" );    func->add_arg( "float[][]", "observations" );    func->doc =        "Search for the 'k' nearest neighbors of 'query' and return their labels, indices, and observations.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // weigh    func = make_new_mfun( "void", "weigh", KNN2_weigh );    func->add_arg( "float[]", "weights" );    func->doc = "Set the weights for each dimension in the data.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // end the class import    type_engine_import_class_end( env );     //---------------------------------------------------------------------    // init as base class: HMM    // 1.4.1.2 added by Yikai Li, Fall 2022    //---------------------------------------------------------------------    // doc string    doc = "a hidden markov model (HMM) utility that generates a sequence of observations based on the training data.";     // begin class definition    if( !type_engine_import_class_begin( env, "HMM", "Object", env->global(), HMM_ctor, HMM_dtor, doc.c_str() ) )        return FALSE;     // data offset    HMM_offset_data = type_engine_import_mvar( env, "int", "@HMM_data", FALSE );    if( HMM_offset_data == CK_INVALID_OFFSET ) goto error;     // init    func = make_new_mfun( "int", "load", HMM_init );    func->add_arg( "float[]", "initiailDistribution" );    func->add_arg( "float[][]", "transitionMatrix" );    func->add_arg( "float[][]", "emissionMatrix" );    func->doc =        "Initialize the HMM model with the given initial state distribution, transition matrix, and emission matrix.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // train    func = make_new_mfun( "int", "train", HMM_train );    func->add_arg( "int", "numStates" );    func->add_arg( "int", "numEmissions" );    func->add_arg( "int[]", "observations" );    func->doc = "Train the HMM model with the given observations.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // generate    func = make_new_mfun( "int", "generate", HMM_generate );

Lines 1–500 of 6928.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t