<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Руководство для начинающих - Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</title>
	<atom:link href="https://python.ivan-shamaev.ru/tag/%D1%80%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D0%B4%D0%BB%D1%8F-%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85/feed/" rel="self" type="application/rss+xml" />
	<link>https://python.ivan-shamaev.ru/tag/руководство-для-начинающих/</link>
	<description>Библиотеки обработки данных. Примеры. Строки, списки, файлы, числа, массивы. Язык программирования Python 3 - скачать</description>
	<lastBuildDate>Fri, 10 Apr 2020 21:19:05 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.4</generator>

<image>
	<url>https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/cropped-data_science_python3_logo-32x32.png</url>
	<title>Руководство для начинающих - Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</title>
	<link>https://python.ivan-shamaev.ru/tag/руководство-для-начинающих/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Правила оформления кода по PEP8 на Python. Руководство для программиста</title>
		<link>https://python.ivan-shamaev.ru/pep8-python-code-rules-programmers-guide/</link>
					<comments>https://python.ivan-shamaev.ru/pep8-python-code-rules-programmers-guide/#respond</comments>
		
		<dc:creator><![CDATA[Шамаев Иван]]></dc:creator>
		<pubDate>Fri, 03 Apr 2020 21:19:00 +0000</pubDate>
				<category><![CDATA[Рекомендации для разработчиков. Советы и фишки]]></category>
		<category><![CDATA[PEP8 Python]]></category>
		<category><![CDATA[Правила оформления кода]]></category>
		<category><![CDATA[Руководство для начинающих]]></category>
		<category><![CDATA[Руководство для программиста]]></category>
		<guid isPermaLink="false">https://python.ivan-shamaev.ru/?p=882</guid>

					<description><![CDATA[<p>Введение в PEP8 (Python Enhancement Proposal #8) Документ Python Enhancement Proposal #8 (сокращенно РЕР8) содержит предложения по стилевому оформлению кода программ на языке Python. Вообще говоря, вы вправе форматировать свой код так, как считаете нужным. Однако применение единообразного стиля облегчит изучение кода другими людьми и улучшит его удобочитаемость. Совместное использование общего стиля с другими Руthоn-программистами [&#8230;]</p>
<p>Сообщение <a href="https://python.ivan-shamaev.ru/pep8-python-code-rules-programmers-guide/">Правила оформления кода по PEP8 на Python. Руководство для программиста</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&#038;title=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" data-a2a-url="https://python.ivan-shamaev.ru/pep8-python-code-rules-programmers-guide/" data-a2a-title="Правила оформления кода по PEP8 на Python. Руководство для программиста"></a></p><h2><strong>Введение в PEP8 (Python Enhancement Proposal #8)</strong></h2>
<p><strong>Документ Python Enhancement Proposal #8 (сокращенно РЕР8)</strong> содержит предложения по стилевому оформлению кода программ на языке Python. Вообще говоря, вы вправе форматировать свой код так, как считаете нужным. Однако применение единообразного стиля облегчит изучение кода другими людьми и улучшит его удобочитаемость. Совместное использование общего стиля с другими Руthоn-программистами в рамках большого сообщества способствует улучшению качества программ при коллективной работе над проектами. Но даже если единственный человек, который когда-либо будет читать ваш код, &#8212; это вы, соблюдение рекомендаций РЕР 8 облегчит внесение последующих изменений в код.</p>
<p><strong>Документ РЕР8</strong> содержит детализированные правила написания кода на Python. По мере развития языка этот документ постоянно обновляется. Было бы неплохо, если бы вы прочитали целиком все руководство</p>
<ul>
<li><a href="https://www.python.org/dev/peps/pep-0008/" target="_blank" rel="noopener noreferrer">Официальный Guide PEP8 на английском языке</a> <br /><a href="https://pythonworld.ru/osnovy/pep-8-rukovodstvo-po-napisaniyu-koda-na-python.html" target="_blank" rel="noopener noreferrer"></a></li>
<li><a href="https://pythonworld.ru/osnovy/pep-8-rukovodstvo-po-napisaniyu-koda-na-python.html" target="_blank" rel="noopener noreferrer">PEP 8 &#8212; руководство по написанию кода на Python. Перевод на русский язык</a><br /><a href="https://pep8.ru/doc/pep8/" target="_blank" rel="noopener noreferrer"></a></li>
<li><a href="https://pep8.ru/doc/pep8/" target="_blank" rel="noopener noreferrer">PEP8 &#8212; стиль кода в языке Python</a></li>
</ul>
<p>Ниже приведены некоторые правила, которых следует обязательно придерживаться.</p>
<h2><strong>Пробелы</strong></h2>
<p>В языке Python пробелы имеют синтаксическое значение. Особое значение Pythоn-программисты придают влиянию пробелов на удобочитаемость кода.</p>
<ul>
<li>Используйте пробелы, а не символы табуляции для создания отступов.</li>
<li>Используйте по 4 пробела для каждого уровня синтаксически значимых отступов.</li>
<li>Длина строк не должна превышать 79 символов.</li>
<li>Дополнительные строки, являющиеся продолжением длинных выражений, должны выделяться четырьмя дополнительными пробелами сверх обычного их количества для отступов данного уровня.</li>
<li>Между определениями функций и классов в файлах следует вставлять две пустые строки.</li>
<li>Между определениями методов в классах следует вставлять одну пустую строку.</li>
<li>Не окружайте пробелами индексы элементов списков вызовы функций и операторы присваивания значений именованным аргументам.</li>
<li>Помещайте по одному и только одному пробелу до и после оператора присваивания.</li>
</ul>
<h2><strong>Имена</strong></h2>
<p>В документе <strong>РЕР8</strong> для различных элементов языка предлагается свой стиль имен. Благодаря этому можно легко определить в процессе чтения кода, какому типу соответствует то или иное имя:</p>
<ul>
<li>Имена функций, переменных и атрибутов должны следовать формату lowercase_underscore (нижний регистр букв, разделение слов символами подчеркивания) .</li>
<li>Имена защищенных атрибутов экземпляра должны следовать _leading_underscore (один символ подчеркивания в начале).</li>
<li>Имена закрытых атрибутов экземпляра должны следовать формату __leading_underscore (два символа подчеркивания в начале).</li>
<li>Имена классов и исключений должны следовать формату CapitalizeWord (каждое слово начинается с прописной буквы).</li>
<li>Константы уровня модуля должны записываться в формате ALL_CAPS (все буквы прописные, в качестве разделителя используется символ подчеркивания).</li>
<li>В определениях методов экземпляров классов в качестве имени первого параметра следует всегда указывать self (это имя ссылается на текущий объект).</li>
<li>В определениях методов классов в качестве имени первого параметра следует всегда указывать cls (это имя ссылается на текущий класс).</li>
</ul>
<h2><strong>Выражения и инструкции</strong></h2>
<p>Одно из положений дзен-философии Python гласит: &#171;Должен существовать один &#8212; и предпочтительно только один &#8212; очевидный способ сделать это&#187;. В рекомендациях документа РЕР8 предпринимается попытка кодифицировать такой стиль написания выражений и предложений.</p>
<ul>
<li>Используйте встроенные отрицания (if a is not b), а не отрицание утвердительных выражений (if not a is b).</li>
<li>Не тестируйте пустые значения (такие, как [] или &#8216; &#8216;). Проверяя их длину (if len(somelist) == 0) . Вместо этого используйте проверку if not some list, исходя из того, что результат вычисления пустого выражения неявно трактуется как False.</li>
<li>То же самое касается и непустых значений (таких, как [1] или &#8216;hi&#8217;): в инструкции if some list результат вычисления непустого значения неявно трактуется как True.</li>
<li>Избегайте записи инструкций if, циклов for и while, а также сложных инструкций except в одной строке. Размещайте их на нескольких строках, чтобы сделать код более понятным.</li>
<li>Всегда помещайте инструкции import в самом начале файла.</li>
<li>Для импорта модулей всегда используйте их абсолютные имена, а не имена, заданные относительно пути к текущему модулю. Например, чтобы импортировать модуль foo из пакета bar, следует использовать инструкцию from bar import foo, а не просто import foo.</li>
<li>Если требуется выполнить относительный импорт, то используйте явный синтаксис: from import foo.</li>
<li>Импортируемые модули должны располагаться в разделах, указываемых в следующем порядке:
<ol>
<li>модули стандартных библиотек;</li>
<li>модули сторонних разработчиков;</li>
<li>ваши собственные модули.</li>
</ol>
</li>
</ul>
<p>В каждом подразделе модули должны располагаться в алфавитном порядке.</p>
<h2><strong>Что следует запомнить</strong></h2>
<ul>
<li>Всегда следуйте рекомендациям по оформлению кода Python, изложенным в документе РЕР 8.</li>
<li>Использование общего с многочисленными членами Руthоn-сообщества стиля оформления кода облегчает коллективную разработку.</li>
<li>Использование единообразного стиля упрощает изменение кода впоследствии.</li>
</ul>
<h2><strong>Best Practices Python PEP8 Code Style &#8212; Стиль кода для написания функций</strong></h2>
<p>Если вы спросите программистов Python, что им больше всего нравится в Python, они часто будут ссылаться на его высокую читабельность. Действительно, высокий уровень читабельности лежит в основе дизайна языка Python, следуя общепризнанному факту, что код читается гораздо чаще, чем пишется.</p>
<p>Одной из причин высокой читабельности кода Python является его полный набор рекомендаций PEP8 по стилю кода и «Pythonic» идиом.</p>
<p>Когда ветеран Python-разработчик (Pythonista) называет части кода не «Pythonic», они обычно означают, что эти строки кода не следуют общим правилам и не выражают свое намерение в том, что считается лучшим (слушайте: наиболее читаемый) путь.</p>
<p>В некоторых случаях не было достигнуто соглашения о том, как выразить намерение в коде Python, но такие случаи редки.</p>
<h3><span>Явный код </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#explicit-code" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Хотя в Python возможен любой вид черной магии, наиболее явный и простой способ предпочтителен.</span></p>
<p><strong><span>Плохо</span></strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">def make_complex(*args):
    x, y = args
    return dict(**locals())</pre>
<p><strong><span>Хорошо</span></strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">def make_complex(x, y):
    return {'x': x, 'y': y}</pre>
<div class="section" id="explicit-code">
<p><span>В приведенном выше хорошем коде x и y явно принимаются от вызывающей стороны, и возвращается явный словарь. Разработчик, использующий эту функцию, точно знает, что делать, читая первые и последние строки, что не так с плохим примером.</span></p>
</div>
<div class="section" id="one-statement-per-line">
<h3><span>Одно утверждение на строку </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#one-statement-per-line" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Несмотря на то, что некоторые составные операторы, такие как списочные выражения, допускаются и ценятся за их краткость и выразительность, использование двух разделенных операторов в одной строке кода является плохой практикой.</span></p>
<p><strong><span>Плохо</span></strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print 'one'; print 'two'

if x == 1: print 'one'

if &lt;complex comparison&gt; and &lt;other complex comparison&gt;:
    # do something</pre>
<p><strong><span>Хорошо</span></strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print 'one'
print 'two'

if x == 1:
    print 'one'

cond1 = &lt;complex comparison&gt;
cond2 = &lt;other complex comparison&gt;
if cond1 and cond2:
    # do something</pre>
<div class="section" id="function-arguments">
<h3><span>Аргументы функции </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#function-arguments" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Аргументы могут быть переданы в функции четырьмя различными способами.</span></p>
<ol class="arabic simple">
<li><strong><span>Позиционные аргументы</span></strong><span> являются обязательными и не имеют значений по умолчанию. Они являются простейшей формой аргументов и могут использоваться для нескольких аргументов функции, которые полностью являются частью значения функции, и их порядок является естественным. Например, пользователь или пользователь функции без труда помнит, что эти две функции требуют двух аргументов и в каком порядке.</span><code class="docutils literal notranslate"><span class="pre">send(message,</span><span> </span><span class="pre">recipient)</span></code><span></span><code class="docutils literal notranslate"><span class="pre">point(x,</span><span> </span><span class="pre">y)</span></code><span></span></li>
</ol>
<p><span>В этих двух случаях, можно использовать имена аргументов при вызове функции и, делая это, можно изменить порядок аргументов, вызывая, например , и , но это снижает читаемость и излишне многословные, по сравнению с более простыми вызовами к и .</span><code class="docutils literal notranslate"><span class="pre">send(recipient='World',</span><span> </span><span class="pre">message='Hello')</span></code><span></span><code class="docutils literal notranslate"><span class="pre">point(y=2,</span><span> </span><span class="pre">x=1)</span></code><span></span><code class="docutils literal notranslate"><span class="pre">send('Hello',</span><span> </span><span class="pre">'World')</span></code><span></span><code class="docutils literal notranslate"><span class="pre">point(1,</span><span> </span><span class="pre">2)</span></code><span></span></p>
<ol class="arabic simple" start="2">
<li><strong><span>Аргументы ключевых слов</span></strong><span> не являются обязательными и имеют значения по умолчанию. Они часто используются для необязательных параметров, отправляемых в функцию. Когда функция имеет более двух или трех позиционных параметров, ее сигнатуру труднее запомнить, и полезно использовать аргументы ключевых слов со значениями по умолчанию. Например, более полная </span><code class="docutils literal notranslate"><span class="pre">send</span></code><span>функция может быть определена как . Здесь и не являются обязательными, и оценивают, когда им не передается другое значение.</span><code class="docutils literal notranslate"><span class="pre">send(message,</span><span> </span><span class="pre">to,</span><span> </span><span class="pre">cc=None,</span><span> </span><span class="pre">bcc=None)</span></code><span></span><code class="docutils literal notranslate"><span class="pre">cc</span></code><span></span><code class="docutils literal notranslate"><span class="pre">bcc</span></code><span></span><code class="docutils literal notranslate"><span class="pre">None</span></code><span></span></li>
</ol>
<p><span>Вызов функции с аргументами ключевых слов может быть выполнен несколькими способами в Python; например, можно следовать порядку аргументов в определении, не называя аргументы в явном виде, как, например , отправляя слепую копию для Бога. Также можно было бы назвать аргументы в другом порядке, например, в . Эти две возможности лучше избегать без каких &#8212; либо веских причин , чтобы не следить за синтаксис , который ближе всего к определению функции: .</span><code class="docutils literal notranslate"><span class="pre">send('Hello',</span><span> </span><span class="pre">'World',</span><span> </span><span class="pre">'Cthulhu',</span><span> </span><span class="pre">'God')</span></code><span></span><code class="docutils literal notranslate"><span class="pre">send('Hello</span><span> </span><span class="pre">again',</span><span> </span><span class="pre">'World',</span><span> </span><span class="pre">bcc='God',</span><span> </span><span class="pre">cc='Cthulhu')</span></code><span></span><code class="docutils literal notranslate"><span class="pre">send('Hello',</span><span> </span><span class="pre">'World',</span><span> </span><span class="pre">cc='Cthulhu',</span><span> </span><span class="pre">bcc='God')</span></code><span></span></p>
<p><span>В качестве примечания, следуя принципу </span><a class="reference external" href="http://en.wikipedia.org/wiki/You_ain't_gonna_need_it"><span>YAGNI</span></a><span> , зачастую сложнее удалить необязательный аргумент (и его логику внутри функции), который был добавлен «на всякий случай» и, по-видимому, никогда не используется, чем добавить новый необязательный аргумент и его логика, когда это необходимо.</span></p>
<ol class="arabic simple" start="3">
<li><span>Список </span><strong><span>произвольных аргументов</span></strong><span> &#8212; это третий способ передачи аргументов в функцию. Если намерение функции лучше выражается сигнатурой с расширяемым числом позиционных аргументов, ее можно определить с помощью </span><code class="docutils literal notranslate"><span class="pre">*args</span></code><span>конструкций. В теле функции </span><code class="docutils literal notranslate"><span class="pre">args</span></code><span>будет кортеж всех оставшихся позиционных аргументов. Например, может быть вызван с каждым получателем в качестве аргумента:, а в теле функции будет равно .</span><code class="docutils literal notranslate"><span class="pre">send(message,</span><span> </span><span class="pre">*args)</span></code><span></span><code class="docutils literal notranslate"><span class="pre">send('Hello',</span><span> </span><span class="pre">'God',</span><span> </span><span class="pre">'Mom',</span><span> </span><span class="pre">'Cthulhu')</span></code><span></span><code class="docutils literal notranslate"><span class="pre">args</span></code><span></span><code class="docutils literal notranslate"><span class="pre">('God',</span><span> </span><span class="pre">'Mom',</span><span> </span><span class="pre">'Cthulhu')</span></code><span></span></li>
</ol>
<p><span>Однако эта конструкция имеет некоторые недостатки и должна использоваться с осторожностью. Если функция получает список аргументов одинаковой природы, часто более понятно определить ее как функцию одного аргумента, причем этот аргумент является списком или любой последовательностью. Здесь, если </span><code class="docutils literal notranslate"><span class="pre">send</span></code><span>есть несколько получателей, лучше определить это явно: и вызвать его с помощью . Таким образом, пользователь функции может заранее манипулировать списком получателей как списком, и это открывает возможность для передачи любой последовательности, включая итераторы, которая не может быть распакована как другие последовательности.</span><code class="docutils literal notranslate"><span class="pre">send(message,</span><span> </span><span class="pre">recipients)</span></code><span></span><code class="docutils literal notranslate"><span class="pre">send('Hello',</span><span> </span><span class="pre">['God',</span><span> </span><span class="pre">'Mom',</span><span> </span><span class="pre">'Cthulhu'])</span></code><span></span></p>
<ol class="arabic simple" start="4">
<li><span></span><strong><span>Произвольный ключевой слово словарь аргумента</span></strong><span> является последним способом передать аргументы функции. Если функции требуется неопределенная серия именованных аргументов, можно использовать </span><code class="docutils literal notranslate"><span class="pre">**kwargs</span></code><span>конструкцию. В теле функции </span><code class="docutils literal notranslate"><span class="pre">kwargs</span></code><span>будет словарь всех переданных именованных аргументов, которые не были перехвачены другими ключевыми аргументами в сигнатуре функции.</span></li>
</ol>
<p><span>Необходима та же осторожность, что и в случае </span><em><span>списка произвольных аргументов</span></em><span> , по аналогичным причинам: эти мощные методы должны использоваться, когда существует явная необходимость их использования, и их не следует использовать, если более простая и понятная конструкция достаточна для выразить намерение функции.</span></p>
<p><span>Программист должен написать функцию, чтобы определить, какие аргументы являются позиционными аргументами, а какие &#8212; необязательными аргументами ключевых слов, и решить, использовать ли передовые методы передачи произвольных аргументов. Если следовать приведенному выше совету разумно, можно и приятно писать функции Python, которые:</span></p>
<ul class="simple">
<li><span>легко читается (имя и аргументы не нуждаются в объяснениях)</span></li>
<li><span>легко изменить (добавление нового ключевого аргумента не нарушает другие части кода)</span></li>
</ul>
</div>
<div class="section" id="avoid-the-magical-wand">
<h3><span>Избегайте волшебной палочки </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#avoid-the-magical-wand" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Мощный инструмент для хакеров, Python поставляется с очень богатым набором хуков и инструментов, позволяющих вам выполнять практически любые хитрые трюки. Например, можно выполнить каждое из следующих действий:</span></p>
<ul class="simple">
<li><span>изменить способ создания и создания объектов</span></li>
<li><span>изменить способ импорта модулей интерпретатором Python</span></li>
<li><span>Можно даже (и рекомендуется при необходимости) встроить подпрограммы C в Python.</span></li>
</ul>
<p><span>Тем не менее, все эти варианты имеют много недостатков, и всегда лучше использовать самый простой способ для достижения вашей цели. Основным недостатком является то, что читаемость сильно страдает при использовании этих конструкций. Многие инструменты анализа кода, такие как pylint или pyflakes, не смогут проанализировать этот «волшебный» код.</span></p>
<p><span>Мы считаем, что разработчик Python должен знать об этих почти безграничных возможностях, потому что это вселяет уверенность в том, что на пути не будет непроходимых проблем. Однако очень важно знать, как и, в частности, когда их </span><strong><span>не</span></strong><span> использовать.</span></p>
<p><span>Подобно мастеру кунг-фу, питонист знает, как убивать одним пальцем, и никогда не делать этого на самом деле.</span></p>
</div>
<div class="section" id="we-are-all-responsible-users">
<h3><span>Мы все ответственные пользователи </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#we-are-all-responsible-users" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Как видно выше, Python допускает множество трюков, и некоторые из них потенциально опасны. Хорошим примером является то, что любой клиентский код может переопределять свойства и методы объекта: в Python нет ключевого слова «private». Эта философия, очень отличающаяся от языков с высокой степенью защиты, таких как Java, которые предоставляют множество механизмов для предотвращения любого неправильного использования, выражается высказыванием: «Мы все ответственные пользователи».</span></p>
<p><span>Это не означает, что, например, никакие свойства не считаются закрытыми и что правильная инкапсуляция невозможна в Python. Скорее, вместо того, чтобы полагаться на бетонные стены, возводимые разработчиками между их кодом и чужим, сообщество Python предпочитает полагаться на ряд соглашений, указывающих, что к этим элементам не следует обращаться напрямую.</span></p>
<p><span>Основное соглашение для частных свойств и деталей реализации заключается в добавлении префикса ко всем «внутренним элементам». Если клиентский код нарушает это правило и получает доступ к этим отмеченным элементам, любое неправильное поведение или проблемы, возникшие при изменении кода, являются ответственностью клиентского кода.</span></p>
<p><span>Использование этого соглашения приветствуется: любой метод или свойство, которые не предназначены для использования клиентским кодом, должны начинаться с подчеркивания. Это гарантирует лучшее разделение обязанностей и более легкую модификацию существующего кода; всегда будет возможно обнародовать частную собственность, но сделать публичную собственность частной может быть гораздо более сложной операцией.</span></p>
</div>
<div class="section" id="returning-values">
<h3><span>Возвращение значения </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#returning-values" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Когда функция усложняется, нередко используют несколько операторов return внутри тела функции. Однако, чтобы сохранить четкое намерение и устойчивый уровень читабельности, желательно избегать возврата значимых значений из многих выходных точек в теле.</span></p>
<p><span>Существует два основных случая возврата значений в функцию: результат возврата функции, когда она была обработана нормально, и случаи ошибок, которые указывают на неправильный входной параметр, или любую другую причину, по которой функция не может завершить вычисление или задача.</span></p>
<p><span>Если вы не хотите вызывать исключения для второго случая, может потребоваться возврат значения, такого как None или False, указывающего, что функция не может работать правильно. В этом случае лучше вернуться, как только был обнаружен неправильный контекст. Это поможет сгладить структуру функции: весь код после оператора return-from-of-error может предполагать, что условие выполнено для дальнейшего вычисления основного результата функции. Наличие нескольких таких операторов возврата часто необходимо.</span></p>
<p><span>Однако, когда функция имеет несколько основных точек выхода для своего нормального хода, становится трудно отлаживать возвращаемый результат, поэтому может быть предпочтительнее сохранить одну точку выхода. Это также поможет выделить некоторые пути кода, а несколько точек выхода являются вероятным признаком того, что такой рефакторинг необходим.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">def complex_function(a, b, c):
    if not a:
        return None  # Raising an exception might be better
    if not b:
        return None  # Raising an exception might be better
    # Some complex code trying to compute x from a, b and c
    # Resist temptation to return x if succeeded
    if not x:
        # Some Plan-B computation of x
    return x  # One single exit point for the returned value x will help
              # when maintaining the code.</pre>
<h2><span>Идиомы </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#idioms" title="Постоянная ссылка на этот заголовок"><span></span></a></h2>
<p><span>Проще говоря, идиома программирования &#8212; это </span><em><span>способ</span></em><span> написания кода. Понятие идиом программирования подробно обсуждается на </span><a class="reference external" href="http://c2.com/cgi/wiki?ProgrammingIdiom"><span>c2</span></a><span> и в </span><a class="reference external" href="https://stackoverflow.com/questions/302459/what-is-a-programming-idiom"><span>Stack Overflow</span></a><span> .</span></p>
<p><span>Идиоматический код Python часто называют </span><em><span>Pythonic</span></em><span> .</span></p>
<p><span>Хотя обычно есть один &#8212; и предпочтительно только один &#8212; очевидный способ сделать это; способ писать идиоматические коды Python могут быть неочевидными для начинающего Python. Таким образом, хорошие идиомы должны быть осознанно приобретены.</span><em><span></span></em><span></span></p>
<p><span>Ниже приведены некоторые распространенные идиомы Python:</span></p>
<div class="section" id="unpacking"><span id="unpacking-ref"></span>
<h3><span>Распаковка </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#unpacking" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Если вы знаете длину списка или кортежа, вы можете назначить имена его элементам при распаковке. Например, поскольку </span><code class="docutils literal notranslate"><span class="pre">enumerate()</span></code><span>будет предоставлять кортеж из двух элементов для каждого элемента в списке:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">for index, item in enumerate(some_list):
    # do something with index and item</pre>
<p><span>Вы также можете использовать это для замены переменных:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">a, b = b, a</pre>
<p><span>Вложенная распаковка тоже работает:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">a, (b, c) = 1, (2, 3)</pre>
<p><span>В Python 3 новый метод расширенной распаковки был представлен </span><span class="target" id="index-0"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-3132"><strong><span>PEP3132</span></strong></a><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">a, *rest = [1, 2, 3]
# a = 1, rest = [2, 3]
a, *middle, c = [1, 2, 3, 4]
# a = 1, middle = [2, 3], c = 4</pre>
<h3><span>Создать игнорируемую переменную </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#create-an-ignored-variable" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Если вам нужно что-то назначить (например, в </span><a class="reference internal" href="https://docs.python-guide.org/writing/style/#unpacking-ref"><span class="std std-ref"><span>распаковке</span></span></a><span> ), но вам не понадобится эта переменная, используйте </span><code class="docutils literal notranslate"><span class="pre">__</span></code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">filename = 'foobar.txt'
basename, __, ext = filename.rpartition('.')</pre>
<blockquote>
<p class="first admonition-title"><strong>Заметка</strong></p>
<p class="last"><span>Многие руководства по стилю Python рекомендуют использовать одно подчеркивание «</span><code class="docutils literal notranslate"><span class="pre">_</span></code><span>» для одноразовых переменных, а не двойное подчеркивание «</span><code class="docutils literal notranslate"><span class="pre">__</span></code><span>», рекомендованное здесь.Проблема заключается в том, что «</span><code class="docutils literal notranslate"><span class="pre">_</span></code><span>» обычно используется в качестве псевдонима для</span><a class="reference external" href="https://docs.python.org/3/library/gettext.html#gettext.gettext" title="(в Python v3.8)"><code class="xref py py-func docutils literal notranslate"><span class="pre">gettext()</span></code></a><span>функции, а также в интерактивном приглашении для хранения значения последней операции.Вместо этого использование двойного подчеркивания является столь же понятным и почти таким же удобным, и исключает риск случайного вмешательства в любой из этих других случаев использования.</span></p>
</blockquote>
<h3><span>Создайте список длины N того же самого </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#create-a-length-n-list-of-the-same-thing" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Используйте </span><code class="docutils literal notranslate"><span class="pre">*</span></code><span>оператор списка Python :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">four_nones = [None] * 4</pre>
<h3><span>Создание списка длины N списков </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#create-a-length-n-list-of-lists" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Поскольку списки являются изменяемыми, </span><code class="docutils literal notranslate"><span class="pre">*</span></code><span>оператор (как указано выше) создаст список из N ссылок на один и тот </span><cite><span>же</span></cite><span> список, что вряд ли вам нужно. Вместо этого используйте понимание списка:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">four_lists = [[] for __ in xrange(4)]</pre>
<p><span>Примечание: используйте range () вместо xrange () в Python 3.</span></p>
<h3><span>Создать строку из списка </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#create-a-string-from-a-list" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Распространенная идиома для создания строк &#8212; использовать </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str.join" title="(в Python v3.8)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.join()</span></code></a><span>пустую строку.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">letters = ['s', 'p', 'a', 'm']
word = ''.join(letters)</pre>
<div class="section" id="create-a-string-from-a-list">
<p><span>Это установит значение переменной </span><em><span>word</span></em><span> в «spam». Эта идиома может применяться к спискам и кортежам.</span></p>
</div>
<div class="section" id="searching-for-an-item-in-a-collection">
<h3><span>Поиск предмета в коллекции </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#searching-for-an-item-in-a-collection" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Иногда нам нужно искать в коллекции вещей. Давайте рассмотрим два варианта: списки и наборы.</span></p>
<p><span>Возьмите следующий код для примера:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">s = set(['s', 'p', 'a', 'm'])
l = ['s', 'p', 'a', 'm']

def lookup_set(s):
    return 's' in s

def lookup_list(l):
    return 's' in l</pre>
<p><span>Хотя обе функции выглядят одинаково, поскольку </span><em><span>lookup_set</span></em><span> использует тот факт, что наборы в Python являются хеш-таблицами, производительность поиска между ними очень различна. Чтобы определить, есть ли элемент в списке, Python должен будет просмотреть каждый элемент, пока не найдет соответствующий элемент. Это отнимает много времени, особенно для длинных списков. В наборе, с другой стороны, хеш элемента сообщит Python, где в наборе искать соответствующий элемент. В результате поиск может быть выполнен быстро, даже если набор большой. Поиск в словарях работает так же. Для получения дополнительной информации см. Эту страницу </span><a class="reference external" href="https://stackoverflow.com/questions/513882/python-list-vs-dict-for-look-up-table"><span>StackOverflow</span></a><span> . Для получения подробной информации о времени, которое различные общие операции выполняют для каждой из этих структур данных, см. </span><a class="reference external" href="https://wiki.python.org/moin/TimeComplexity?"><span>Эту страницу</span></a><span> .</span></p>
<p><span>Из-за этих различий в производительности часто рекомендуется использовать наборы или словари вместо списков в случаях, когда:</span></p>
<ul class="simple">
<li><span>Коллекция будет содержать большое количество предметов</span></li>
<li><span>Вы будете неоднократно искать предметы в коллекции</span></li>
<li><span>У вас нет дубликатов.</span></li>
</ul>
<p><span>Для небольших коллекций или коллекций, в которых вы не часто будете искать, дополнительное время и память, необходимые для настройки хэш-таблицы, часто будут больше, чем время, сэкономленное благодаря улучшенной скорости поиска.</span></p>
<h2><span>Дзен питона </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#zen-of-python" title="Постоянная ссылка на этот заголовок"><span></span></a></h2>
<p><span>Также известен как </span><span class="target" id="index-1"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-0020"><strong><span>PEP 20</span></strong></a><span> , руководящие принципы для дизайна Python.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">&gt;&gt;&gt; import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!</pre>
<p><span>Некоторые примеры хорошего стиля Python см. На </span><a class="reference external" href="https://github.com/hblanks/zen-of-python-by-example"><span>этих слайдах из группы пользователей Python</span></a><span> .</span></p>
<h2><span>Соглашения PEP8</span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#conventions" title="Постоянная ссылка на этот заголовок"><span></span></a></h2>
<p><span>Вот некоторые соглашения, которым вы должны следовать, чтобы сделать ваш код легче для чтения.</span></p>
<h3><span>Проверьте, равна ли переменная постоянной </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#check-if-a-variable-equals-a-constant" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Вам не нужно явно сравнивать значение с True, None или 0 &#8212; вы можете просто добавить его в оператор if. См. </span><a class="reference external" href="http://docs.python.org/library/stdtypes.html#truth-value-testing"><span>Проверка истинности значения</span></a><span> для получения списка того, что считается ложным.</span></p>
<p><strong><span>Плохо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">if attr == True:
    print 'True!'

if attr == None:
    print 'attr is None!'</pre>
<p><strong><span>Хорошо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Just check the value
if attr:
    print 'attr is truthy!'

# or check for the opposite
if not attr:
    print 'attr is falsey!'

# or, since None is considered false, explicitly check for it
if attr is None:
    print 'attr is None!</pre>
<h3><span>Доступ к элементу словаря </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#access-a-dictionary-element" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Не используйте </span><code class="xref py py-meth docutils literal notranslate"><span class="pre">dict.has_key()</span></code><span>метод. Вместо этого используйте синтаксис или передайте аргумент по умолчанию для .</span><code class="docutils literal notranslate"><span class="pre">x</span><span> </span><span class="pre">in</span><span> </span><span class="pre">d</span></code><span></span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict.get" title="(в Python v3.8)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">dict.get()</span></code></a><span></span></p>
<p><strong><span>Плохо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">d = {'hello': 'world'}
if d.has_key('hello'):
    print d['hello']    # prints 'world'
else:
    print 'default_value'</pre>
<p><strong><span>Хорошо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">d = {'hello': 'world'}

print d.get('hello', 'default_value') # prints 'world'
print d.get('thingy', 'default_value') # prints 'default_value'

# Or:
if 'hello' in d:
    print d['hello']</pre>
<h3><span>Короткие способы манипулирования списками </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#short-ways-to-manipulate-lists" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><a class="reference external" href="http://docs.python.org/tutorial/datastructures.html#list-comprehensions"><span>Постижения списков</span></a><span> предоставляют мощный и лаконичный способ работы со списками.</span></p>
<p><a class="reference external" href="http://docs.python.org/tutorial/classes.html#generator-expressions"><span>Выражения генератора</span></a><span> следуют почти тому же синтаксису, что и списки, но возвращают генератор вместо списка.</span></p>
<p><span>Создание нового списка требует больше работы и использует больше памяти. Если вы просто собираетесь пройтись по новому списку, используйте вместо этого итератор.</span></p>
<p><strong><span>Плохо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># needlessly allocates a list of all (gpa, name) entires in memory
valedictorian = max([(student.gpa, student.name) for student in graduates])</pre>
<p><strong><span>Хорошо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">valedictorian = max((student.gpa, student.name) for student in graduates)</pre>
<p><span>Используйте списки, когда вам действительно нужно создать второй список, например, если вам нужно использовать результат несколько раз.</span></p>
<p><span>Если ваша логика слишком сложна для понимания короткого списка или выражения генератора, рассмотрите возможность использования функции генератора вместо возврата списка.</span></p>
<p><strong><span>Хорошо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">def make_batches(items, batch_size):
    """
    &gt;&gt;&gt; list(make_batches([1, 2, 3, 4, 5], batch_size=3))
    [[1, 2, 3], [4, 5]]
    """
    current_batch = []
    for item in items:
        current_batch.append(item)
        if len(current_batch) == batch_size:
            yield current_batch
            current_batch = []
    yield current_batch</pre>
<p><span>Никогда не используйте списочное понимание только для его побочных эффектов.</span></p>
<p><strong><span>Плохо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">[print(x) for x in sequence]</pre>
<p><strong><span>Хорошо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">for x in sequence:
    print(x)</pre>
<h3><span>Фильтрация списка </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#filtering-a-list" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><strong><span>Плохо</span></strong><span> :</span></p>
<p><span>Никогда не удаляйте элементы из списка, пока вы просматриваете его.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Filter elements greater than 4
a = [3, 4, 5]
for i in a:
    if i &gt; 4:
        a.remove(i)</pre>
<p><span>Не делайте несколько проходов по списку.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">while i in a:
    a.remove(i)</pre>
<p><strong><span>Хорошо</span></strong><span> :</span></p>
<p><span>Используйте понимание списка или выражение генератора.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># comprehensions create a new list object
filtered_values = [value for value in sequence if value != x]

# generators don't create another list
filtered_values = (value for value in sequence if value != x)</pre>
<h4><span>Возможные побочные эффекты изменения исходного списка </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#possible-side-effects-of-modifying-the-original-list" title="Постоянная ссылка на этот заголовок"><span></span></a></h4>
<p><span>Изменение исходного списка может быть рискованным, если на него ссылаются другие переменные. Но вы можете использовать </span><em><span>назначение срезов,</span></em><span> если вы действительно хотите это сделать.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># replace the contents of the original list
sequence[::] = [value for value in sequence if value != x]</pre>
<h3><span>Изменение значений в списке </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#modifying-the-values-in-a-list" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><strong><span>Плохо</span></strong><span> :</span></p>
<p><span>Помните, что назначение никогда не создает новый объект. Если две или более переменных ссылаются на один и тот же список, изменение одной из них изменит их все.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Add three to all list members.
a = [3, 4, 5]
b = a                     # a and b refer to the same list object

for i in range(len(a)):
    a[i] += 3             # b[i] also changes</pre>
<p><strong><span>Хорошо</span></strong><span> :</span></p>
<p><span>Безопаснее создать новый объект списка и оставить оригинал в покое.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">a = [3, 4, 5]
b = a

# assign the variable "a" to a new list without changing "b"
a = [i + 3 for i in a]</pre>
<p><span>Используйте </span><a class="reference external" href="https://docs.python.org/3/library/functions.html#enumerate" title="(в Python v3.8)"><code class="xref py py-func docutils literal notranslate"><span class="pre">enumerate()</span></code></a><span>счетчик вашего места в списке.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">a = [3, 4, 5]
for i, item in enumerate(a):
    print i, item
# prints
# 0 3
# 1 4
# 2 5</pre>
<p><a class="reference external" href="https://docs.python.org/3/library/functions.html#enumerate" title="(в Python v3.8)"><code class="xref py py-func docutils literal notranslate"><span class="pre">enumerate()</span></code></a><span>Функция имеет лучшую читаемость , чем обработка счетчика вручную. Более того, он лучше оптимизирован для итераторов.</span></p>
<h3><span>Читать из файла </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#read-from-a-file" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Используйте синтаксис для чтения из файлов. Это автоматически закроет файлы для вас.</span><code class="docutils literal notranslate"><span class="pre">with</span><span> </span><span class="pre">open</span></code><span></span></p>
<p><strong><span>Плохо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">f = open('file.txt')
a = f.read()
print a
f.close()</pre>
<p><strong><span>Хорошо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">with open('file.txt') as f:
    for line in f:
        print line</pre>
<div class="section" id="read-from-a-file">
<p><span>Это </span><code class="docutils literal notranslate"><span class="pre">with</span></code><span>утверждение лучше, потому что оно гарантирует, что вы всегда закроете файл, даже если внутри </span><code class="docutils literal notranslate"><span class="pre">with</span></code><span>блока возникнет исключение .</span></p>
</div>
<div class="section" id="line-continuations">
<h3><span>Продолжение строки </span><a class="headerlink" href="https://docs.python-guide.org/writing/style/#line-continuations" title="Постоянная ссылка на этот заголовок"><span></span></a></h3>
<p><span>Когда логическая строка кода длиннее допустимого предела, вам необходимо разбить ее на несколько физических строк. Интерпретатор Python объединяет последовательные строки, если последний символ строки является обратной косой чертой. Это полезно в некоторых случаях, но, как правило, его следует избегать из-за его хрупкости: пробел, добавленный в конец строки после обратной косой черты, нарушит код и может привести к неожиданным результатам.</span></p>
<p><span>Лучшее решение &#8212; использовать круглые скобки вокруг ваших элементов. Оставленный с незакрытой круглой скобкой в ​​конце строки, интерпретатор Python присоединится к следующей строке, пока круглые скобки не будут закрыты. То же самое относится и к фигурным и квадратным скобкам.</span></p>
<p><strong><span>Плохо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">my_very_big_string = """For a long time I used to go to bed early. Sometimes, \
    when I had put out my candle, my eyes would close so quickly that I had not even \
    time to say “I’m going to sleep.”"""

from some.deep.module.inside.a.module import a_nice_function, another_nice_function, \
    yet_another_nice_function</pre>
<p><strong><span>Хорошо</span></strong><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">my_very_big_string = (
    "For a long time I used to go to bed early. Sometimes, "
    "when I had put out my candle, my eyes would close so quickly "
    "that I had not even time to say “I’m going to sleep.”"
)

from some.deep.module.inside.a.module import (
    a_nice_function, another_nice_function, yet_another_nice_function)</pre>
<p><span>Однако чаще всего разделение длинной логической строки является признаком того, что вы пытаетесь сделать слишком много вещей одновременно, что может ухудшить читабельность.</span></p>
</div>
</div>
</div>
</div>
</div>


<p></p>
<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&amp;linkname=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpep8-python-code-rules-programmers-guide%2F&#038;title=%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0%20%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%BF%D0%BE%20PEP8%20%D0%BD%D0%B0%20Python.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%81%D1%82%D0%B0" data-a2a-url="https://python.ivan-shamaev.ru/pep8-python-code-rules-programmers-guide/" data-a2a-title="Правила оформления кода по PEP8 на Python. Руководство для программиста"></a></p><p>Сообщение <a href="https://python.ivan-shamaev.ru/pep8-python-code-rules-programmers-guide/">Правила оформления кода по PEP8 на Python. Руководство для программиста</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.ivan-shamaev.ru/pep8-python-code-rules-programmers-guide/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Keras Tutorial: Руководство для начинающих по глубокому обучению на Python</title>
		<link>https://python.ivan-shamaev.ru/keras-tutorial-beginner-guide-to-deep-learning-in-python/</link>
					<comments>https://python.ivan-shamaev.ru/keras-tutorial-beginner-guide-to-deep-learning-in-python/#comments</comments>
		
		<dc:creator><![CDATA[Шамаев Иван]]></dc:creator>
		<pubDate>Sun, 08 Dec 2019 20:46:32 +0000</pubDate>
				<category><![CDATA[Машинное обучение. Python]]></category>
		<category><![CDATA[deep learning python]]></category>
		<category><![CDATA[Keras]]></category>
		<category><![CDATA[Keras Python 3]]></category>
		<category><![CDATA[Keras Tutorial]]></category>
		<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[python 3]]></category>
		<category><![CDATA[Глубокое обучение]]></category>
		<category><![CDATA[Глубокое обучение Python]]></category>
		<category><![CDATA[Руководство для начинающих]]></category>
		<guid isPermaLink="false">https://python.ivan-shamaev.ru/?p=463</guid>

					<description><![CDATA[<p>Keras Tutorial: Руководство для начинающих по глубокому обучению на Python 3 В этом пошаговом руководстве по Keras вы узнаете, как построить сверточную нейронную сеть на Python! Фактически, мы будем обучать классификатор для рукописных цифр, который может похвастаться более чем 99% точностью в известном наборе данных MNIST. Прежде чем мы начнем, мы должны отметить, что это [&#8230;]</p>
<p>Сообщение <a href="https://python.ivan-shamaev.ru/keras-tutorial-beginner-guide-to-deep-learning-in-python/">Keras Tutorial: Руководство для начинающих по глубокому обучению на Python</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&#038;title=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" data-a2a-url="https://python.ivan-shamaev.ru/keras-tutorial-beginner-guide-to-deep-learning-in-python/" data-a2a-title="Keras Tutorial: Руководство для начинающих по глубокому обучению на Python"></a></p><blockquote>
<p><strong>Keras Tutorial:</strong> Руководство для начинающих по глубокому обучению на <strong>Python 3</strong></p>
</blockquote>
<p>В этом пошаговом руководстве по Keras вы узнаете, как построить сверточную нейронную сеть на Python!</p>
<p>Фактически, мы будем обучать классификатор для рукописных цифр, который может похвастаться более чем 99% точностью в известном наборе данных MNIST.</p>
<p>Прежде чем мы начнем, мы должны отметить, что это руководство ориентировано на новичков, которые заинтересованы в прикладном глубокого изучения.</p>
<p><strong>Наша цель</strong> &#8212; познакомить вас с одной из самых популярных и мощных библиотек для построения нейронных сетей на Python. Это означает, что мы разберем большую часть теории и математики, но мы также укажем вам на большие ресурсы для их изучения.</p>
<h2><strong>Вступительная часть по Keras Tutorial Python 3</strong></h2>
<p>Для начала изучения машинного обучения на Python с библиотекой Keras, желательно, чтобы Вы:</p>
<ul>
<li>Понимали основные концепции машинного обучения</li>
<li>Имели навыки программирования на Python</li>
</ul>
<h3><strong>Почему Keras?</strong></h3>
<p><strong>Keras</strong> &#8212; рекомендуемая библиотека для глубокого изучения Python, особенно для начинающих. Его минималистичный, модульный подход позволяет с легкостью построить и запустить глубокие нейронные сети.</p>
<p><strong>Типичные рабочие процессы Keras выглядят так:</strong></p>
<ul>
<li>Определите ваши тренировочные данные: входной тензор и целевой тензор.</li>
<li>Определите сеть слоев (или модель), которая отображает входные данные для наших целей.</li>
<li>Настройте процесс обучения, выбрав функцию потерь, оптимизатор и некоторые показатели для мониторинга.</li>
<li>Повторяйте данные тренировки, вызывая метод fit() вашей модели.</li>
</ul>
<h3><strong>Что такое глубокое обучение?</strong></h3>
<p><strong>Глубокое обучение относится к нейронным сетям с несколькими скрытыми слоями</strong>, которые могут изучать все более абстрактные представления входных данных. Это явное упрощение, но для нас это практическое определение для старта в этой дисциплине.</p>
<p>Например, глубокое обучение привело к значительным достижениям в области компьютерного зрения. Теперь мы можем классифицировать изображения, находить в них объекты и даже помечать их заголовками. Для этого глубокие нейронные сети со многими скрытыми слоями могут последовательно изучать более сложные функции из исходного входного изображения:</p>
<ul>
<li>Первые скрытые слои могут изучать только локальные контуры.</li>
<li>Затем каждый последующий слой (или фильтр) изучает более сложные представления.</li>
<li>Наконец, последний слой может классифицировать изображение как кошку или кенгуру.</li>
</ul>
<p>Эти типы глубоких нейронных сетей называются <strong>сверточными нейронными сетями.</strong></p>
<h3><strong>Что такое сверточные нейронные сети (Convolutional Neural Networks CNN)?</strong></h3>
<p>Короче говоря, <strong>сверточные нейронные сети (CNN)</strong> представляют собой многослойные нейронные сети (иногда до 17 или более слоев), которые предполагают, что входные данные являются изображениями.</p>
<p><strong>Типичная архитектура CNN:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/typical_cnn_architecture_keras_tutorial_python3.png"><img fetchpriority="high" decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/typical_cnn_architecture_keras_tutorial_python3.png" alt="" width="640" height="197" class="aligncenter size-full wp-image-472" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/typical_cnn_architecture_keras_tutorial_python3.png 640w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/typical_cnn_architecture_keras_tutorial_python3-300x92.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>
<p>Удовлетворяя это требование, CNN могут резко сократить количество параметров, которые должны быть настроены. Следовательно, CNN могут эффективно справляться с высокой размерностью необработанных изображений.</p>
<p>Их основная механика выходит за рамки этого урока, но вы можете прочитать о них <strong><a href="http://cs231n.github.io/convolutional-networks/" target="_blank" rel="noopener noreferrer">здесь</a></strong>.</p>
<h3><strong>Чем эта статья не является</strong></h3>
<p>Это не полный курс по глубокому обучению. Это руководство предназначено для того, чтобы перенести вас с нуля в вашу первую сверточную нейронную сеть с минимально возможной головной болью!</p>
<p>Если вы заинтересованы в овладении теорией глубокого обучения, мы рекомендуем этот замечательный курс из Стэнфорда:</p>
<ul>
<li><strong><a href="http://cs231n.stanford.edu/" target="_blank" rel="noopener noreferrer">CS231n: сверточные нейронные сети для визуального распознавания</a></strong></li>
</ul>
<h3><strong>О моделях Keras</strong></h3>
<p>В Keras доступно два основных типа моделей: <strong>последовательная модель</strong> и <strong>класс Model</strong>, используемый с функциональным API .</p>
<p><strong>Эти модели имеют ряд общих методов и атрибутов:</strong></p>
<ul>
<li><code>model.layers</code><span> это плоский список слоев, составляющих модель.</span></li>
<li><code>model.inputs</code><span> список входных тензоров модели.</span></li>
<li><code>model.outputs</code><span> список выходных тензоров модели.</span></li>
<li><code>model.summary()</code><span>печатает краткое представление вашей модели.</span></li>
<li><code>model.get_config()</code><span>возвращает словарь, содержащий конфигурацию модели.</span></li>
<li><code>model.get_weights()</code><span><span><span> </span>возвращает список всех весовых тензоров в модели в виде массивов Numpy.</span></span></li>
<li><code>model.set_weights(weights)</code><span><span>устанавливает значения весов модели из списка массивов Numpy.<span> </span></span><span>Массивы в списке должны иметь ту же форму, что и возвращаемые<span> </span></span></span><code>get_weights()</code><span><span>.</span></span></li>
<li><code>model.to_json()</code><span><span>возвращает представление модели в виде строки JSON.<span> </span></span><span>Обратите внимание, что представление не включает веса, только архитектуру.</span></span></li>
<li><code>model.to_yaml()</code><span>возвращает представление модели в виде строки YAML. Обратите внимание, что представление не включает веса, только архитектуру.</span></li>
<li><code>model.save_weights(filepath)</code><span><span><span> </span>сохраняет вес модели в виде файла HDF5.</span></span></li>
<li><code>model.load_weights(filepath, by_name=False)</code><span><span>загружает вес модели из файла HDF5 (созданного<span> </span></span></span><code>save_weights</code><span><span>).<span> </span></span><span>По умолчанию ожидается, что архитектура не изменится.</span></span></li>
</ul>
<h4><strong>Методы API последовательной модели (Sequential model API)</strong></h4>
<h5 id="compile"><strong>Компиляция &#8212; Compile</strong></h5>
<pre class="EnlighterJSRAW" data-enlighter-language="python">compile(
        optimizer, 
        loss=None, 
        metrics=None, 
        loss_weights=None, 
        sample_weight_mode=None, 
        weighted_metrics=None, 
        target_tensors=None
)</pre>
<p><span>Настраивает модель для обучения.</span></p>
<p><strong><span>Аргументы:</span></strong></p>
<ul>
<li><strong>optimizer</strong>: строка (имя оптимизатора) или экземпляр оптимизатора.</li>
<li><strong>loss (потеря)</strong>: <span>строка (имя целевой функции) или целевая функция или </span><code>Loss</code><span>экземпляр. Смотрите </span><a href="https://keras.io/losses"><span>потери</span></a><span>. Если модель имеет несколько выходов, вы можете использовать разные потери на каждом выходе, передав словарь или список потерь. Значение потерь, которое будет минимизировано моделью, будет тогда суммой всех индивидуальных потерь</span>.</li>
<li><strong>metrics</strong>: <span>список метрик, которые будут оцениваться моделью во время обучения и тестирования. Как правило, вы будете использовать </span><code>metrics=['accuracy']</code><span>. Чтобы указать разные метрики для разных выходов модели с несколькими выходами, вы также можете передать словарь, например </span><code>metrics={'output_a': 'accuracy', 'output_b': ['accuracy', 'mse']}</code><span>. Вы также можете передать список (len = len (выводы)) списков метрик, таких как </span><code>metrics=[['accuracy'], ['accuracy', 'mse']]</code><span>или </span><code>metrics=['accuracy', ['accuracy', 'mse']]</code>.</li>
<li><strong>loss_weights</strong>: <span>необязательный список или словарь, задающий скалярные коэффициенты (числа Python) для взвешивания вкладов потерь в различные выходные данные модели. Значение потерь, которое будет минимизировано моделью, будет затем </span><em><span>взвешенной суммой</span></em><span> всех индивидуальных потерь, взвешенных по </span><code>loss_weights</code><span>коэффициентам. Если список, ожидается, что он будет иметь соотношение 1: 1 к выходам модели. Если это диктат, ожидается, что выходные имена (строки) будут сопоставлены скалярным коэффициентам.</span></li>
<li><strong>sample_weight_mode</strong>: <span>Если вам нужно сделать взвешивание выборки по временным шагам (2D веса), установите это значение </span><code>"temporal"</code><span>. </span><code>None</code><span>по умолчанию используются веса выборки (1D). Если модель имеет несколько выходов, вы можете использовать разные </span><code>sample_weight_mode</code><span>на каждом выходе, передав словарь или список режимов.</span></li>
<li><strong>weighted_metrics</strong>: <span>список метрик, которые будут оцениваться и взвешиваться по sample_weight или class_weight во время обучения и тестирования.</span></li>
<li><strong>target_tensors</strong>: <span>по умолчанию <strong>Keras</strong> создаст заполнители для цели модели, которые будут <strong>снабжены</strong> целевыми данными во время обучения. Если вместо этого вы хотите использовать свои собственные целевые тензоры (в свою очередь, Keras не будет ожидать внешних данных Numpy для этих целей во время обучения), вы можете указать их с помощью </span><code>target_tensors</code><span>аргумента. Это может быть один тензор (для модели с одним выходом), список тензоров или точные сопоставления выходных имен с целевыми тензорами.</span></li>
<li><strong>**kwargs</strong>: <span>при использовании бэкэндов Theano / CNTK эти аргументы передаются в </span><code>K.function</code><span>. При использовании бэкэнда TensorFlow эти аргументы передаются в </span><code>tf.Session.run</code><span>.</span></li>
</ul>
<h5><strong>fit</strong></h5>
<p><span>Обучает модель для фиксированного числа эпох (итераций в наборе данных).</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">fit(
        x=None, 
        y=None, 
        batch_size=None, 
        epochs=1, 
        verbose=1, 
        callbacks=None, 
        validation_split=0.0, 
        validation_data=None, 
        shuffle=True, 
        class_weight=None, 
        sample_weight=None, 
        initial_epoch=0, 
        steps_per_epoch=None, 
        validation_steps=None, 
        validation_freq=1, 
        max_queue_size=10, 
        workers=1, 
        use_multiprocessing=False
)</pre>
<p><strong>Аргументы:</strong></p>
<ul>
<li><strong>x</strong>: <span>входные данные. Это может быть</span>:
<ul>
<li><span><span>Массив Numpy (или похожий на массив) или список массивов (в случае, если модель имеет несколько входов).</span></span></li>
<li><span><span>Диктовое отображение (dict mapping) входных имен в соответствующий массив / тензоры, если модель имеет именованные входы.</span></span></li>
<li><span><span>Генератор или<span> </span></span></span><code>keras.utils.Sequence</code><span><span>возвращение<span> </span></span></span><code>(inputs, targets)</code><span><span>или<span> </span></span></span><code>(inputs, targets, sample weights)</code><span><span>.</span></span></li>
<li><span><span>None (default) &#8212; Нет (по умолчанию) при подаче из тензоров, встроенных в каркас (например, тензоры данных TensorFlow)</span></span>.</li>
</ul>
</li>
<li><strong>y</strong>: <span>целевые данные. Как и входные данные </span><code>x</code><span>, это могут быть либо массив (ы) Numpy, тензор (ы), встроенные в платформу, список массивов Numpy (если модель имеет несколько выходных данных), либо None (по умолчанию), если они поступают из тензоров, встроенных в платформу (например, TensorFlow) тензоры данных). Если выходным слоям в модели присвоены имена, вы также можете передать словарь, отображающий выходные имена в массивы Numpy. If </span><code>x</code><span>является генератором или  </span><code>keras.utils.Sequence </code><span>экземпляром, </span><code>y</code> <span>указывать не следует (поскольку цели будут получены из </span><code>x</code><span>).</span></li>
<li><strong>batch_size</strong>: <span>целое число или </span><code>None</code><span>. Количество образцов на обновление градиента. Если </span><code>batch_size</code><span>не указан, по умолчанию будет 32. Не указывайте, </span><code>batch_size</code><span>если ваши данные представлены в виде символических тензоров, генераторов или </span><code>Sequence</code><span>экземпляров (так как они генерируют пакеты).</span></li>
<li><strong>epochs</strong>: <span>целочисленные. Количество эпох для обучения модели. Эпоха &#8212; это итерация по всему </span><code>x</code><span>и </span><code>y</code><span> предоставленным данным. Обратите внимание, что в сочетании с </span><code>initial_epoch</code><span>, </span><code>epochs</code><span>следует понимать как «конечную эпоху». Модель не обучается для ряда итераций, заданных </span><code>epochs</code><span>, а просто до тех пор, пока не </span><code>epochs</code><span>будет достигнута эпоха индекса .</span></li>
<li><strong>verbose</strong>: <span>Integer. </span><span>0, 1 или 2. Режим многословия. </span><span>0 = тихий, 1 = индикатор выполнения, 2 = одна строка за эпоху.</span></li>
<li><strong>callbacks</strong>: <span>список </span><code>keras.callbacks.Callback</code><span>экземпляров. Список обратных вызовов, применяемых во время обучения и проверки (если). Смотрите </span><a href="https://keras.io/callbacks"><span>обратные вызовы</span></a><span>.</span></li>
<li><strong>validation_split</strong>: <span>с плавающей точкой от 0 до 1. Доля данных обучения, которые будут использоваться в качестве данных проверки. Модель выделит эту часть обучающих данных, не будет обучаться им и будет оценивать потери и любые метрики модели на этих данных в конце каждой эпохи. Данные проверки выбираются из последних выборок </span><code>x</code><span>и </span><code>y</code><span>предоставленных данных перед перетасовкой. Этот аргумент не поддерживается, когда он </span><code>x</code><span>является генератором или </span><code>Sequence</code><span>экземпляром.</span></li>
<li><strong>validation_data</strong>:
<p><span>данные для оценки потерь и любые метрики модели в конце каждой эпохи. Модель не будет обучаться на этих данных. </span><code>validation_data</code><span>перекроет </span><code>validation_split</code><span>. </span><code>validation_data</code><span>может быть: &#8212; кортеж </span><code>(x_val, y_val)</code><span>массивов или тензоров </span><code>(x_val, y_val, val_sample_weights)</code><span>Numpy &#8212; кортеж массивов Numpy &#8212; набор данных или итератор набора данных</span></p>
<p><span>Для первых двух случаев, </span><code>batch_size</code><span>должны быть предоставлены. Для последнего случая, </span><code>validation_steps</code><span>должны быть предоставлены.</span></p>
</li>
<li>
<p><strong>shuffle</strong>: <span>Boolean (следует ли перемешивать данные тренировки перед каждой эпохой) или str (для «партии»). «пакетная» &#8212; это специальная опция для работы с ограничениями данных HDF5; он тасуется кусками размером с партию. Не имеет эффекта, когда </span><code>steps_per_epoch</code><span>нет </span><code>None</code><span>.</span></p>
</li>
<li>
<p><span></span><strong>class_weight</strong>: <span>необязательный словарь, отображающий индексы класса (целые числа) на значение веса (с плавающей запятой), используемое для взвешивания функции потерь (только во время обучения). </span><span>Это может быть полезно для того, чтобы сказать модели «уделять больше внимания» выборкам из недопредставленного класса.</span></p>
</li>
<li><strong>sample_weight</strong>: <span>необязательный массив весов Numpy для обучающих выборок, используемый для взвешивания функции потерь (только во время обучения). Вы можете либо передать плоский (1D) массив Numpy такой же длины, что и входные выборки (отображение весов и выборок 1: 1), либо в случае временных данных вы можете передать двумерный массив с формой </span><code>(samples, sequence_length)</code><span>, чтобы применить разный вес для каждого временного шага каждого образца. В этом случае вы должны обязательно указать </span><code>sample_weight_mode="temporal"</code><span>в </span><code>compile()</code><span>. Этот аргумент не поддерживается, когда </span><code>x</code><span>генератор или </span><code>Sequence</code><span>экземпляр вместо этого предоставляют sample_weights в качестве третьего элемента </span><code>x</code><span>.</span></li>
<li><strong>initial_epoch</strong>: <span>целое число. </span><span>Эпоха, с которой начинается тренировка (полезно для возобновления предыдущего тренировочного заезда).</span></li>
<li><strong>steps_per_epoch</strong>: <span>целое число или </span><code>None</code><span>. Общее количество шагов (партий образцов) до объявления одной эпохи законченной и начала следующей эпохи. При обучении с использованием входных тензоров, таких как тензоры данных TensorFlow, значение по умолчанию </span><code>None</code><span>равно числу выборок в вашем наборе данных, деленному на размер пакета, или 1, если это невозможно определить.</span></li>
<li><strong>validation_steps</strong>: <span>только релевантно, если  </span><code>steps_per_epoch</code><span>  указано. Общее количество шагов (партий образцов) для проверки перед остановкой.</span></li>
<li><strong>validation_steps</strong>: <span>релевантно, только если </span><code>validation_data</code><span>предоставлено и является генератором. Общее количество шагов (партий образцов), которые нужно нарисовать перед остановкой при выполнении проверки в конце каждой эпохи.</span></li>
<li><strong>validation_freq</strong>: <span>уместно, только если предоставлены данные проверки. Целое число или список / кортеж / набор. Если целое число, указывает, сколько тренировочных эпох должно быть выполнено до того, как будет выполнен новый прогон проверки, например, </span><code>validation_freq=2</code><span>выполняет проверку каждые 2 эпохи. Если в списке, кортеже или наборе указываются эпохи, в которых нужно выполнять проверку, например, </span><code>validation_freq=[1, 2, 10]</code><span>выполняет проверку в конце 1-й, 2-й и 10-й эпох.</span></li>
<li><strong>max_queue_size</strong>: <span>целое число. Используется только для генератора или </span><code>keras.utils.Sequence</code><span> входа. Максимальный размер очереди генератора. Если не указано, по </span><code>max_queue_size</code><span>умолчанию будет 10.</span></li>
<li><strong>workers</strong>: <span>целое число. Используется только для генератора или </span><code>keras.utils.Sequence</code><span>входа. Максимальное количество процессов, которые могут ускоряться при использовании потоков на основе процессов. Если не указан, по </span><code>workers</code><span> умолчанию будет 1. Если 0, будет запускать генератор в основном потоке.</span></li>
<li><strong>use_multiprocessing</strong>: <span>Boolean. Используется только для генератора или </span><code>keras.utils.Sequence</code><span>входа. Если </span><code>True</code><span>, используйте процессные потоки. Если не указано, по </span><code>use_multiprocessing</code><span>умолчанию </span><code>False</code><span>. Обратите внимание, что, поскольку эта реализация опирается на многопроцессорность, вы не должны передавать невыгружаемые аргументы генератору, так как они не могут быть легко переданы дочерним процессам.</span></li>
<li><strong>**kwargs</strong>: <span>используется для обратной совместимости.</span></li>
</ul>
<h2><strong>Краткий обзор учебника/статьи по Keras</strong></h2>
<p><strong>Вот перечень шагов для создания вашей первой сверточной нейройнной сети (CNN) с использованием Keras:</strong></p>
<ol>
<li>Настройте свою среду.</li>
<li>Установите Керас / Keras.</li>
<li>Импорт библиотек и модулей.</li>
<li>Загрузить данные изображения из MNIST.</li>
<li>Предварительная обработка входных данных для Keras.</li>
<li>Метки препроцесс-класса для Keras.</li>
<li>Определите архитектуру модели.</li>
<li>Скомпилируйте модель.</li>
<li>Подгонка модели по тренировочным данным.</li>
<li>Оценить модель по данным испытаний.</li>
</ol>
<h3><strong>Шаг 1: Настройте свою рабочую среду</strong></h3>
<p><span>убедитесь, что на вашем компьютере установлено следующее:</span></p>
<ul>
<li><span><strong>Python</strong> 2.7+ (Python 3 тоже хорошо, но Python 2.7 все еще более популярен для науки о данных в целом)</span></li>
<li><span><strong>SciPy</strong> <strong>с NumPy</strong></span></li>
<li><span><strong>Matplotlib</strong> (необязательно, рекомендуется для исследовательского анализа)</span></li>
<li><span><strong>Theano</strong> * ( </span><strong><a href="http://deeplearning.net/software/theano/install.html#install" target="_blank" rel="noopener noreferrer">Инструкция по установке</a></strong><span> )</span></li>
</ul>
<blockquote>
<p><strong>Theano</strong> &#8212; это библиотека <strong>Python</strong>, которая позволяет нам так эффективно оценивать математические операции, включая многомерные массивы. В основном он используется при создании проектов глубокого обучения. <strong>Он работает намного быстрее на графическом процессоре (GPU), чем на CPU.</strong> Theano достигает высоких скоростей, что создает жесткую конкуренцию реализациям на языке C для задач, связанных с большими объемами данных.<br /><strong>Theano </strong>знает, как брать структуры и преобразовывать их в очень эффективный код, который использует numpy и некоторые нативные библиотеки. Он в основном предназначен для обработки типов вычислений, требуемых для алгоритмов больших нейронных сетей, используемых в Deep Learning. Именно поэтому, это очень популярная библиотека в области глубокого обучения.</p>
</blockquote>
<p><em>Рекомендуется установить <strong>Python</strong>, <strong>NumPy</strong>, <strong>SciPy</strong> и <strong>matplotlib</strong> через дистрибутив <a href="https://www.anaconda.com/" target="_blank" rel="noopener noreferrer"><strong>Anaconda</strong></a>. Он поставляется со всеми этими пакетами.</em></p>
<p><strong><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/conda_cheatsheet_command_line_package_and_environment_manager.pdf">Conda Cheatsheet: command line package and environment manager.pdf</a></strong></p>
<hr />
<p><strong>Краткий обзор как настроить Анаконду здесь:</strong></p>
<p><blockquote class="wp-embedded-content" data-secret="1Ax30pKqzT"><a href="https://python.ivan-shamaev.ru/guide-conda-environments-anaconda-python-data-science-platform/">Инструкция по Anaconda &#038; Conda. Как управлять и настроить среду для Python?</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="«Инструкция по Anaconda &#038; Conda. Как управлять и настроить среду для Python?» &#8212; Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект" src="https://python.ivan-shamaev.ru/guide-conda-environments-anaconda-python-data-science-platform/embed/#?secret=1Ax30pKqzT" data-secret="1Ax30pKqzT" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe></p>
<hr />
<p><em><span><strong>* Примечание:</strong> <strong>TensorFlow</strong> также поддерживается (как альтернатива <strong>Theano</strong>), но мы придерживаемся Theano для простоты. Основное отличие состоит в том, что вам необходимо изменить данные немного по-другому, прежде чем передавать их в свою сеть.</span></em></p>
<p><span style="color: #008000;"><strong>Еще раз пробежимся по устанавливаемым библиотекам:</strong></span></p>
<blockquote>
<p><strong>SciPy (произносится как сай пай)</strong> — это пакет прикладных математических процедур, основанный на расширении <strong>Numpy</strong> Python. С SciPy интерактивный сеанс Python превращается в такую же полноценную среду обработки данных и прототипирования сложных систем, как MATLAB, IDL, Octave, R-Lab и SciLab.<br /><strong></strong></p>
<p><strong>Matplotlib</strong> — библиотека на языке программирования Python для визуализации данных.<br /><strong></strong></p>
<p><strong>Theano</strong> — библиотека, которая используется для разработки систем машинного обучения как сама по себе, так и в качестве вычислительного бекэнда для более высокоуровневых библиотек, например, Lasagne, Keras или Blocks.<br /><strong></strong></p>
<p><strong>NumPy</strong> &#8212; это библиотека языка Python, добавляющая поддержку больших многомерных массивов и матриц, вместе с большой библиотекой высокоуровневых (и очень быстрых) математических функций для операций с этими массивами.</p>
</blockquote>
<h4><strong>Проверим правильно ли мы все установили</strong></h4>
<p>Переходим в <strong>Jupyter Notebook</strong> в среде, которая имеет установленные библиотеки/пакеты. Запускаем следующие команды:</p>
<p><strong>1. Для проверки среды:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import sys
print(sys.version)
print(sys.base_prefix)</pre>
<p>Результата:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">3.7.5 (default, Oct 31 2019, 15:18:51) [MSC v.1916 64 bit (AMD64)]
C:\Users\User\.conda\envs\MyNewEnvironmentName</pre>
<p><strong>2. Для проверки библиотек:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import numpy as np
import theano as th
import keras as kr
import matplotlib as mpl

print('numpy:' + np.__version__)
print('theano:' + th.__version__)
print('keras:' + kr.__version__)
print('matplotlib:' + mpl.__version__)</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">numpy:1.17.4
theano:1.0.4
keras:2.2.4
matplotlib:3.1.1</pre>
<p><strong>Как это выглядит в Jupyter Notebook:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/keras_tutorial_check_libs_and_env_conda.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/keras_tutorial_check_libs_and_env_conda.png" alt="Keras Tutorial: Руководство для начинающих по глубокому обучению на Python" width="597" height="375" class="aligncenter size-full wp-image-566" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/keras_tutorial_check_libs_and_env_conda.png 597w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/keras_tutorial_check_libs_and_env_conda-300x188.png 300w" sizes="(max-width: 597px) 100vw, 597px" /></a></p>
<h3><strong>Шаг 2. Импортируем библиотеки и модули для нашего проекта</strong></h3>
<p><span style="color: #ff6600;"><strong>Удаляем предыдущие проверочные шаги из Notebook.</strong></span></p>
<p>Теперь начнем с импорта <strong>numpy</strong> и установки начального числа для генератора псевдослучайных чисел на компьютере. Это позволяет нам воспроизводить результаты из нашего скрипта:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import numpy as np
np.random.seed(123)  # for reproducibility</pre>
<p><span>Далее мы импортируем тип модели <strong>Sequential</strong> из <strong>Keras</strong>. </span><span>Это просто <strong>линейный набор слоев нейронной сети</strong>, и он идеально подходит для того типа <strong>CNN с прямой связью</strong>, который мы строим в этом руководстве.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from keras.models import Sequential</pre>
<p><span>Далее, давайте <strong>импортируем «основные» слои из Keras</strong>. </span><span>Это слои, которые используются практически в любой нейронной сети:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from keras.layers import Dense, Dropout, Activation, Flatten</pre>
<p><span>Затем мы <strong>импортируем слои CNN из Keras.</strong> </span><span>Это сверточные слои, которые помогут нам эффективно тренироваться на данных изображения:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from keras.layers import Convolution2D, MaxPooling2D</pre>
<p><span>Наконец, мы <strong>импортируем некоторые утилиты</strong>. </span><span>Это поможет нам преобразовать наши данные позже:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from keras.utils import np_utils</pre>
<p><span>Теперь у нас есть все необходимое для построения <strong>архитектуры нейронной сети.</strong></span></p>
<h4>Полный текст скрипта после шага 2:</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import numpy as np
np.random.seed(123)  # for reproducibility

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils</pre>
<h3><strong>Шаг 3. Загружаем изображения из MNIST</strong></h3>
<p><span><strong>MNIST</strong> &#8212; отличный набор данных для начала глубокого обучения и компьютерного зрения. </span><span>Это достаточно сложная задача, чтобы гарантировать нейронные сети, но она управляема на одном компьютере.</span></p>
<p><span>Библиотека Keras удобно уже включает это. </span><span>Мы можем загрузить это так:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from keras.datasets import mnist
 
# Load pre-shuffled MNIST data into train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()</pre>
<p><span>Мы можем посмотреть на <strong>форму набора данных</strong>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print(X_train.shape)</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">(60000, 28, 28)</pre>
<p><span>Отлично, получается, что в нашем обучающем наборе 60 000 сэмплов, и размер каждого изображения составляет 28 х 28 пикселей. </span><span>Мы можем подтвердить это, построив первый пример в matplotlib:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from matplotlib import pyplot as plt
plt.imshow(X_train[0])</pre>
<p><strong>Вывод изображения:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/keras_tutorial_matplotlib_image_plt_imshow_xtrain_0.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/keras_tutorial_matplotlib_image_plt_imshow_xtrain_0.png" alt="" width="486" height="342" class="aligncenter size-full wp-image-572" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/keras_tutorial_matplotlib_image_plt_imshow_xtrain_0.png 486w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/keras_tutorial_matplotlib_image_plt_imshow_xtrain_0-300x211.png 300w" sizes="(max-width: 486px) 100vw, 486px" /></a></p>
<p><span>В целом, при работе с компьютерным зрением полезно визуально отобразить данные, прежде чем выполнять какую-либо работу алгоритма. </span><span>Это быстрая проверка работоспособности, которая может предотвратить легко предотвратимые ошибки (например, неверную интерпретацию измерений данных).</span></p>
<h4><strong>Полный скрипт после шага 3</strong></h4>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import numpy as np
np.random.seed(123)  # for reproducibility

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras.datasets import mnist

from matplotlib import pyplot as plt
 
# Загрузка предварительно перемешанных данных MNIST в наборы trains и tests
(X_train, y_train), (X_test, y_test) = mnist.load_data()

# Форма набора данных
print(X_train.shape)

# Вывод изображения
plt.imshow(X_train[0])</pre>
<h3><strong>Шаг 4: Предварительная обработка входных данных для Keras</strong></h3>
<p><span>При использовании бэкэнда Theano вы должны явно объявить размер для </span>глубины<span> входного изображения. Например, полноцветное изображение со всеми 3  </span><strong><span>каналами RGB</span></strong><span> будет иметь глубину 3.</span></p>
<p><span>Наши изображения <strong>MNIST</strong> имеют глубину только 1, но мы должны явно объявить это.</span></p>
<p><span>Другими словами, мы хотим преобразовать наш набор данных из формы<strong> (n, ширина, высота)</strong> в <strong>(n, глубина, ширина, высота)</strong>.</span></p>
<p><span>Вот как мы можем сделать это легко:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">X_train = X_train.reshape(X_train.shape[0], 1, 28, 28)
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28)</pre>
<p><span>Чтобы подтвердить, мы можем снова напечатать размеры <strong>X_train</strong>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print(X_train.shape)</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">(60000, 1, 28, 28)</pre>
<p><span>Последний шаг <strong>предварительной обработки для входных данных</strong> &#8212; преобразовать наш тип данных в </span><strong><span>float32</span></strong><span> и <strong>нормализовать</strong> наши значения данных в диапазоне [0, 1].</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255</pre>
<p><span>Теперь наши входные данные готовы к обучению модели.</span></p>
<h4><strong>Полный текст скрипта после 4 шага</strong></h4>
<pre class="EnlighterJSRAW" data-enlighter-language="null">import numpy as np
np.random.seed(123)  # для воспроизводимости

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras.datasets import mnist

from matplotlib import pyplot as plt
 
# Загрузка предварительно перемешанных данных MNIST в наборы trains и tests
(X_train, y_train), (X_test, y_test) = mnist.load_data()

# Форма набора данных
print("=== Результат X_train.shape ===")
print(X_train.shape)

# Вывод изображения
plt.imshow(X_train[0])

# Преобразование набора данных из формы (n, ширина, высота) в (n, глубина, ширина, высота)
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28)
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28)

# Вывод размеров X_train
print("=== Результат X_train.shape ===")
print(X_train.shape)

# Преобразование типа данных в float32
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')

# Нормализация значений данных в диапазоне [0, 1]
X_train /= 255
X_test /= 255</pre>
<h3><strong>Шаг 5. Предварительная обработка меток классов для Keras</strong></h3>
<p><span>Далее, давайте посмотрим на форму наших данных меток классов:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print(y_train.shape)</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">(60000,)</pre>
<p><span>Хм &#8230; это может быть проблематично. </span><span>У нас должно быть 10 разных классов, по одному на каждую цифру, но, похоже, у нас есть только одномерный массив. </span><span>Давайте посмотрим на ярлыки для первых 10 учебных образцов:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print(y_train[:10])</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">[5 0 4 1 9 2 1 3 1 4]</pre>
<p><span>И есть проблема. Данные y_train и y_test не разделены на 10 различных меток классов, а представлены в виде одного массива со значениями классов.</span></p>
<p><span>Мы можем это легко исправить:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Convert 1-dimensional class arrays to 10-dimensional class matrices
Y_train = np_utils.to_categorical(y_train, 10)
Y_test = np_utils.to_categorical(y_test, 10)</pre>
<blockquote>
<p><strong>Метод np_utils.to_categorical</strong> &#8212; Преобразует вектор класса (целые числа) в двоичную матрицу классов.</p>
</blockquote>
<p><span>Теперь мы можем взглянуть еще раз:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print(Y_train.shape)</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">(60000, 10)</pre>
<h4><strong>Полный текст скрипта после 5 шага</strong></h4>
<pre class="EnlighterJSRAW" data-enlighter-language="null">import numpy as np
np.random.seed(123)  # для воспроизводимости

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras.datasets import mnist

from matplotlib import pyplot as plt
 
# Загрузка предварительно перемешанных данных MNIST в наборы trains и tests
(X_train, y_train), (X_test, y_test) = mnist.load_data()

# Форма набора данных
print("=== Результат X_train.shape ===")
print(X_train.shape)

# Вывод изображения
plt.imshow(X_train[0])

# Преобразование набора данных из формы (n, ширина, высота) в (n, глубина, ширина, высота)
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28)
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28)

# Вывод размеров X_train
print("=== Результат X_train.shape ===")
print(X_train.shape)

# Преобразование типа данных в float32
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')

# Нормализация значений данных в диапазоне [0, 1]
X_train /= 255
X_test /= 255

# Просмотр формы меток классов наших данных
print("=== Результат y_train.shape ===")
print(y_train.shape)

print("=== Результат y_train[:10] ===")
print(y_train[:10])

# Преобразование одномерных массивов классов в 10-мерные матрицы классов
Y_train = np_utils.to_categorical(y_train, 10)
Y_test = np_utils.to_categorical(y_test, 10)

# Вывод после преобразования
print("=== Результат Y_train.shape после np_utils.to_categorical ===")
print(Y_train.shape)</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">=== Результат X_train.shape ===
(60000, 28, 28)

=== Результат X_train.shape ===
(60000, 1, 28, 28)

=== Результат y_train.shape ===
(60000,)

=== Результат y_train[:10] ===
[5 0 4 1 9 2 1 3 1 4]

=== Результат Y_train.shape после np_utils.to_categorical ===
(60000, 10)</pre>
<h3><strong>Шаг 6: Зададим архитектуру модели нейронной сети</strong></h3>
<p>Теперь мы готовы определить архитектуру нашей модели. В реальной научно-исследовательской работе исследователи потратят значительное количество времени на изучение архитектуру моделей.</p>
<p>Чтобы продолжать этот урок, мы не будем обсуждать здесь теорию или математику.</p>
<p>Когда вы только начинаете, вы можете просто воспроизвести проверенную архитектуру из академических работ или использовать существующие примеры. Вот список примеров реализации в Keras.</p>
<p>Начнем с объявления последовательного формата модели:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">model = Sequential()</pre>
<p><span>Далее мы объявляем входной слой:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">model.add(Conv2D(32,(3, 3), activation = 'relu', input_shape=(1,28,28), data_format='channels_first'))</pre>
<p>Входной параметр shape должен иметь форму 1 образца. В этом случае это то же самое (1, 28, 28), которое соответствует (глубина, ширина, высота) каждого изображения цифры.</p>
<p>Но что представляют собой первые 3 параметра? Они соответствуют количеству используемых фильтров свертки, количеству строк в каждом ядре свертки и количеству столбцов в каждом ядре свертки соответственно.</p>
<p>* Примечание. Размер шага по умолчанию равен (1,1), и его можно настроить с помощью параметра «subsample».</p>
<p>Мы можем подтвердить это, напечатав форму текущей модели:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print(model.output_shape)</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">(None, 32, 26, 26)</pre>
<p><span>Затем мы можем просто добавить больше слоев в нашу модель, как будто мы строим legos:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))</pre>
<p><span>Опять же, мы не будем слишком углубляться в теорию, но важно выделить  слой </span><strong><span>Dropout, который</span></strong><span> мы только что добавили. Это метод регуляризации нашей модели с целью предотвращения переоснащения. Вы можете прочитать больше об этом </span><a href="https://www.quora.com/How-does-the-dropout-method-work-in-deep-learning" target="_blank" rel="noopener noreferrer"><span>здесь</span></a><span> .</span></p>
<p><span>MaxPooling2D &#8212; это способ уменьшить количество параметров в нашей модели, переместив фильтр пула 2&#215;2 по предыдущему слою и взяв максимум 4 значения в фильтре 2&#215;2.</span></p>
<p><span>Пока что для параметров модели мы добавили два слоя свертки. Чтобы завершить архитектуру нашей модели, давайте добавим полностью связанный слой, а затем выходной слой:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))</pre>
<p><span>Для плотных слоев первым параметром является выходной размер слоя. Keras автоматически обрабатывает связи между слоями.</span></p>
<p><span>Обратите внимание, что конечный слой имеет выходной размер 10, соответствующий 10 классам цифр.</span></p>
<p><span>Также обратите внимание, что веса из слоев Convolution должны быть сплющены (сделаны одномерными) перед передачей их в полностью связанный плотный слой.</span></p>
<p><span>Вот как выглядит вся архитектура модели:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">model = Sequential()

model.add(Conv2D(32,(3, 3), activation = 'relu', input_shape=(1,28,28), data_format='channels_first'))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))</pre>
<p><span>Теперь все, что нам нужно сделать, это определить функцию потерь и оптимизатор, и тогда мы будем готовы обучить ее.</span></p>
<h3><strong>Шаг 7. Скомпилируем модель</strong></h3>
<p><span>Сложная часть уже закончилась.</span></p>
<p><span>Теперь нам просто нужно скомпилировать модель, и мы будем готовы обучать ее. </span><span>Когда мы компилируем модель, мы объявляем функцию потерь и оптимизатор (SGD, Adam и т.д.).</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])</pre>
<p>Keras имеет множество функций потери и встроенных оптимизаторов на выбор.</p>
<h3><strong>Шаг 8. Обучим модель на тестовых данных (тренировочных данных)</strong></h3>
<p><span>Чтобы соответствовать модели, все, что нам нужно сделать, это объявить размер партии и количество эпох для обучения, а затем передать наши данные обучения.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">model.fit(X_train, Y_train, 
          batch_size=32, epochs=10, verbose=1)</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">Epoch 1/10
60000/60000 [==============================] - 38100s 635ms/step - loss: 0.2253 - acc: 0.9337
Epoch 2/10
60000/60000 [==============================] - 728s 12ms/step - loss: 0.1195 - acc: 0.9650
Epoch 3/10
60000/60000 [==============================] - 964s 16ms/step - loss: 0.0927 - acc: 0.9724
Epoch 4/10
60000/60000 [==============================] - 1169s 19ms/step - loss: 0.0778 - acc: 0.9768
Epoch 5/10
60000/60000 [==============================] - 1223s 20ms/step - loss: 0.0709 - acc: 0.9794
Epoch 6/10
60000/60000 [==============================] - 730s 12ms/step - loss: 0.0640 - acc: 0.9809
Epoch 7/10
60000/60000 [==============================] - 749s 12ms/step - loss: 0.0578 - acc: 0.9828
Epoch 8/10
60000/60000 [==============================] - 730s 12ms/step - loss: 0.0554 - acc: 0.9825
Epoch 9/10
60000/60000 [==============================] - 728s 12ms/step - loss: 0.0528 - acc: 0.9848
Epoch 10/10
60000/60000 [==============================] - 719s 12ms/step - loss: 0.0495 - acc: 0.9852</pre>
<p><span>Вы также можете использовать различные </span><a href="https://keras.io/callbacks/" target="_blank" rel="noopener noreferrer"><span>обратные вызовы</span></a><span>  для установки правил ранней остановки, сохранения весов моделей по ходу дела или регистрации истории каждой эпохи обучения.</span></p>
<h3><strong>Шаг 9: Оценка работы модели на тестовых данных</strong></h3>
<p><span>Наконец, мы можем оценить нашу модель по тестовым данным:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">score = model.evaluate(X_test, Y_test, verbose=0)
score</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">[2.3163251502990723, 0.0986]</pre>


<p></p>
<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&amp;linkname=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fkeras-tutorial-beginner-guide-to-deep-learning-in-python%2F&#038;title=Keras%20Tutorial%3A%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%BB%D1%8F%20%D0%BD%D0%B0%D1%87%D0%B8%D0%BD%D0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%BF%D0%BE%20%D0%B3%D0%BB%D1%83%D0%B1%D0%BE%D0%BA%D0%BE%D0%BC%D1%83%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8E%20%D0%BD%D0%B0%20Python" data-a2a-url="https://python.ivan-shamaev.ru/keras-tutorial-beginner-guide-to-deep-learning-in-python/" data-a2a-title="Keras Tutorial: Руководство для начинающих по глубокому обучению на Python"></a></p><p>Сообщение <a href="https://python.ivan-shamaev.ru/keras-tutorial-beginner-guide-to-deep-learning-in-python/">Keras Tutorial: Руководство для начинающих по глубокому обучению на Python</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.ivan-shamaev.ru/keras-tutorial-beginner-guide-to-deep-learning-in-python/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
