patternpythonMinor
Song lyric generator using Markov Chains - Python
Viewed 0 times
chainslyricgeneratorsongusingpythonmarkov
Problem
I have written a pop song generator which uses the Markovify library to produce lyrics based on (just for testing purposes) songs by Avril Lavigne.
In order to make the generator a bit more competent I have adapted some code which uses the
It works, but is slow and sometimes gets stuck in a loop when the
The
Lyric Generator
```
import random
import markovify
import ast
from rhyme import rhyme_finder
from sylco import sylco
# Open and model lyrics
with open('lavigne_verse.txt') as f:
verse_text = f.read()
with open('lavigne_chorus.txt') as f:
chorus_text = f.read()
with open('lyrics_tokenize.txt') as f:
tokenized_text = f.read()
verse_model = markovify.NewlineText(verse_text, state_size=2)
chorus_model = markovify.NewlineText(chorus_text, state_size=2)
# Evaluate tokenized_text as a list
tokenized_text = ast.literal_eval(tokenized_text)
# Specify then remove punctuation
punc = set([',','.','"','?','!'])
def clean(str):
if str[-1] in punc:
return str[:-1]
return str
# Generate line that rhymes with stem of verse line 1
def match_rhyme(stem, verse_model):
# Check if rhymes exist
try:
ls = rhyme_finder(stem, tokenized_text)
except KeyError:
return None
if not ls:
return None
# If rhymes exist generate lines
for n in range(100):
while True:
rhyme_l
In order to make the generator a bit more competent I have adapted some code which uses the
nltk library to determine whether or not two words rhyme. I have used this to make the verses conform to an ABAC rhyme scheme.It works, but is slow and sometimes gets stuck in a loop when the
rhyme_finder function is called. I would greatly appreciate any suggestions as to how to streamline the programme, and or make it more efficient. I have linked the main programme app.py below, as well as the rhyme_finder function. But the Avril Lavigne lyrics, and the nltk.tokenize lyrics are on Pastebin. The
Markovify lib (https://github.com/jsvine/markovify), the Sylco syllable counter (https://github.com/eaydin/sylco), and some nltk dependencies (cmudict) are required to run. Lyric Generator
```
import random
import markovify
import ast
from rhyme import rhyme_finder
from sylco import sylco
# Open and model lyrics
with open('lavigne_verse.txt') as f:
verse_text = f.read()
with open('lavigne_chorus.txt') as f:
chorus_text = f.read()
with open('lyrics_tokenize.txt') as f:
tokenized_text = f.read()
verse_model = markovify.NewlineText(verse_text, state_size=2)
chorus_model = markovify.NewlineText(chorus_text, state_size=2)
# Evaluate tokenized_text as a list
tokenized_text = ast.literal_eval(tokenized_text)
# Specify then remove punctuation
punc = set([',','.','"','?','!'])
def clean(str):
if str[-1] in punc:
return str[:-1]
return str
# Generate line that rhymes with stem of verse line 1
def match_rhyme(stem, verse_model):
# Check if rhymes exist
try:
ls = rhyme_finder(stem, tokenized_text)
except KeyError:
return None
if not ls:
return None
# If rhymes exist generate lines
for n in range(100):
while True:
rhyme_l
Solution
Some suggestions:
may become much simpler:
but - as you use it only in one place
and in turn the
where
So you may delete both the
as sets in Python inherently not allow duplicates.
would be clearer with using the
def unique(s):
u = []
for x in s:
if x not in u:
u.append(x)
else:
pass
return umay become much simpler:
def unique(s):
return list(set(s))but - as you use it only in one place
word_list_u = unique(word_list)and in turn the
word_list_u is used only in one place, too:for (x, y) in word_list_u:where
word_list_u need not be a list.So you may delete both the
unique() definition and its usage, and write directlyfor (x, y) in set(word_list):as sets in Python inherently not allow duplicates.
punc = set([',','.','"','?','!'])
def clean(str):
if str[-1] in punc:
return str[:-1]
return strwould be clearer with using the
endswith() method and a tuple of punctuation symbols:punc = tuple(',."?!')
def clean(str):
if str.endswith(punc):
return str[:-1]
return strCode Snippets
def unique(s):
u = []
for x in s:
if x not in u:
u.append(x)
else:
pass
return udef unique(s):
return list(set(s))word_list_u = unique(word_list)for (x, y) in word_list_u:for (x, y) in set(word_list):Context
StackExchange Code Review Q#148653, answer score: 3
Revisions (0)
No revisions yet.