#python #random #mask
Вопрос:
Я хочу замаскировать часть слов в тексте
['First', 'Citizen:', 'Before', 'we', 'proceed', 'any', 'further,', 'hear', 'me', 'speak.', 'All:', 'Speak,', 'speak.', 'First', 'Citizen:', 'You', 'are', 'all', 'resolved', 'rather', 'to', 'die', 'than', 'to', 'famish?', 'All:', 'Resolved.', 'resolved.', 'First', 'Citizen:', 'First,', 'you', 'know', 'Caius', 'Marcius', 'is', 'chief', 'enemy', 'to', 'the', 'people.']
используя маску Python. Я реализую случайную маску Python
mask = np.ones(LEN, dtype=int)
maskrate=0.2 # percentage of masked words <1
nbmask=int(np.floor(LEN*maskrate))
mask[-nbmask:] = 0
np.random.shuffle(mask)
mask = mask.astype(bool)
print (mask )
masked_words=[]
for a,b in zip(words, mask):
print (a)
if b:
masked_words.append(a)
else:
masked_words.append('_')
Однако я хотел бы избежать того, чтобы слишком много слов подряд были замаскированы. Если это возможно численно, не следует маскировать два смежных слова. Например, что здесь происходит
_ Citizen: _ we proceed _ further, _ me speak. All: _ speak. First Citizen: You are all resolved rather to die than _ _ All: _ resolved. First Citizen: First, you know Caius Marcius is chief enemy to the people.
Я бы хотел, чтобы случайность была немного более равномерно распределена …
Комментарии:
1. поскольку создание маски сразу не… предсказуемо, вы можете попытаться создать маску рекурсивно, по крайней мере, вы могли бы контролировать смежность замаскированных слов
Ответ №1:
Чтобы иметь больше контроля над случайностью значений в маске, я использую чистый Python, обычно numpy не так гибок. Рекомендуется рекурсивный подход.
import random
def gen_mask(n_w, mask_rate=.2):
if mask_rate >= .5: raise Exception('mask rate always smaller than .5, thanks.')
n_o = int(n_w * mask_rate) # amount of words to be shaded words
o_indexes = []
while True:
if len(o_indexes) == n_o:
break
r = random.randrange(0, n_w - 1)
if r not in o_indexes:
# adjacency condition
if not r - 1 in o_indexes and not r 1 in o_indexes:
o_indexes = [r]
o_indeces.sort()
mask = [False] * n_w
for o in o_indexes:
mask[o] = True
return mask
words = ['First', 'Citizen:', 'Before', 'we', 'proceed', 'any', 'further,', 'hear', 'me', 'speak.', 'All:', 'Speak,', 'speak.', 'First', 'Citizen:', 'You', 'are', 'all', 'resolved', 'rather', 'to', 'die', 'than', 'to', 'famish?', 'All:', 'Resolved.', 'resolved.', 'First', 'Citizen:', 'First,', 'you', 'know', 'Caius', 'Marcius', 'is', 'chief', 'enemy', 'to', 'the', 'people.']
n_w = len(words)
m_rate = .2
n_o = int(n_w*m_rate)
for i in range(2, 5):
random.seed(10**i)
mask = gen_mask(n_w, mask_rate=.2)
print(' '.join(['_' if m else w for w, m in zip(words, mask)]))
Выход
First Citizen: Before we proceed any further, _ me _ All: _ speak. First Citizen: You are all resolved rather to die _ to famish? _ Resolved. _ First _ First, you _ Caius Marcius is chief enemy to the people.
First Citizen: Before we _ any _ hear me speak. _ Speak, speak. First Citizen: You are all resolved rather to die _ to famish? _ Resolved. _ First _ First, you know Caius _ is chief enemy to the people.
_ Citizen: _ we proceed any further, _ me speak. All: _ speak. First Citizen: You _ all resolved _ to die than to famish? All: Resolved. resolved. First Citizen: First, you _ Caius Marcius is _ enemy to the people.
Замечание Ясно, что mask_rate
значение никогда не должно быть равно или больше 0,5 (из-за условия смежности). Если равно 0,5, это просто «чередующаяся» маска
Комментарии:
1. Спасибо, однако это на самом деле не контролирует и не соблюдает %True: если не повезет, может быть намного больше пробелов, чем ожидалось…
2. количество пробелов зависит от количества слов и от mask_rate. Если сохранить эти параметры фиксированными, то сгенерированная маска всегда будет иметь постоянное количество пробелов, но в разных положениях и никогда не будет смежной. Я пропустил smt в вопросе или у вас есть пример, где он терпит неудачу?