java audio embedding
1.0.0
Java 中的音訊嵌入
目前專案嘗試開發一個純Java音訊編碼器,可以在純Java或Android程式中使用。這樣的音訊編碼器可用於音樂類型分類或音樂搜尋或音樂推薦器。
目前項目包含兩個深度學習網絡,採用自:
這兩個模型的訓練和驗證如下圖所示:
Java中的機器學習包是tensorflow,它載入預先訓練的音訊分類器模型(.pb格式)。音訊分類器模型最初是使用 Python 中的 Keras 實現和訓練的。然後將訓練好的分類器模型(.h5 格式)轉換為 .pb 模型文件,該文件可以直接由 Java 中的 Tensorflow 載入。
音訊分類器模型的keras訓練可以在README_Training.md中找到
下面的範例程式碼展示如何使用 cifar 音訊分類器來預測音樂類型:
import com . github . chen0040 . tensorflow . classifiers . models . cifar10 . Cifar10AudioClassifier ;
import com . github . chen0040 . tensorflow . classifiers . utils . ResourceUtils ;
import org . slf4j . Logger ;
import org . slf4j . LoggerFactory ;
import java . io . File ;
import java . io . IOException ;
import java . io . InputStream ;
import java . util . ArrayList ;
import java . util . Collections ;
import java . util . List ;
public class Demo {
public static void main ( String [] args ) {
InputStream inputStream = ResourceUtils . getInputStream ( "tf_models/cifar10.pb" );
Cifar10AudioClassifier classifier = new Cifar10AudioClassifier ();
classifier . load_model ( inputStream );
List < String > paths = getAudioFiles ();
Collections . shuffle ( paths );
for ( String path : paths ) {
System . out . println ( "Predicting " + path + " ..." );
File f = new File ( path );
String label = classifier . predict_audio ( f );
System . out . println ( "Predicted: " + label );
}
}
}
下面的範例程式碼展示如何使用 resnet v2 音訊分類器來預測音樂類型:
import com . github . chen0040 . tensorflow . classifiers . resnet_v2 . ResNetV2AudioClassifier ;
import com . github . chen0040 . tensorflow . classifiers . utils . ResourceUtils ;
import org . slf4j . Logger ;
import org . slf4j . LoggerFactory ;
import java . io . File ;
import java . io . IOException ;
import java . io . InputStream ;
import java . util . ArrayList ;
import java . util . Collections ;
import java . util . List ;
public class Demo {
public static void main ( String [] args ) {
InputStream inputStream = ResourceUtils . getInputStream ( "tf_models/resnet-v2.pb" );
ResNetV2AudioClassifier classifier = new ResNetV2AudioClassifier ();
classifier . load_model ( inputStream );
List < String > paths = getAudioFiles ();
Collections . shuffle ( paths );
for ( String path : paths ) {
System . out . println ( "Predicting " + path + " ..." );
File f = new File ( path );
String label = classifier . predict_audio ( f );
System . out . println ( "Predicted: " + label );
}
}
}
下面的範例程式碼展示如何使用 cifar 音訊分類器將音訊檔案編碼為浮點陣列:
import com . github . chen0040 . tensorflow . classifiers . models . cifar10 . Cifar10AudioClassifier ;
import com . github . chen0040 . tensorflow . classifiers . utils . ResourceUtils ;
import org . slf4j . Logger ;
import org . slf4j . LoggerFactory ;
import java . io . File ;
import java . io . IOException ;
import java . io . InputStream ;
import java . util . ArrayList ;
import java . util . Collections ;
import java . util . List ;
public class Demo {
public static void main ( String [] args ){
InputStream inputStream = ResourceUtils . getInputStream ( "tf_models/cifar10.pb" );
Cifar10AudioClassifier classifier = new Cifar10AudioClassifier ();
classifier . load_model ( inputStream );
List < String > paths = getAudioFiles ();
Collections . shuffle ( paths );
for ( String path : paths ) {
System . out . println ( "Encoding " + path + " ..." );
File f = new File ( path );
float [] encoded_audio = classifier . encode_audio ( f );
System . out . println ( "Encoded: " + Arrays . toString ( encoded_audio ));
}
}
}
下面的範例程式碼展示如何使用 resnet v2 音訊分類器將音訊檔案編碼為浮點陣列:
import com . github . chen0040 . tensorflow . classifiers . resnet_v2 . ResNetV2AudioClassifier ;
import com . github . chen0040 . tensorflow . classifiers . utils . ResourceUtils ;
import org . slf4j . Logger ;
import org . slf4j . LoggerFactory ;
import java . io . File ;
import java . io . IOException ;
import java . io . InputStream ;
import java . util . ArrayList ;
import java . util . Collections ;
import java . util . List ;
public class Demo {
public static void main ( String [] args ) {
InputStream inputStream = ResourceUtils . getInputStream ( "tf_models/resnet-v2.pb" );
ResNetV2AudioClassifier classifier = new ResNetV2AudioClassifier ();
classifier . load_model ( inputStream );
List < String > paths = getAudioFiles ();
Collections . shuffle ( paths );
for ( String path : paths ) {
System . out . println ( "Encoding " + path + " ..." );
File f = new File ( path );
float [] encoded_audio = classifier . encode_audio ( f );
System . out . println ( "Encoded: " + Arrays . toString ( encoded_audio ));
}
}
}
下面的範例程式碼展示如何使用 AudioSearchEngine 類別索引和搜尋音訊檔案:
import com . github . chen0040 . tensorflow . search . models . AudioSearchEngine ;
import com . github . chen0040 . tensorflow . search . models . AudioSearchEntry ;
import java . io . File ;
import java . util . List ;
public class Demo {
public static void main ( String [] args ){
AudioSearchEngine searchEngine = new AudioSearchEngine ();
if (! searchEngine . loadIndexDbIfExists ()) {
searchEngine . indexAll ( FileUtils . getAudioFiles ());
searchEngine . saveIndexDb ();
}
int pageIndex = 0 ;
int pageSize = 20 ;
boolean skipPerfectMatch = true ;
File f = new File ( "mp3_samples/example.mp3" );
System . out . println ( "querying similar music to " + f . getName ());
List < AudioSearchEntry > result = searchEngine . query ( f , pageIndex , pageSize , skipPerfectMatch );
for ( int i = 0 ; i < result . size (); ++ i ){
System . out . println ( "# " + i + ": " + result . get ( i ). getPath () + " (distSq: " + result . get ( i ). getDistance () + ")" );
}
}
}
下面的範例程式碼展示如何使用 KnnAudioRecommender 類別根據使用者的音樂歷史推薦音樂:
import com . github . chen0040 . tensorflow . classifiers . utils . FileUtils ;
import com . github . chen0040 . tensorflow . recommenders . models . AudioUserHistory ;
import com . github . chen0040 . tensorflow . recommenders . models . KnnAudioRecommender ;
import com . github . chen0040 . tensorflow . search . models . AudioSearchEntry ;
import java . io . File ;
import java . util . Collections ;
import java . util . List ;
public class Demo {
public static void main ( String [] args ){
AudioUserHistory userHistory = new AudioUserHistory ();
List < String > audioFiles = FileUtils . getAudioFilePaths ();
Collections . shuffle ( audioFiles );
for ( int i = 0 ; i < 40 ; ++ i ){
String filePath = audioFiles . get ( i );
userHistory . logAudio ( filePath );
try {
Thread . sleep ( 100L );
} catch ( InterruptedException e ) {
e . printStackTrace ();
}
}
KnnAudioRecommender recommender = new KnnAudioRecommender ();
if (! recommender . loadIndexDbIfExists ()) {
recommender . indexAll ( new File ( "music_samples" ). listFiles ( a -> a . getAbsolutePath (). toLowerCase (). endsWith ( ".au" )));
recommender . saveIndexDb ();
}
System . out . println ( userHistory . head ( 10 ));
int k = 10 ;
List < AudioSearchEntry > result = recommender . recommends ( userHistory . getHistory (), k );
for ( int i = 0 ; i < result . size (); ++ i ){
AudioSearchEntry entry = result . get ( i );
System . out . println ( "Search Result #" + ( i + 1 ) + ": " + entry . getPath ());
}
}
}