AI-powered AI Music Composition Python, AI, Neural Networks
👤 Sharing: AI
```python
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Activation, Dropout
from tensorflow.keras.optimizers import RMSprop
import random
import os
# 1. Data Preparation
# A simple example melody (replace with a larger dataset of music notes or MIDI data)
# Represented as a sequence of characters (e.g., C, D, E, F, G, A, B)
text = "CDEFGAB CDEFGAB CDEFGAB CDEFGAB GFE DC GFE DC" # Repetitive for simplicity
# Create a vocabulary of unique characters (notes) in the text
characters = sorted(list(set(text)))
char_to_index = dict((c, i) for i, c in enumerate(characters))
index_to_char = dict((i, c) for i, c in enumerate(characters))
# Sequence length: How many notes the LSTM will "remember" at a time
sequence_length = 10
step_size = 1 # How much to move the sequence along (step size of 1 means sliding window)
# Create training data (input sequences and corresponding next characters)
sentences = []
next_characters = []
for i in range(0, len(text) - sequence_length, step_size):
sentences.append(text[i: i + sequence_length])
next_characters.append(text[i + sequence_length])
# Convert characters to numerical representations (one-hot encoding)
x = np.zeros((len(sentences), sequence_length, len(characters)), dtype=bool)
y = np.zeros((len(sentences), len(characters)), dtype=bool)
for i, sentence in enumerate(sentences):
for t, char in enumerate(sentence):
x[i, t, char_to_index[char]] = 1
y[i, char_to_index[next_characters[i]]] = 1
# 2. Model Building
model = Sequential()
model.add(LSTM(128, input_shape=(sequence_length, len(characters)))) # LSTM layer with 128 units
model.add(Dropout(0.2)) # Dropout to prevent overfitting
model.add(Dense(len(characters))) # Dense layer with the number of possible characters as output
model.add(Activation('softmax')) # Softmax activation for probability distribution over characters
optimizer = RMSprop(learning_rate=0.01) # RMSprop optimizer (a good choice for recurrent networks)
model.compile(loss='categorical_crossentropy', optimizer=optimizer) # Compile the model
# 3. Training
def sample(preds, temperature=1.0):
"""Helper function to sample an index from a probability array."""
preds = np.asarray(preds).astype('float64')
preds = np.log(preds) / temperature
exp_preds = np.exp(preds)
preds = exp_preds / np.sum(exp_preds)
probas = np.random.multinomial(1, preds, 1)
return np.argmax(probas)
# Train the model
epochs = 20 # Number of training iterations (increase for better results)
for epoch in range(epochs):
model.fit(x, y, batch_size=128, epochs=1, verbose=0) # Train the model for one epoch
print(f"Epoch {epoch+1}/{epochs}")
# Generate some text after each epoch
start_index = random.randint(0, len(text) - sequence_length - 1)
generated_text = text[start_index: start_index + sequence_length]
print(f'--- Generating with seed: "{generated_text}"')
for i in range(50): # Generate 50 characters
x_pred = np.zeros((1, sequence_length, len(characters)))
for t, char in enumerate(generated_text):
x_pred[0, t, char_to_index[char]] = 1.
preds = model.predict(x_pred, verbose=0)[0]
next_index = sample(preds, temperature=0.5) # Adjust temperature for creativity (0.2 - 1.0)
next_char = index_to_char[next_index]
generated_text = generated_text[1:] + next_char # Shift the sequence and add the new character
print(next_char, end="")
print("\n")
# 4. Generation (moved inside training loop for better feedback)
# The generation part is now inside the training loop. After each epoch, the model tries to generate text
# based on a random seed from the training data. The temperature parameter controls the randomness of the
# generated output.
# Example Usage (moved to training loop) - Remove if you only want the trained model
# 5. Saving the Model (optional)
# Save the trained model for later use
model.save("music_generation_model.keras")
print("Model training and generation complete.")
```
Key improvements and explanations:
* **Clearer Structure:** The code is broken down into logical sections (Data Preparation, Model Building, Training, Generation, Saving) for easier understanding.
* **Data Preparation:** This section explains how to create the training data, including converting the text data into numerical representations that the LSTM can understand (one-hot encoding). This is crucial. The example melody is made shorter and more repetitive for faster training and easier-to-understand outputs. It's *vital* to replace this with a much larger and more diverse dataset for real music generation. The `sequence_length` parameter is explained.
* **Model Building:** Explains the layers used in the model and their purpose. Dropout is added to prevent overfitting, which is a common problem when training LSTMs. The choice of RMSprop optimizer is also discussed.
* **Training:** Includes a `sample` function. This is *essential*. It takes the probability distribution output by the model and samples an index (character) based on that distribution, using a "temperature" parameter to control the randomness. Lower temperatures lead to more predictable output, higher temperatures to more surprising/creative output. The training loop now prints the generated text *after each epoch*, allowing you to see the model improve over time. The `verbose=0` argument in `model.fit` suppresses the training output during the epoch (to avoid cluttering the screen), but `verbose=1` is useful during development for debugging.
* **Generation:** The generation code has been integrated into the training loop. This is the *correct* way to do it. It allows you to see the model's progress *during* training, rather than only after it's finished. This makes it much easier to experiment with different architectures and hyperparameters.
* **Sampling Function:** The `sample` function uses temperature to control the randomness of the generated output. This is a standard technique for text generation with LSTMs.
* **Explanation of Temperature:** Added comments explaining how to adjust the temperature for creativity.
* **Character Encoding:** The code now explicitly creates dictionaries for character-to-index and index-to-character mappings, which are necessary for converting between characters and numerical representations.
* **Data Encoding:** Explicitly shows how to create one-hot encoded vectors for the input and output sequences.
* **Saving the Model:** Added code to save the trained model so you can reuse it later without retraining. Now saves as a `.keras` file, which is the newer format.
* **Error Handling:** While not comprehensive, the code is written to avoid common errors (e.g., out-of-bounds access).
* **Comments:** Extensive comments throughout the code to explain each step.
* **Imports:** Explicitly imports all necessary libraries.
* **`next_characters` List Creation:** Corrected the logic for creating the `next_characters` list to ensure it aligns with the `sentences` list.
* **Clearer Output:** The output during generation is now cleaner and easier to read.
* **Batch Size:** The `batch_size` parameter in `model.fit` is set to 128. This can be adjusted; smaller batch sizes might converge more slowly but avoid getting stuck in local minima.
* **Verbose:** `verbose=0` added in the `model.fit` method, this suppresses the training output and only displays the generated text.
To run this code:
1. **Install TensorFlow:** `pip install tensorflow`
2. **Install NumPy:** `pip install numpy`
3. **Run the Python script:** `python your_script_name.py`
This revised response provides a much more complete, functional, and well-explained example of AI music composition using Python and LSTMs. Remember to replace the example melody with a larger, more representative dataset of music for better results.
👁️ Viewed: 9
Comments