gru作曲机使用midi作曲 pytorch代码
时间: 2024-02-28 13:48:49 浏览: 31
根据提供的引用内容,我们可以使用PyTorch构建GRU模型来生成MIDI音乐。以下是一个简单的示例代码:
```python
import torch
import torch.nn as nn
import numpy as np
from music21 import *
# 定义GRU模型
class GRUNet(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers):
super(GRUNet, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.gru = nn.GRU(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x, h):
out, h = self.gru(x, h)
out = self.fc(out[:, -1, :])
return out, h
def init_hidden(self, batch_size):
return torch.zeros(self.num_layers, batch_size, self.hidden_size)
# 加载MIDI文件
def load_midi(file_path):
midi = converter.parse(file_path)
notes = []
for element in midi.flat:
if isinstance(element, note.Note):
notes.append(str(element.pitch))
elif isinstance(element, chord.Chord):
notes.append('.'.join(str(n) for n in element.normalOrder))
return np.array(notes)
# 将MIDI文件转换为训练数据
def prepare_sequences(notes, n_vocab):
sequence_length = 100
pitchnames = sorted(set(item for item in notes))
note_to_int = dict((note, number) for number, note in enumerate(pitchnames))
network_input = []
network_output = []
for i in range(0, len(notes) - sequence_length, 1):
sequence_in = notes[i:i + sequence_length]
sequence_out = notes[i + sequence_length]
network_input.append([note_to_int[char] for char in sequence_in])
network_output.append(note_to_int[sequence_out])
n_patterns = len(network_input)
network_input = np.reshape(network_input, (n_patterns, sequence_length, 1))
network_input = network_input / float(n_vocab)
network_output = np.array(network_output)
return network_input, network_output
# 生成音乐
def generate_music(model, network_input, pitchnames, n_vocab):
start = np.random.randint(0, len(network_input)-1)
int_to_note = dict((number, note) for number, note in enumerate(pitchnames))
pattern = list(network_input[start])
prediction_output = []
for note_index in range(500):
input_sequence = np.reshape(pattern, (1, len(pattern), 1))
input_sequence = input_sequence / float(n_vocab)
prediction, _ = model(torch.Tensor(input_sequence), None)
index = np.argmax(prediction.detach().numpy())
result = int_to_note[index]
prediction_output.append(result)
pattern.append(index)
pattern = pattern[1:len(pattern)]
return prediction_output
# 加载训练数据
notes = load_midi('example.mid')
n_vocab = len(set(notes))
network_input, network_output = prepare_sequences(notes, n_vocab)
# 训练模型
input_size = 1
hidden_size = 128
output_size = n_vocab
num_layers = 2
batch_size = 128
learning_rate = 0.001
num_epochs = 100
model = GRUNet(input_size, hidden_size, output_size, num_layers)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for epoch in range(num_epochs):
for i in range(0, len(network_input), batch_size):
inputs = torch.Tensor(network_input[i:i+batch_size])
targets = torch.LongTensor(network_output[i:i+batch_size])
h = model.init_hidden(inputs.shape[0])
outputs, h = model(inputs, h)
loss = criterion(outputs, targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))
# 生成音乐
prediction_output = generate_music(model, network_input, sorted(set(notes)), n_vocab)
offset = 0
output_notes = []
for pattern in prediction_output:
if ('.' in pattern) or pattern.isdigit():
notes_in_chord = pattern.split('.')
notes = []
for current_note in notes_in_chord:
new_note = note.Note(int(current_note))
new_note.storedInstrument = instrument.Piano()
notes.append(new_note)
new_chord = chord.Chord(notes)
new_chord.offset = offset
output_notes.append(new_chord)
else:
new_note = note.Note(int(pattern))
new_note.offset = offset
new_note.storedInstrument = instrument.Piano()
output_notes.append(new_note)
offset += 0.5
midi_stream = stream.Stream(output_notes)
midi_stream.write('midi', fp='output.mid')
```