From d3a4bc155672556d7f825efee11bdf409612149c Mon Sep 17 00:00:00 2001 From: Mikhail Nefedov Date: Sat, 25 Nov 2023 11:14:41 +0100 Subject: [PATCH] update hw --- notebooks/bow/homework.ipynb | 2 +- notebooks/spelling/Spellchecking.ipynb | 641 +++++++++---------------- notebooks/spelling/homework.ipynb | 35 +- 3 files changed, 232 insertions(+), 446 deletions(-) diff --git a/notebooks/bow/homework.ipynb b/notebooks/bow/homework.ipynb index 40de613..93fb1d9 100644 --- a/notebooks/bow/homework.ipynb +++ b/notebooks/bow/homework.ipynb @@ -182,7 +182,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.16" + "version": "3.8.14" } }, "nbformat": 4, diff --git a/notebooks/spelling/Spellchecking.ipynb b/notebooks/spelling/Spellchecking.ipynb index 7c4020a..b452354 100644 --- a/notebooks/spelling/Spellchecking.ipynb +++ b/notebooks/spelling/Spellchecking.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -41,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -60,7 +60,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -70,7 +70,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -79,7 +79,7 @@ "915" ] }, - "execution_count": 8, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -90,7 +90,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -110,7 +110,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -133,7 +133,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -166,7 +166,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -184,7 +184,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -208,7 +208,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -226,7 +226,7 @@ " (('это', 'ето'), 9)]" ] }, - "execution_count": 14, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -251,7 +251,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -267,7 +267,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 33, "metadata": {}, "outputs": [], "source": [ @@ -277,7 +277,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -287,7 +287,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -317,7 +317,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -366,7 +366,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -384,7 +384,7 @@ " ('не', 23228)]" ] }, - "execution_count": 21, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -402,7 +402,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, "metadata": {}, "outputs": [], "source": [ @@ -416,314 +416,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Отвлечемся на вероятности" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "У нас есть три основных способа посмотреть на конкретную вероятность:\n", - "\n", - "1) в питоне по умолчанию используется запись маленьких и больших чисел через число e в степени. Степень выводится сразу после числа e (если в начале степени стоит - , то это число меньше единицы). Чем больше/меньше степень, тем больше/меньше число" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2.4440966240624417e-05\n" - ] - } - ], - "source": [ - "print(P('солнце')) # вероятность слова солнце по нашему словарю" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Также можно самому задавать числа таким образом - это может сэкономить немного времени и сократить код. Так часто задают learning_rate в нейронных сетях " - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(10.0, 0.1, 0.0001, 10000.0)" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "1e1, 1e-1, 1e-4, 1e4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2) для того, чтобы вывести привычную десятичную дробь, можно воспользоваться строковым методом .format с указанием количества знаков после запятой" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.000024440966241\n" - ] - } - ], - "source": [ - "print('{0:.15f}'.format(P('солнце')))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "3) Вероятности слов обычно очень маленькие. С ними неудобно работать, а в расчетах с умножением вероятностей это вообще может привести к занулению (underflow). Поэтому часто используется логарифм вероятности (основание не имеет значения). " - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-10.61924988922861\n" - ] - } - ], - "source": [ - "print(np.log(P('солнце')))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Несколько фактов про логарифмы вероятностей" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Вероятность это число от 0 до 1, поэтому её логарифм всегда будет от минус бесконечности до 0. " - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(-9.210340371976182, -0.0010005003335835344, 0.0)" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.log(0.0001), np.log(0.999), np.log(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Логарифм от нуля равен бесконечности. Бесконечность сломает вычисления, в которых она окажется слагаемым" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/mnefedov/.pyenv/versions/3.7.2/lib/python3.7/site-packages/ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in log\n", - " \"\"\"Entry point for launching an IPython kernel.\n" - ] - }, - { - "data": { - "text/plain": [ - "-inf" - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.log(0) + np.log(1e100)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Есть специальная функция в numpy, которая добавляет к вероятности единицу прежде чем брать логарифм. Важное уточнение: нужно преобразовывать вероятности последовательно, каким-то одним способом - либо np.log либо np.log1p, нельзя для нуля делать np.log1p, а для всех остальных np.log!" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(0.0, 0.6931471805599453)" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.log1p(0), np.log1p(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Для того, чтобы вернуться к обычной вероятности нужно взять экспоненту от логарифма вероятности. " - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.10000000000000002" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.exp(np.log(0.1))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Если вы использовали np.log1p, то вернутся поможет np.expm1 (она вычитает единицу после экспоненциирования)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(0.1, 0.0)" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.expm1(np.log1p(0.1)), np.expm1(np.log1p(0.0))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Умножение вероятностей тождественно сложению логарифмов вероятностей" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.0002" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "(0.01*0.02)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.0002000000000000002" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.exp(np.log(0.01) + np.log(0.02)) \n", - "# о том почему результат выглядит так странно можно почитать \n", - "# вот тут - https://docs.python.org/3/tutorial/floatingpoint.html" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Вернемся к нашей задаче" + "Во втором подготовительном семинаре немного разбиралась работа с вероятностями в питоне (представление маленьких и больших чисел в питоне, свойства логарифмов вероятностей), будет полезно повторить - https://github.com/mannefedov/compling_nlp_hse_course/blob/master/notebooks/first_module_intro/02_ngrams.ipynb (раздел про вероятности в конце)" ] }, { @@ -742,7 +435,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 25, "metadata": {}, "outputs": [], "source": [ @@ -761,6 +454,7 @@ " \"Выбираем слова, которые есть в корпусе\"\n", " return set(w for w in words if w in vocab)\n", "\n", + "\n", "def edits1(word):\n", " \"Создаем кандидатов, которые отличаются на одну букву\"\n", " letters = 'йцукенгшщзхъфывапролджэячсмитьбюё'\n", @@ -785,15 +479,15 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 92.3 ms, sys: 3.15 ms, total: 95.4 ms\n", - "Wall time: 95.1 ms\n" + "CPU times: user 582 µs, sys: 58 µs, total: 640 µs\n", + "Wall time: 908 µs\n" ] }, { @@ -802,14 +496,14 @@ "'солнце'" ] }, - "execution_count": 31, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%time\n", - "correction('ссонлце')" + "correction('сcолнце')" ] }, { @@ -979,15 +673,15 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 165 µs, sys: 1e+03 ns, total: 166 µs\n", - "Wall time: 166 µs\n" + "CPU times: user 492 µs, sys: 32 µs, total: 524 µs\n", + "Wall time: 716 µs\n" ] }, { @@ -996,7 +690,7 @@ "'солнце'" ] }, - "execution_count": 39, + "execution_count": 36, "metadata": {}, "output_type": "execute_result" } @@ -1008,15 +702,15 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 1.08 s, sys: 9.32 ms, total: 1.09 s\n", - "Wall time: 1.08 s\n" + "CPU times: user 1.49 s, sys: 4.36 ms, total: 1.5 s\n", + "Wall time: 1.52 s\n" ] }, { @@ -1025,7 +719,7 @@ "'насмехатьсяаававттававаываываы'" ] }, - "execution_count": 40, + "execution_count": 37, "metadata": {}, "output_type": "execute_result" } @@ -1126,7 +820,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 38, "metadata": {}, "outputs": [], "source": [ @@ -1135,11 +829,11 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 39, "metadata": {}, "outputs": [], "source": [ - "def get_closest_match_with_metric(text, lookup,topn=20, metric=textdistance.levenshtein):\n", + "def get_closest_match_with_metric(text, lookup, topn=20, metric=textdistance.levenshtein):\n", " # Counter можно использовать и с не целыми числами\n", " similarities = Counter()\n", " \n", @@ -1158,14 +852,33 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 2.95 s, sys: 49.2 ms, total: 3 s\n", - "Wall time: 3 s\n" + "CPU times: user 11.8 s, sys: 322 ms, total: 12.1 s\n", + "Wall time: 12 s\n" ] }, { "data": { "text/plain": [ - "[('конце', 0.8), ('монце', 0.8), ('сонче', 0.8)]" + "[('солнце', 0.8333333333333334),\n", + " ('конце', 0.8),\n", + " ('монце', 0.8),\n", + " ('соне', 0.8),\n", + " ('сонче', 0.8),\n", + " ('донце', 0.8),\n", + " ('солнцем', 0.7142857142857143),\n", + " ('солнцев', 0.7142857142857143),\n", + " ('солнца', 0.6666666666666667),\n", + " ('сочное', 0.6666666666666667),\n", + " ('синице', 0.6666666666666667),\n", + " ('солнцу', 0.6666666666666667),\n", + " ('сочные', 0.6666666666666667),\n", + " ('свинце', 0.6666666666666667),\n", + " ('сфорце', 0.6666666666666667),\n", + " ('монцей', 0.6666666666666667),\n", + " ('ньонце', 0.6666666666666667),\n", + " ('соньер', 0.6666666666666667),\n", + " ('сорное', 0.6666666666666667),\n", + " ('донцем', 0.6666666666666667)]" ] }, "execution_count": 45, @@ -1175,9 +888,64 @@ ], "source": [ "%%time\n", - "get_closest_match_with_metric('сонце', vocab, 3, textdistance.hamming)" + "get_closest_match_with_metric('сонце', vocab, 20, textdistance.levenshtein)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 15.7 s, sys: 25.6 ms, total: 15.7 s\n", + "Wall time: 15.8 s\n" + ] + }, + { + "data": { + "text/plain": [ + "[('солнце', 0.8333333333333334),\n", + " ('конце', 0.8),\n", + " ('монце', 0.8),\n", + " ('соне', 0.8),\n", + " ('сонче', 0.8),\n", + " ('донце', 0.8),\n", + " ('солнцем', 0.7142857142857143),\n", + " ('солнцев', 0.7142857142857143),\n", + " ('солнца', 0.6666666666666667),\n", + " ('сочное', 0.6666666666666667),\n", + " ('синице', 0.6666666666666667),\n", + " ('солнцу', 0.6666666666666667),\n", + " ('сочные', 0.6666666666666667),\n", + " ('свинце', 0.6666666666666667),\n", + " ('сфорце', 0.6666666666666667),\n", + " ('монцей', 0.6666666666666667),\n", + " ('ньонце', 0.6666666666666667),\n", + " ('соньер', 0.6666666666666667),\n", + " ('сорное', 0.6666666666666667),\n", + " ('донцем', 0.6666666666666667)]" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "get_closest_match_with_metric('сонце', vocab, 20, textdistance.damerau_levenshtein)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": 46, @@ -1251,7 +1019,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 47, "metadata": {}, "outputs": [], "source": [ @@ -1260,31 +1028,50 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 48, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 1.74 s, sys: 4.1 ms, total: 1.74 s\n", - "Wall time: 1.74 s\n" + "CPU times: user 2.92 s, sys: 6 ms, total: 2.93 s\n", + "Wall time: 2.96 s\n" ] }, { "data": { "text/plain": [ - "[('кул', 1.0), ('акул', 0.75), ('коул', 0.75), ('куль', 0.75), ('кули', 0.75)]" + "[('солнце', 0.8333333333333334),\n", + " ('конце', 0.8),\n", + " ('монце', 0.8),\n", + " ('соне', 0.8),\n", + " ('солнцем', 0.7142857142857143),\n", + " ('солнца', 0.6666666666666667),\n", + " ('солнцу', 0.6666666666666667),\n", + " ('сочные', 0.6666666666666667),\n", + " ('союзе', 0.6),\n", + " ('зоне', 0.6),\n", + " ('сносе', 0.6),\n", + " ('фоне', 0.6),\n", + " ('концу', 0.6),\n", + " ('конца', 0.6),\n", + " ('конец', 0.6),\n", + " ('гонке', 0.6),\n", + " ('донец', 0.6),\n", + " ('сотне', 0.6),\n", + " ('сон', 0.6),\n", + " ('синие', 0.6)]" ] }, - "execution_count": 49, + "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%time\n", - "get_closest_match_with_metric('кул', vocab_top, 5, textdistance.damerau_levenshtein)" + "get_closest_match_with_metric('сонце', vocab_top, 20, textdistance.damerau_levenshtein)" ] }, { @@ -1312,31 +1099,31 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 52, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 140 ms, sys: 1.77 ms, total: 142 ms\n", - "Wall time: 141 ms\n" + "CPU times: user 155 ms, sys: 2.25 ms, total: 157 ms\n", + "Wall time: 161 ms\n" ] }, { "data": { "text/plain": [ - "['поезд']" + "['солнце', 'соне', 'солнцем', 'сотне']" ] }, - "execution_count": 51, + "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%time\n", - "get_close_matches('апофеоз', vocab_top.keys(), n=1)" + "get_close_matches('сонце', vocab_top.keys(), n=4)" ] }, { @@ -1373,7 +1160,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 53, "metadata": {}, "outputs": [], "source": [ @@ -1384,7 +1171,7 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 64, "metadata": {}, "outputs": [], "source": [ @@ -1394,13 +1181,13 @@ "id2word = {i:word for i, word in enumerate(vocab)}\n", "\n", "\n", - "vec = CountVectorizer(analyzer='char', ngram_range=(1,1))\n", + "vec = CountVectorizer(analyzer='char', max_features=10000, ngram_range=(1,3))\n", "X = vec.fit_transform(vocab)" ] }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 65, "metadata": {}, "outputs": [], "source": [ @@ -1409,16 +1196,16 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(368802, 1094)" + "(368802, 10000)" ] }, - "execution_count": 55, + "execution_count": 66, "metadata": {}, "output_type": "execute_result" } @@ -1429,7 +1216,7 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 67, "metadata": {}, "outputs": [], "source": [ @@ -1450,43 +1237,43 @@ }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 66.4 ms, sys: 12.3 ms, total: 78.7 ms\n", - "Wall time: 79.2 ms\n" + "CPU times: user 225 ms, sys: 23.7 ms, total: 249 ms\n", + "Wall time: 253 ms\n" ] }, { "data": { "text/plain": [ - "[('цоссен', 0.05131670194948623),\n", - " ('цоссене', 0.05612019255146106),\n", - " ('концессионное', 0.08649972160886044),\n", - " ('сценой', 0.0871290708247231),\n", - " ('солнце', 0.0871290708247231),\n", - " ('сценок', 0.0871290708247231),\n", - " ('сосновец', 0.09630388588493599),\n", - " ('сено', 0.10557280900008414),\n", - " ('сенокосцев', 0.10557280900008414),\n", - " ('осен', 0.10557280900008414),\n", - " ('соне', 0.10557280900008414),\n", - " ('бесценного', 0.10557280900008414),\n", - " ('лентоносец', 0.10557280900008414),\n", - " ('броненосец', 0.10557280900008414),\n", - " ('сцен', 0.10557280900008414),\n", - " ('бессоннице', 0.10557280900008414),\n", - " ('носе', 0.10557280900008414),\n", - " ('самоценное', 0.10557280900008414),\n", - " ('сное', 0.10557280900008414),\n", - " ('онсе', 0.10557280900008414)]" + "[('монце', 0.24999999999999978),\n", + " ('донце', 0.24999999999999978),\n", + " ('конце', 0.24999999999999978),\n", + " ('херсонцев', 0.2640199278060129),\n", + " ('саксонцев', 0.2640199278060129),\n", + " ('сон', 0.2928932188134523),\n", + " ('олонце', 0.2998599579859951),\n", + " ('ньонце', 0.2998599579859952),\n", + " ('соне', 0.3264246859454365),\n", + " ('донцем', 0.3291796067500631),\n", + " ('монцей', 0.3291796067500631),\n", + " ('солнце', 0.3291796067500631),\n", + " ('концессионное', 0.33217692887937167),\n", + " ('концерн', 0.3545027756320972),\n", + " ('монцезе', 0.3545027756320972),\n", + " ('концессионном', 0.35948738477965136),\n", + " ('концессионера', 0.36155760193093855),\n", + " ('концессионером', 0.36555873142548445),\n", + " ('лондонцев', 0.367544467966324),\n", + " ('эстонцев', 0.3700592116512881)]" ] }, - "execution_count": 57, + "execution_count": 68, "metadata": {}, "output_type": "execute_result" } @@ -1505,7 +1292,7 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 69, "metadata": {}, "outputs": [], "source": [ @@ -1520,31 +1307,31 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 70, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 1e+03 ns, sys: 0 ns, total: 1e+03 ns\n", - "Wall time: 2.15 µs\n" + "CPU times: user 74.2 ms, sys: 25.7 ms, total: 99.9 ms\n", + "Wall time: 106 ms\n" ] }, { "data": { "text/plain": [ - "[('крейг', 0.8), ('крэйг', 0.8), ('крейга', 0.6666666666666667)]" + "[('солнце', 0.8333333333333334), ('монце', 0.8), ('донце', 0.8)]" ] }, - "execution_count": 59, + "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "%time\n", - "get_closest_hybrid_match('крйг', X, vec)" + "%%time\n", + "get_closest_hybrid_match('сонце', X, vec)" ] }, { @@ -1556,13 +1343,13 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "2cfa99cdf0db49c1a28309091794e10b", + "model_id": "6b7310769f05474692061c96191cbda6", "version_major": 2, "version_minor": 0 }, @@ -1614,7 +1401,7 @@ }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 72, "metadata": { "scrolled": false }, @@ -1623,8 +1410,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "0.847023511755878\n", - "0.421583850931677\n", + "0.8533266633316658\n", + "0.4704968944099379\n", "0.09004249454461927\n" ] } @@ -1671,27 +1458,43 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 73, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting pyaspeller\n", + " Downloading pyaspeller-2.0.0-py3-none-any.whl (12 kB)\n", + "Requirement already satisfied: requests<3.0.0,>=2.27.1 in /Users/mnefedov/miniforge3/envs/tf1/lib/python3.8/site-packages (from pyaspeller) (2.28.1)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /Users/mnefedov/miniforge3/envs/tf1/lib/python3.8/site-packages (from requests<3.0.0,>=2.27.1->pyaspeller) (2022.9.24)\n", + "Requirement already satisfied: idna<4,>=2.5 in /Users/mnefedov/miniforge3/envs/tf1/lib/python3.8/site-packages (from requests<3.0.0,>=2.27.1->pyaspeller) (3.4)\n", + "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /Users/mnefedov/miniforge3/envs/tf1/lib/python3.8/site-packages (from requests<3.0.0,>=2.27.1->pyaspeller) (1.26.12)\n", + "Requirement already satisfied: charset-normalizer<3,>=2 in /Users/mnefedov/miniforge3/envs/tf1/lib/python3.8/site-packages (from requests<3.0.0,>=2.27.1->pyaspeller) (2.1.1)\n", + "Installing collected packages: pyaspeller\n", + "Successfully installed pyaspeller-2.0.0\n" + ] + } + ], "source": [ "!pip install pyaspeller" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 76, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'Неправильное предложение.'" + "'Для Яндекс Спеллера есть питоновская библиотека, которая упрощает его использование. У него есть некоторые ограничения (10 к запросов в день), но для небольших проектов этого вполне достаточно.'" ] }, - "execution_count": 6, + "execution_count": 76, "metadata": {}, "output_type": "execute_result" } @@ -1700,15 +1503,23 @@ "# Так можно исправить предложение целиком\n", "from pyaspeller import YandexSpeller\n", "speller = YandexSpeller()\n", - "fixed = speller.spelled('Нипрвильное приджлажение.')\n", + "fixed = speller.spelled('Для Яндекс Спеллера есть питоновская библиотека, которая упрощает его использование. У него есть некоторые ограничения (10 к запросов в день), но для небольших проектов этого вполне достаточно.')\n", "fixed" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 75, "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mnefedov/miniforge3/envs/tf1/lib/python3.8/site-packages/pyaspeller/word.py:17: UserWarning: Class Word is deprecated. Use YandexSpeller().spelled(text) instead\n", + " warnings.warn(\"Class Word is deprecated. Use YandexSpeller().spelled(text) instead\")\n" + ] + }, { "name": "stdout", "output_type": "stream", @@ -1749,7 +1560,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.8.14" } }, "nbformat": 4, diff --git a/notebooks/spelling/homework.ipynb b/notebooks/spelling/homework.ipynb index 4d0ef16..a9a0604 100644 --- a/notebooks/spelling/homework.ipynb +++ b/notebooks/spelling/homework.ipynb @@ -72,7 +72,7 @@ "id": "f9cf9985", "metadata": {}, "source": [ - "## 2. Symspell (5 баллов)" + "## 2. Symspell (7 баллов)" ] }, { @@ -80,10 +80,10 @@ "id": "9392cc23", "metadata": {}, "source": [ - "Реализуйте алгоритм Symspell. Он похож на алгоритм Норвига, но проще и быстрее. Там к словам применяется только одна операция - удаление символа. Описание алгоритма по шагам:\n", + "Реализуйте алгоритм Symspell. Он похож на алгоритм Норвига, но проще и быстрее. Он основан только на одной операции - удалении символа. Описание алгоритма по шагам:\n", "\n", "1) Составляется словарь правильных слов \n", - "2) На основе словаря правильных слов составляется словарь удалений - для каждого правильного слова создаются все варианты удалений и создается словарь, где ключ - слово с удалением, а значение - правильное слово \n", + "2) На основе словаря правильных слов составляется словарь удалений - для каждого правильного слова создаются все варианты удалений и создается словарь, где ключ - слово с удалением, а значение - правильное слово (!) \n", "3) Для выбора исправления для слова с опечаткой генерируются все варианты удаления, из них выбираются те, что есть в словаре удалений, построенного на шаге 2. Слово с опечаткой заменяется на правильное слово, соответствующее варианту удаления \n", "4) Если в словаре удалений есть несколько вариантов, то выбирается удаление, которому соответствует наиболее вероятное правильное слово \n", "\n", @@ -91,36 +91,11 @@ "Оцените качество полученного алгоритма теми же тремя метриками." ] }, - { - "cell_type": "code", - "execution_count": 2, - "id": "96c9fae0", - "metadata": {}, - "outputs": [], - "source": [ - "# ваш код тут" - ] - }, - { - "cell_type": "markdown", - "id": "b292d96d", - "metadata": {}, - "source": [ - "## *3. Чтение. (2 балла)" - ] - }, { "cell_type": "markdown", "id": "dee4b28f", "metadata": {}, - "source": [ - "Прочитайте эту главу в книге Speech and Language Processing - https://web.stanford.edu/~jurafsky/slp3/2.pdf .\n", - "Ответьте на следующий вопрос:\n", - "\n", - "1. Что такое Byte-Pair Encoding (опишите по-русски, как минимум 10 предложениями)?\n", - "\n", - "*Это задание не связано напрямую с исправлением опечаток, но это важная тема, к которой мы вернемся в конце курса" - ] + "source": [] }, { "cell_type": "code", @@ -147,7 +122,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.9.16" } }, "nbformat": 4,