日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

项目笔记(一):实验——用神经网络实现midi音乐旋律音轨的确定

發布時間:2024/3/12 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 项目笔记(一):实验——用神经网络实现midi音乐旋律音轨的确定 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

零、寫在前面

計劃要用seq2seq模型做一個交響樂編曲程序,encoder network的輸入是一個樂句旋律,decoder network的目標target是這個樂句完整的管弦配樂版本。本文記錄的實驗的目的是自動提取出midi樂句的旋律音軌。

一、原理

參考這篇文獻中的方法:提取出這個樂句中各個音軌(樂器)的以下特征:

  • 平均力度
  • 所有音符累加總時值
  • 時值類型
  • 最高音與最低音之間的音程
  • 第二高音與第二低音之間的音程
  • 每個音軌的五個特征疊在一起,作為一個樂句的神經網絡輸入。
    對應于主旋律的音軌的one-hot向量作為神經網絡的目標輸出。

    之前文獻中,使用了其他的特征作為輸入,但那些特征并不十分合理。

    二、技術細節

    1.midi_to_features.py

    這個文件用于提取出一個樂句各個音軌的5個特征值,用了python的pretty_midi包作為處理midi文件的工具。

    import pretty_mididef get_avg_velocity(instrument):# 平均力度velocity = 0for note in instrument.notes:velocity += note.velocityvelocity /= len(instrument.notes)return velocitydef get_sum_duration(instrument):# 所有音符累加總時值duration = 0for note in instrument.notes:duration += note.end - note.startreturn durationdef get_types_of_duration(instrument):# 時值類型duration = []for note in instrument.notes:duration.append(note.end - note.start)types = len(set(duration))return typesdef get_pitch_range(instrument):# 最高音與最低音之間的音程pitch = []for note in instrument.notes:pitch.append( note.pitch )sorted_pitch = sorted( set(pitch) )range = sorted_pitch[-1] - sorted_pitch[0]return rangedef get_second_pitch_range(instrument):# 第二高音與第二低音之間的音程pitch = []for note in instrument.notes:pitch.append( note.pitch )sorted_pitch = sorted( set(pitch) )range = sorted_pitch[-2] - sorted_pitch[1]return range

    上面的代碼中五個函數對應于提取一個樂句中某一音軌(樂器)的五個特征值。
    我們接下來將每一個音軌(樂器)的這五個值,壓縮到到一個向量中。

    def get_train_example(midi_file):pm = pretty_midi.PrettyMIDI( midi_file=midi_file )train_example = []for instrument in pm.instruments:train_example.append(get_avg_velocity(instrument))train_example.append(get_sum_duration(instrument))train_example.append(get_types_of_duration(instrument))train_example.append(get_pitch_range(instrument))train_example.append(get_second_pitch_range(instrument))return train_example

    接下來還要寫函數來遍歷數據集,提取出各個midi樂句的(一個樂句一個midi文件)特征值。將他們疊在一起,作為訓練集的輸入。

    def get_X_train():X_train = [[]]for i in range(13): # 一共切取了14個midi片段,其中13個作為訓練樣本midi_file = 'data/x'+str(i+1)+'.mid'train_example = get_train_example(midi_file)if i==0:X_train[0]=train_exampleelse:X_train.append(train_example)return X_train

    類似地,再寫測試集:

    def get_X_test():X_test = [[]]midi_file = 'data/x14.mid'train_example = get_train_example(midi_file)X_test[0]=train_examplereturn X_test

    2. features_to_melody.py

    這個文件里用tensorflow構建一個二層神經網絡,用matplotlib繪圖。我們使用鋼琴曲作為數據集,左右手各一個音軌,每個音軌5個特征值,所以一個樂句共有10個特征值。對應的y值顯然也只有兩種可能。

    from midi_to_features import * import tensorflow as tf import matplotlib.pyplot as plt import numpy as npn_x, n_y = 10, 2

    接下來我們制作訓練集和測試集的輸入和輸出,我使用的數據中都是旋律再右手的,所以所有的輸出都相同。

    # get training data X_train = get_X_train() Y_example = [1, 0] Y_train = [[]] for i in range (13):if i == 0:Y_train[0] = Y_exampleelse:Y_train.append( Y_example )#行列互換,使其符合tensorflow的輸入格式 X_train = list(map(list, zip(*X_train))) Y_train = list(map(list, zip(*Y_train))) print("X_train:", X_train) print("Y_train:", Y_train)# get testing data X_test = get_X_test() X_test = list(map(list, zip(*X_test))) Y_test = [[1],[0]] print("X_test:", X_test) print("Y_test:", Y_test)

    接下來是構建神經網絡的準備工作:創建placeholder和初始化參數(用xavier來初始化所有w,用全零初始化b)。

    # Create placeholders def create_placeholders(n_x, n_y):X = tf.placeholder(tf.float32, shape=[n_x, None])Y = tf.placeholder(tf.float32, shape=[n_y, None])return X, Y# Initialize the parameters def initialize_parameters():W1 = tf.get_variable("W1", [25, n_x], initializer=tf.contrib.layers.xavier_initializer())b1 = tf.get_variable("b1", [25, 1], initializer=tf.zeros_initializer())W2 = tf.get_variable("W2", [12, 25], initializer=tf.contrib.layers.xavier_initializer())b2 = tf.get_variable("b2", [12, 1], initializer=tf.zeros_initializer())W3 = tf.get_variable("W3", [n_y, 12], initializer=tf.contrib.layers.xavier_initializer())b3 = tf.get_variable("b3", [n_y, 1], initializer=tf.zeros_initializer())parameters = {"W1": W1,"b1": b1,"W2": W2,"b2": b2,"W3": W3,"b3": b3}return parameters

    神經網絡的正向傳播,激活函數使用relu。

    # Forward propagation def forward_propagation(X, parameters):W1 = parameters['W1']b1 = parameters['b1']W2 = parameters['W2']b2 = parameters['b2']W3 = parameters['W3']b3 = parameters['b3']Z1 = tf.add(tf.matmul(W1, X), b1)A1 = tf.nn.relu(Z1)Z2 = tf.add(tf.matmul(W2, A1), b2)A2 = tf.nn.relu(Z2)Z3 = tf.add(tf.matmul(W3, A2), b3)return Z3

    使用softmax作為輸出層,定義交叉熵損失。

    # Compute Cost def compute_cost(Z3, Y):logits = tf.transpose(Z3)labels = tf.transpose(Y)cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = logits, labels = labels))return cost

    現在我們可以開始構建整個模型了。

    # the model def model(X_train, Y_train, X_test, Y_test,learning_rate = 0.0001, num_epochs = 1000,print_cost = True):n_x, n_y, = 10, 2, 13costs = []# 創建placeholderX, Y = create_placeholders(n_x, n_y)# 初始化參數parameters = initialize_parameters()# 神經網絡前向傳播Z3 = forward_propagation(X, parameters)# 計算損失函數cost = compute_cost(Z3, Y)#用adam算法最小化損失函數optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)init = tf.global_variables_initializer()# 創建tensorflow的sessionwith tf.Session() as sess:sess.run(init)for epoch in range(num_epochs):_, Cost = sess.run([optimizer, cost], feed_dict={X: X_train, Y: Y_train})# 打印出cost的變化if print_cost == True and epoch % 100 == 0:print ("Cost after epoch %i: %f" % (epoch, Cost))costs.append(Cost)# 用matplotlib繪制 時間-損失圖像plt.plot(np.squeeze(costs))plt.ylabel('cost')plt.xlabel('iterations (per tens)')plt.title("Learning rate =" + str(learning_rate))plt.show()parameters = sess.run(parameters)print ("Parameters have been trained!")correct_prediction = tf.equal(tf.argmax(Z3), tf.argmax(Y))# 計算準確率accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))print("Train Accuracy:", accuracy.eval({X: X_train, Y: Y_train}))print("Test Accuracy:", accuracy.eval({X: X_test, Y: Y_test}))return parametersparameters = model(X_train, Y_train, X_test, Y_test)

    3.數據集

    這個實驗只是為了驗證可行性,用了很小很小的數據集(對應無比強烈的過擬合)。我手工提取了莫扎特土耳其進行曲(這是我寫過的這首曲子的樂理分析)的一共14旋律材料(14個樂句)。13個作為訓練集,最后一個作為測試集。他們可以在這里下載。

    我使用的是降b小調的版本,但樂句整體的移調不會影響輸出,所以,never mind。

    三、結論

    Cost after epoch 0: 9.850606 Cost after epoch 100: 0.593675 Cost after epoch 200: 0.267264 Cost after epoch 300: 0.170038 Cost after epoch 400: 0.108876 Parameters have been trained! Train Accuracy: 1.0 Test Accuracy: 1.0

    我們看到,神經網絡對于訓練集擬合地很好,正確率100%(其實是過擬合),測試樣本Test Accuracy: 1.0,即算法正確地分類了測試樣本。

    這說明,用神經網絡實現midi音樂旋律音軌的確定,這一方法是可行的。

    總結

    以上是生活随笔為你收集整理的项目笔记(一):实验——用神经网络实现midi音乐旋律音轨的确定的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。