/*---------------------------------------------------------------------------- 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. Load more
/*---------------------------------------------------------------------------- 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 type static 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 type static 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 type static t_CKINT g_tt_regression = -1; static t_CKINT g_tt_classification = -2; // 1.4.2.0 (yikai) added SVM CK_DLL_CTOR( SVM_ctor ); CK_DLL_DTOR( SVM_dtor ); CK_DLL_MFUN( SVM_train ); CK_DLL_MFUN( SVM_predict ); // offset static t_CKUINT SVM_offset_data = 0; // 1.4.2.0 (yikai) added KNN CK_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 KNN2 CK_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 ); // offset static t_CKUINT KNN_offset_data = 0; static t_CKUINT KNN2_offset_data = 0; // 1.4.2.0 (yikai) added HMM CK_DLL_CTOR( HMM_ctor ); CK_DLL_DTOR( HMM_dtor ); CK_DLL_MFUN( HMM_init ); CK_DLL_MFUN( HMM_train ); CK_DLL_MFUN( HMM_generate ); // offset static t_CKUINT HMM_offset_data = 0; // 1.4.2.1 (yikai) added Word2Vec CK_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 ); // offset static t_CKUINT Word2Vec_offset_data = 0; // 1.4.2.0 (yikai) added PCA CK_DLL_CTOR( PCA_ctor ); CK_DLL_DTOR( PCA_dtor ); CK_DLL_SFUN( PCA_reduce ); // offset static t_CKUINT PCA_offset_data = 0; // 1.4.2.1 (yikai) added Wekinator CK_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 ); // offset static t_CKUINT Wekinator_offset_data = 0; // 1.4.2.0 (yikai) added MLP CK_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 ); // offset static 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 );