Я создаю программу, и часть моей программы имеет функцию, чтобы найти windowData с window_size = 2
Мой код:
string = [['I', 'have', 'a', 'pen', 'to', 'use']]
window_size = 2
windowData = []
for lines in string:
for index,word in enumerate(lines):
for words in lines[max(index-window_size,0):min(index+window_size,len(string)+1)]:
if words != word:
windowData.append([word,words])
print(windowData)
токовый выход:
[['I', 'have'], ['have', 'I'], ['a', 'I'], ['a', 'have'], ['pen', 'have']]
Из моего понимания о пропуске-графе должно быть что-то вроде этого, не так ли? (Пожалуйста, поправьте меня, если я ошибаюсь)
Ожидаемый результат:
[['I', 'have'], ['I', 'a'], ['have', 'I'], ['have', 'a'], ['have', 'pen'], ['a', 'have'], ['a', 'I'], ['a', 'pen'],['a', 'to'], ['pen', 'a'], ['pen', 'have'], ['pen', 'to'], ['pen', 'use'], ['to', 'pen'], ['to', 'a'],['to', 'use'], ['use', 'pen'],['use', 'to']]
Я понимаю, что изучения только одного языка программирования недостаточно, но я должен больше сосредоточиться на решении проблем. Если возможно, пожалуйста, предложите мне некоторые сайты. Спасибо.
Несколько замечаний:
Неплохая идея вызывать список списков строк по имени переменной "string"; если на самом деле здесь это вид списков-токенизированных текстов, обычно используемых в Word2Vec
, имя, подобное "предложениям" или "текстам", является более четким.
Вы не хотите повторно перечислять lines
каждом вложенном цикле, а скорее работаете с текущим элементом внешнего цикла. Таким образом, цикл над sentences
даст sentence
. Вы будете перебирать sentence
чтобы получить каждое word
.
Эти пары "контекстное слово" для целевых слов на самом деле являются отличным местом для использования кортежей Python, по сути, крошечных неизменяемых списков, созданных в момент необходимости, - просто используйте скобки, а не квадратные скобки.
Вам не нужно добавлять один к длине sentence
при разрезании окон, урезанных в конце, потому что длина уже является фактическим количеством элементов, которое на один выше, чем последняя позиция. Но вам нужно добавить один к index + window_size
, потому что операция index + window_size
([x:y]
) не включает второе значение (y).
Если вы намереваетесь использовать этот цикл для обработки многих текстов, вы можете не захотеть возвращать все пары как один гигантский список пар из всех текстов. Вместо этого вы можете захотеть вернуть один список-пары для каждого списка слов на входе.
Когда вы только начинаете и пытаетесь понять, это помогает использовать очень описательные имена переменных и вызывать промежуточные результаты для разделения строк в именованных переменных для ясности.
Попробуйте эту минимально измененную версию, которая отражает эти изменения:
sentences = [['I', 'have', 'a', 'pen', 'to', 'use']]
window_size = 2
pairs_for_all_sentences = []
for sentence in sentences:
this_sentence_pairs = []
for index, target_word in enumerate(sentence):
window_words = sentence[max(index - window_size, 0) : min(index + window_size + 1, len(sentence))]
for window_word in window_words:
if window_word != target_word:
this_sentence_pairs.append((window_word, target_word))
pairs_for_all_sentences.append(this_sentence_pairs)
print(pairs_for_all_sentences)
Последнее замечание: по сравнению с тем, как создаются реальные пары skip-gram, это не совсем правильно. Если для этого слова не создается ни одна пара, если одно и то же слово появляется внутри окна, создается слово "слово-слово". Поэтому в предложении "Я очень счастлив", на самом деле будут подготовлены две ('very', 'very')
пары.
использовать itertools:
from itertools import combinations
string = ['I', 'have', 'a', 'pen', 'to', 'use']
window_size = 2
print(list(combinations(string, window_size)))
выход:
[('I', 'have'), ('I', 'a'), ('I', 'pen'), ('I', 'to'), ('I', 'use'), ('have', 'a'), ('have', 'pen'), ('have', 'to'), ('have', 'use'), ('a', 'pen'), ('a', 'to'), ('a', 'use'), ('pen', 'to'), ('pen', 'use'), ('to', 'use')]