Skip to content

Instantly share code, notes, and snippets.

@Blucknote
Created April 26, 2021 13:24
Show Gist options
  • Save Blucknote/a518f1208a6b4a8bc5080af3b40c1efa to your computer and use it in GitHub Desktop.
Save Blucknote/a518f1208a6b4a8bc5080af3b40c1efa to your computer and use it in GitHub Desktop.
markov chain?
import random
class Dictogram(dict):
def __init__(self, iterable=None):
# Инициализируем наше распределение как новый объект класса,
# добавляем имеющиеся элементы
super(Dictogram, self).__init__()
self.types = 0 # число уникальных ключей в распределении
self.tokens = 0 # общее количество всех слов в распределении
if iterable:
self.update(iterable)
def update(self, iterable):
# Обновляем распределение элементами из имеющегося
# итерируемого набора данных
for item in iterable:
if item in self:
self[item] += 1
self.tokens += 1
else:
self[item] = 1
self.types += 1
self.tokens += 1
def count(self, item):
# Возвращаем значение счетчика элемента, или 0
if item in self:
return self[item]
return 0
def return_random_word(self):
random_key = random.sample(self, 1)
# Другой способ:
# random.choice(histogram.keys())
return random_key[0]
def return_weighted_random_word(self):
# Сгенерировать псевдослучайное число между 0 и (n-1),
# где n - общее число слов
random_int = random.randint(0, self.tokens - 1)
index = 0
list_of_keys = [*self.keys()]
# вывести 'случайный индекс:', random_int
for i in range(0, self.types):
index += self[list_of_keys[i]]
# вывести индекс
if (index > random_int):
# вывести list_of_keys[i]
return list_of_keys[i]
def make_markov_model(data):
markov_model = dict()
for i in range(0, len(data) - 1):
if data[i] in markov_model:
# Просто присоединяем к уже существующему распределению
markov_model[data[i]].update([data[i + 1]])
else:
markov_model[data[i]] = Dictogram([data[i + 1]])
return markov_model
def make_higher_order_markov_model(order, data):
markov_model = dict()
for i in range(0, len(data) - order):
# Создаем окно
window = tuple(data[i: i + order])
# Добавляем в словарь
if window in markov_model:
# Присоединяем к уже существующему распределению
markov_model[window].update([data[i + order]])
else:
markov_model[window] = Dictogram([data[i + order]])
return markov_model
def generate_random_start(model):
# Чтобы сгенерировать любое начальное слово, раскомментируйте строку:
# return random.choice(model.keys())
# Чтобы сгенерировать "правильное" начальное слово, используйте код ниже:
# Правильные начальные слова - это те, что являлись началом предложений в корпусе
if 'END' in model:
seed_word = 'END'
while seed_word == 'END':
seed_word = model['END'].return_weighted_random_word()
return seed_word
return random.choice([*model.keys()])
def generate_random_sentence(length, markov_model):
current_word = generate_random_start(markov_model)
sentence = [current_word]
for i in range(0, length):
current_dictogram = markov_model[current_word]
random_weighted_word = current_dictogram.return_weighted_random_word()
current_word = random_weighted_word
sentence.append(current_word)
sentence[0] = sentence[0].capitalize()
return ' '.join(sentence) + '.'
text = """
Попробуйте придумать, где вы сами можете использовать генератор текста на основе марковских цепей.
Только не забывайте, что самое главное — это то, как вы парсите модель и какие особые ограничения устанавливаете на генерацию.
Автор этой статьи, например, при создании генератора твитов использовал большое окно,
ограничил генерируемый контент до 140 символов и использовал для начала предложений только «правильные» слова,
то есть те, которые являлись началом предложений в корпусе. END
"""
m = make_markov_model(text)
print(generate_random_sentence(10,m))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment