-
Notifications
You must be signed in to change notification settings - Fork 0
/
train.py
128 lines (117 loc) · 4.33 KB
/
train.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# THEANO_FLAGS=device=gpu,floatX=float32 python train.py
# bug: training length should be larger than batch size
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
from keras.layers import LSTM
from keras.utils.data_utils import get_file
from keras.models import load_model
import numpy as np
import random
import sys
import copy
import time
import re
import pysynth
### Define some constants
maxlen = 16 # The length of LSTM
epochs = 50
### Read the file and put the music into a list
def splitMusic(file_name = "dataset/data.txt"):
print("...Reading file %s and count the number of songs..." %(file_name))
with open(file_name, "r") as f:
m = f.readlines()
print ("%d songs found." %(len(m)))
m = [re.split('[\[\],\s\']*', p)[1:-1] for p in m]
return m
### Make the dict from index to length¬e and reverse
def makeDict(melody):
print("...Making the dict from index to length¬e and reverse...")
l = set()
n = set()
for melo in melody:
l = l | set(melo[1 : : 2])
n = n | set(melo[0 : : 2])
print ("%d type of note duration" %(len(l)))
print ("%d type of notes" %(len(n)))
dic_size = len(l) * len(n)
print ("input dict length: %d" %(dic_size))
m_to_i = {}
i_to_m = {}
count = 0
for a in l:
for b in n:
m_to_i[a + '\t' + b] = count
i_to_m[count] = a + '\t' + b
count += 1
return m_to_i, i_to_m, dic_size
### Form the training sets
def makeTrainset(melody, m_to_i):
print("...Making the training set...")
X = []
y = []
for i,melo in enumerate(melody):
ind = [m_to_i[melo[2*i+1] + '\t' + melo[2*i]] for i in range(len(melo) // 2)]
for i in range(len(ind) - maxlen):
X.append(ind[i : i + maxlen])
y.append(ind[i + maxlen])
dic_size = len(m_to_i)
X_train = np.zeros((len(X), maxlen, dic_size), dtype=np.bool)
y_train = np.zeros((len(X), dic_size), dtype=np.bool)
for i, m in enumerate(X):
for t, n in enumerate(m):
X_train[i, t, n] = 1
y_train[i, y[i]] = 1
# print ("Training set size: X_train", X_train.shape)
# print ("Training set size: y_train", y_train.shape)
return X_train, y_train
### Make the LSTM-model and training
def trainModel(X_train, y_train, seq_length, dic_size):
print ("...Making the LSTM-model...")
model = Sequential()
model.add(LSTM(512, return_sequences=True, input_shape=(seq_length, dic_size)))
model.add(Dropout(0.2))
model.add(LSTM(512, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(dic_size))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
print ("...Start training...")
model.fit(X_train, y_train, batch_size=256, nb_epoch=epochs)
return model
### Predict the output notes with feedin and write it out to music_out.txt
def predict(model, feedin, len, i_to_m):
predi = [list(f).index(True) for f in feedin]
m = copy.deepcopy(feedin)
for i in range(len):
y = model.predict(np.array([m]))
note = list(y[0]).index(max(y[0]))
predi.append(note)
n = copy.deepcopy(m)
n[0 : maxlen - 1] = m[1 : ]
n[-1] = np.zeros(dic_size, dtype=np.bool)
n[-1][note] = 1
m = n
# localtime = time.asctime( time.localtime(time.time()) )
# print("...Writing file back to %s" %("music_out_" + localtime+ ".txt"))
# with open("music_out_" + localtime+ ".txt", "w") as f:
# for i in predi:
# f.write(i_to_m[i] + '\t')
return(predi)
### The main program
melody = splitMusic("dataset/demo.txt")
melo_to_index, index_to_melo, dic_size = makeDict(melody)
X, y = makeTrainset(melody, melo_to_index)
# Use part to train and part as trigger to create music
X_train, y_train, X_test, y_test = X[0:90000], y[0:90000], X[-20000:], y[-20000:]
print ("Training set size: X_train", X_train.shape)
print ("Training set size: y_train", y_train.shape)
model = trainModel(X_train, y_train, maxlen, dic_size)
print ("..Training has finished...")
### Uncomment to save the model, for usage, please refer to Keras FAQ
# model.save('trained_model/demo.h5')
### Compose the music and save
comp = [predict(model, X_test[i], 200, index_to_melo) for i in range(0,20000,1000)]
wave = [[index_to_melo[i] for i in c] for c in comp]
wave = [[[m.split()[1], float(m.split()[0])] for m in w] for w in wave]
for i,w in enumerate(wave):
pysynth.make_wav(w, fn = "composed_melody/demo/demox"+str(i)+".wav")