Как хакеры подменяют DNS-запросы с помощью «отравления» кэша

Подмена сервера доменных имен (DNS) — это кибератака, с помощью которой злоумышленник направляет трафик жертвы на вредоносный сайт (вместо легитимного IP-адреса). Злоумышленники используют метод «отравления» кэша DNS для перехвата интернет-трафика и кражи учетных данных или конфиденциальной информации. Отравление кэша DNS и подмена DNS — тождественные понятия, часто используемые как синонимы. Хакер хочет обманом заставить пользователей ввести личные данные на небезопасном сайте. Как ему этого добиться? С помощью отравления кэша DNS. Для этого хакер подменяет или заменяет данные DNS для определенного сайта, а затем перенаправляет жертву на сервер злоумышленника вместо легитимного сервера. Таким образом хакер добивается своей цели, ведь перед ним открываются широкие возможности: он может совершить фишинговую атаку, украсть данные или даже внедрить в систему жертвы вредоносную программу.

Что такое подмена DNS и отравление кэша?

Прежде чем начать разговор об отравлении кэша DNS, сначала давайте вспомним, что такое DNS и кэширование DNS. DNS — это всемирный каталог IP-адресов и доменных имен. Можно сказать, что это своеобразный телефонный справочник интернета. DNS переводит удобные для пользователей адреса, такие как varonis.com, в IP-адреса, например 92.168.1.169, которые используются компьютерами для работы в сети. Кэширование DNS — это система хранения адресов на DNS-серверах по всему миру. Для ускорения обработки ваших DNS-запросов разработчики создали распределенную систему DNS. Каждый сервер хранит список известных ему DNS-записей, который называется кэшем. Если на ближайшем к вам DNS-сервере нужный IP-адрес отсутствует, он запрашивает вышестоящие DNS-серверы до тех пор, пока адрес веб-сайта, на который вы пытаетесь попасть, не будет найден. После этого ваш DNS-сервер сохраняет эту новую запись в вашем кэше, чтобы в следующий раз получить ответ быстрее.

Примеры и последствия отравления кэша DNS

Концепция DNS не приспособлена к специфике современного интернета. Конечно, со временем DNS был усовершенствован, однако сейчас по-прежнему достаточно одного неправильно настроенного DNS-сервера, чтобы миллионы пользователей ощутили на себе последствия. Пример — атака на WikiLeaks, когда злоумышленники с помощью отравления кэша DNS перехватывали трафик, перенаправляя его на собственный клон сайта. Целью этой атаки было увести трафик с WikiLeaks, и она достигла определенного успеха. Отравление кэша DNS весьма непросто обнаружить обычным пользователям. В настоящее время система DNS построена на доверии, и это является ее слабым местом. Люди чересчур сильно доверяют DNS и никогда не проверяют, соответствует ли адрес в их браузере тому, что им в действительности нужно. Злоумышленники же пользуются этой беспечностью и невнимательностью для кражи учетных данных и другой важной информации.

Как работает отравление кэша DNS?

Отравление кэша DNS означает, что на ближайшем к вам DNS-сервере содержится запись, отправляющая вас по неверному адресу, который, как правило, контролируется злоумышленником. Существует ряд методов, которые используют злоумышленники для отравления кэша DNS.

Перехват трафика локальной сети с помощью подмены протокола ARP

Вы удивитесь, насколько уязвимой может быть локальная сеть. Многие администраторы могут пребывать в уверенности, что перекрыли все возможные доступы, но, как известно, дьявол кроется в деталях.

Одна из распространенных проблем — сотрудники, работающие удаленно. Можно ли быть уверенными, что их сеть Wi-Fi защищена? Хакеры могут взломать слабый пароль от сети Wi-Fi за считанные часы.

Еще одна проблема — открытые порты Ethernet, доступные всем желающим в коридорах, вестибюлях и других общественных местах. Просто представьте: посетитель может подключить к своему устройству кабель Ethernet, предназначенный для дисплея в вестибюле. Как хакер может использовать доступ к вашей локальной сети, полученный одним из перечисленных выше способов? Во-первых, он сможет создать фишинговую страницу для сбора учетных данных и другой ценной информации. Затем он может разместить этот сайт либо в локальной сети, либо на удаленном сервере, и для этого ему потребуется всего-навсего одна строка кода на Python. После этого хакер может начать следить за сетью с помощью специальных инструментов, таких как Betterrcap. На этом этапе хакер изучает сеть и производит рекогносцировку, но трафик все еще проходит через маршрутизатор. Затем злоумышленник может совершить подмену протокола разрешения адресов (ARP), чтобы изнутри изменить структуру сети. Протокол ARP используется сетевыми устройствами для связывания MAC-адреса устройства с IP-адресом в сети. Bettercap будет отправлять сообщения, заставляя все устройства в сети считать компьютер хакера маршрутизатором. Благодаря этой уловке хакер сможет перехватывать весь сетевой трафик, проходящий через маршрутизатор. Достигнув перенаправления трафика, злоумышленник может запустить модуль Bettercap для подмены DNS. Этот модуль будет искать любые запросы к целевому домену и отправлять жертве ложные ответы. Ложный ответ содержит IP-адрес компьютера злоумышленника, переправляя все запросы к целевому сайту на фишинговую страницу, созданную хакером. Теперь хакер видит трафик, предназначенный для других устройств в сети, собирает вводимые учетные данные и внедряет вредоносные загрузки.
Если же хакер не может получить доступ к локальной сети, он прибегнет к одной из следующих атак.

Подделка ответов с помощью атаки «дней рождения»

DNS не проверяет подлинность ответов на рекурсивные запросы, поэтому в кэше сохраняется первый ответ. Злоумышленники используют так называемый «парадокс дней рождения», чтобы попытаться предугадать и отправить поддельный ответ запрашивающей стороне. Для предугадывания атака «дней рождения» использует математику и теорию вероятностей. В этом случае злоумышленник пытается угадать идентификатор транзакции вашего DNS-запроса, и в случае успеха поддельная запись DNS попадает к вам раньше легитимного ответа. Успех атаки «дней рождения» не гарантирован, но в конце концов злоумышленник сможет подложить в кэш поддельный ответ. После того как атака увенчается успехом, хакер сможет видеть трафик от поддельной записи DNS до окончания жизненного цикла (TTL) записи DNS.

Эксплойт Каминского

Эксплойт Каминского является разновидностью атаки «дней рождения». Обнаруживший эту уязвимость Дэн Каминский впервые представил ее на конференции BlackHat в 2008 году. Суть эксплойта заключается в том, что сначала хакер отправляетDNS-резолверу запрос для несуществующего домена, например fake.varonis.com. Получив такой запрос, DNS-резолвер перенаправляет его на авторитетный сервер имен, чтобы получить IP-адрес ложного субдомена. На этом этапе злоумышленник перегружает DNS-резолвер огромным количеством поддельных ответов в надежде, что один из этих поддельных ответов совпадет с идентификатором транзакции исходного запроса. В случае успеха хакер подменяет в кэше DNS-сервера IP-адрес, например, как в нашем примере с varonis.com. Резолвер продолжит отвечать всем запрашивающим, что поддельный IP-адрес varonis.com является настоящим, пока не истечет жизненный цикл записи DNS.

Как обнаружить отравление кэша DNS?

Как обнаружить, что кэш DNS отравлен? Для этого нужно следить за вашими DNS-серверами в поисках индикаторов возможной атаки. Однако ни у кого нет вычислительных мощностей, чтобы справиться с такими объемами DNS-запросов. Лучшим решением будет применить к вашему мониторингу DNS аналитику безопасности данных. Это позволит отличить нормальное поведение DNS от атак злоумышленников.
• Внезапное увеличение активности DNS из одного источника в отношении одного домена свидетельствует о потенциальной атаке «дней рождения».
• Увеличение активности DNS из одного источника, который запрашивает у вашего DNS-сервера многочисленные доменные имена без рекурсии, свидетельствует о попытке подобрать запись для последующего отравления.
Помимо мониторинга DNS необходимо также вести мониторинг событий Active Directory и поведения файловой системы, чтобы вовремя обнаружить аномальную активность. А еще лучше будет использовать аналитику для поиска взаимосвязи между всеми тремя векторами. Это позволит получить ценную контекстную информацию для усиления стратегии кибербезопасности.

Способы защиты от отравления кэша DNS

Помимо мониторинга и аналитики вы можете внести изменения в настройки DNS-сервера:

  • ограничьте рекурсивные запросы, чтобы защититься от потенциального целевого отравления кэша;
  • храните только данные, относящиеся к запрашиваемому домену;
  • ограничьте ответы только теми, которые касаются запрашиваемого домена;
  • требуйте у клиентов использовать протокол HTTPS.

Убедитесь, что вы используете последние версии программного обеспечения BIND и DNS и, таким образом, имеете все актуальные исправления уязвимостей. Если возможно, например, в случае с удаленными сотрудниками, организуйте работу так, чтобы все удаленные компьютеры были подключены через VPN. Это защитит трафик и DNS-запросы от локального отслеживания. Кроме того, стимулируйте сотрудников создавать надежные пароли для сетей Wi-Fi, чтобы также снизить риски.

И, наконец, используйте зашифрованные DNS-запросы. Модули безопасности службы доменных имен (DNSSEC) — это протокол DNS, который использует подписанные DNS-запросы для предотвращения их подмены. При использовании DNSSEC, DNS-резолверу необходимо проверить подпись на уполномоченном DNS-сервере, что замедляет весь процесс. Вследствие этого DNSSEC пока не получил широкого распространения.

DNS поверх HTTPS (DoH) и DNS поверх TLS (DoT) являются конкурирующими спецификациями для следующей версии DNS и, в отличие от DNSSEC, предназначены для обеспечения безопасности DNS-запросов без ущерба скорости. Тем не менее эти решения не идеальны, поскольку могут замедлить или полностью сделать невозможным локальный мониторинг и анализ DNS. Важно отметить, что DoH и DoT могут обходить родительский контроль и другие блокировки на уровне DNS, установленные в сети. Несмотря на это, Cloudflare, Quad9 и Google имеют общедоступные DNS-серверы с поддержкой DoT. Многие новые клиенты поддерживают эти современные стандарты, хотя их поддержка и отключена по умолчанию. Вы можете найти более подробную информацию об этом в нашем посте по безопасности DNS.

Подмена DNS заменяет легитимный IP-адрес сайта на IP-адрес компьютера хакера. Обнаружить подмену очень непросто, ведь с точки зрения конечного пользователя он вводит в браузере абсолютно нормальный адрес сайта. Несмотря на это остановить подобную атаку можно. Риски снизить можно, используя мониторинг DNS, например, от Varonis, а также стандарт шифрования DNS поверх TLS (DoT).

Отравление кэша: часто задаваемые вопросы

Ознакомьтесь с распространенными вопросами о подмене DNS и ответами на них.

Отравление кэша DNS и подмена кэша DNS (спуфинг) — это одно и то же?

Да, отравлением кэша и подменой кэша называют один и тот же тип кибератаки.

Как работает отравление кэша DNS?

Отравление кэша обманывает ваш DNS-сервер, сохраняя на нём поддельную запись DNS. После этого трафик перенаправляется на сервер, выбранный хакером, и там осуществляется кража данных.

Какие меры безопасности можно применять для защиты от отравления кэша DNS?

Владельцы сайта могут осуществлять мониторинг и аналитику для выявления подмены DNS. Кроме того, можно обновить DNS-серверы, чтобы использовать модули безопасности службы доменных имен (DNSSEC) или другую систему шифрования, например DNS поверх HTTPS или DNS поверх TLS. Повсеместное использование полного сквозного шифрования, такого как HTTPS, также может предотвратить подмену DNS. Брокеры безопасного облачного доступа (CASB) чрезвычайно полезны для этих целей. Конечные пользователи могут сбросить потенциально подделанный кэш DNS, периодически очищая кэш DNS своего браузера, или после подключения к небезопасной или общедоступной сети. Использование VPN может защитить от подмены DNS в локальной сети. Избегайте подозрительных ссылок. Это поможет избежать риска заражения кэша вашего браузера.

Как проверить, подверглись ли вы атаке с отравлением кэша?

После того как кэш DNS был отравлен, это сложно обнаружить. Куда лучшая тактика — осуществлять мониторинг ваших данных и защищать систему от вредоносных программ, чтобы уберечься от утечек данных в следствие отравления кэша DNS. Посетите нашу интерактивную лабораторию кибератак, чтобы увидеть, как мы используем мониторинг DNS для обнаружения реальных угроз кибербезопасности.

Как работает связь DNS?

Когда конечный пользователь вводит URL-адрес, например Varonis.com, в свой браузер, происходит следующее:

  1. Сначала браузер проверит свой локальный кэш на наличие уже сохраненных данных DNS.
  2. Если эти данные отсутствуют, он запросит вышестоящий DNS-сервер, которым, как правило, является ваш маршрутизатор в локальной сети.
  3. Если маршрутизатор в своем кэше тоже не содержит требуемой записи DNS, то запрос отправится дальше, к вышестоящим поставщикам DNS, таким как Google, Cloudflare или Quad9.
  4. Этот вышестоящий сервер получит DNS-запрос и проверит свой кэш.
    4.1. Если данных в кэше нет, запустится рекурсивный DNS-резолвер, и сначала будут запрошены корневые серверы DNS с вопросом «кто обрабатывает .com».
    4.2. Затем резолвер отправит запрос серверу домена верхнего уровня .com, чтобы узнать «кто обрабатывает Varonis.com», на который домен верхнего уровня отвечает полномочным сервером имен для данного URL.
    4.3. После этого резолвер отправляет запрос полномочному серверу имен вопрос «какой IP-адрес у Varonis.com», на который полномочный сервер отвечает IP-адресом домена.
  5. Затем данные DNS отправляются обратно по цепочке, пока не попадут на устройство конечного пользователя. На всем пути следования каждый из DNS-серверов запишет полученный ответ в свой кэш для дальнейшего использования.

Как злоумышленники отравляют кэш DNS?

Способов отравления кэша много, и вот самые распространенные из них: принудить жертву нажать на вредоносную ссылку, использующую встроенный код для изменения кэша DNS в браузере пользователя; взлом локального DNS-сервера с помощью «атаки через посредника». Вышеупомянутая «атака через посредника» использует подмену протокола разрешения адресов (ARP) для перенаправления DNS-запросов на DNS-сервер, контролируемый злоумышленником.

Что такое отравление кэша DNS?

Отравление кэша DNS — это действия по замене записи в базе данных DNS на IP-адрес, ведущий на вредоносный сервер, контролируемый злоумышленником.

Как выполняется подмена DNS?

Хакер выполняет атаку с подменой DNS, получая доступ и изменяя кэш DNS или перенаправляя запросы DNS на свой собственный DNS-сервер.

Что подразумевается под подменой DNS (спуфингом)?

Понятие «подмена DNS» (спуфинг) значит, что URL, вводимый пользователем в браузере, например varonis.com, на самом деле не ведет на нужный официальный IP-адрес, соответствующий этому URL. Вместо этого пользователь перенаправляется на вредоносный сервер, контролируемый хакером.

Чем опасна подмена DNS?

Подмена DNS представляет опасность, потому что по своей природе служба имен доменов (DNS) считается надежной, поэтому зачастую ее не защищают каким-либо шифрованием. Это приводит к тому, что хакеры могут подменять записи в кэше DNS для дальнейшей кражи данных, внедрения вредоносных программ, фишинга и блокировки обновлений.
Основная угроза, которую представляет атака подменой DNS, заключается в краже данных через фишинговые страницы. Помимо этого существует риск внедрения вредоносной программы под видом загружаемых файлов, которые выглядят настоящими. Также, если обновление системы производится через интернет, злоумышленник может блокировать обновление, изменяя записи в DNS так, чтобы они не вели на нужный сайт.

ссылка на оригинал статьи https://habr.com/ru/company/varonis/blog/555330/

Полив газона с помощью модели сегментации изображений и системы на базе Arduino

Инженерная цель данного эксперимента заключалась в разработке системы из трёх частей, а именно модели сегментации изображения, скрипта управления двигателем и спринклера, работающего под управлением Arduino. Эта система должна целенаправленно поливать участки травяного газона, что позволит сэкономить значительное количество воды, а заодно и времени.


Задача

Представьте, что вы прогуливаетесь по своему кварталу мимо красивых зелёных лужаек. Что такое?.. Вода же должна литься на газон, а не на тротуар рядом! Здесь люди ходят! Слева от вас большой газон орошается из-под земли десятком спринклеров. Но, хоть вся трава и поливается обильно, на газоне тут и там заметны проплешины. Многие не видят в этом проблемы — эка невидаль! — и безмятежно прыгают через лужи. Но проблема здесь не только в лужах, а в том, что, несмотря на использование такого количества воды, газон всё равно не растёт нормально. И проблема эта более серьёзная, чем можно подумать. В Америке от 30 до 60 % городской пресной воды используется для полива газонов, и самое печальное, что приблизительно 50 % этой воды тратится впустую из-за небрежно или неправильно установленной системы полива.

Уход за газонами недешёвое занятие. Чтобы газоны росли так, как нужно, необходимо правильно подобрать удобрения, компост и, самое главное, правильно их поливать. В этой статье я расскажу о разработанном мною решении — какие шаги я предпринял при планировании, создании прототипа и внедрении.

Первоначальные соображения

В начале этого проекта у меня не было ни опыта работы с методами машинного распознавания образов, не говоря уже о каком-никаком плане.

Сухие проплешины.
Сухие проплешины.

Разница в цвете между светло-коричневыми участками и зеленью здоровой травы сразу бросается в глаза. Я начал решать задачу так: проанализировал RGB-значения различных областей изображения. Если бы я мог выявлять «менее зелёные» области и найти критерий, по которому такие участки можно было выделять, я мог бы их точно определить. Однако всё оказалось не так просто, как я думал. 

Главной проблемой было множество внешних факторов, на которые я повлиять не мог, но они могли сами повлиять на результаты. Например, RGB-значение участка изображения может быть изменено ночным электрическим освещением. При таком количестве посторонних факторов система была бы просто нежизнеспособна. Мне определённо нужно было искать лучшее решение.

Сегментация изображений

Новое решение оформилось в виде концепции, называемой сегментацией изображения. Сегментация изображений — это процесс машинного распознавания образов, разделяющий изображения на «сегменты» на основе сходства пикселей. В основном он используется, чтобы обнаруживать на изображении объекты (в таком случае он называется методом обнаружения объектов), и применяется в автономных транспортных средствах, при обработке медицинских изображений и спутниковой съёмке.

Сегментация изображений.
Сегментация изображений.

Используя метод сегментации изображений, я смог бы обнаружить проплешины на газоне. И я засел за изучение методов создания моделей сегментации изображений с помощью Tensorflow.

Я обнаружил замечательную библиотеку под названием ImageAI, написанную Олафенвой Мозесом. Библиотека ImageAI позволяет обнаруживать объекты с использованием набора данных, созданного пользователем. С помощью ImageAI мне удалось подобрать оптимальный набор данных, наиболее подходящий для моей модели.

Первый набор данных / Тестовый

Методы машинного обучения работают только в том случае, если в них заложены данные. Без большого количества точных и осмысленных данных обучать модели и получать прогнозы об окружающем нас мире практически невозможно. Если мы хотим хорошо обучить студента, мы должны предоставить ему как можно больше ресурсов, чтобы обучение было эффективным.

Бесплатные общедоступные наборы данных можно найти на множестве веб-сайтов и во многих приложениях. Эти данные, в частности, могут использовать инженеры при работе над проектами. Однако для моего проекта никаких наборов данных не было, и поэтому мне пришлось создавать свои собственные. Как выяснилось, создание набора данных оказалось чуть ли не самой сложной проблемой во всём проекте.

Набор данных для сегментации изображений состоит из двух частей: изображений и аннотаций. Существует множество способов аннотирования изображений, то есть пометок места расположения объекта на изображении. Я использовал формат Pascal VOC, сохраняющий аннотации в файлах .xml. То есть, если мой набор данных содержит 50 изображений, мне пришлось бы  аннотировать каждое отдельное изображение и создать 50 xml-файлов с  аннотациями соответствующих изображений.

Вначале у меня было много вопросов о наборе данных: сколько изображений нужно иметь, как  аннотировать изображение, как использовать аннотацию в коде, как узнать, подходит ли для модели то или иное изображение, и так далее. Тут мне здорово помог Олафенва Мозес, который, к счастью, написал очень информативную  статью о том, как создавать пользовательский набор данных и использовать его в библиотеке ImageAI.

Первым шагом было получение изображений, и он оказался значительно сложнее, чем предполагалось. Как я ни старался, я не смог найти в сети нужные мне высококачественные изображения. Я погуглил строку «трава с проплешинами», и для первого набора данных мне удалось загрузить всего 65 изображений. Чтобы вы понимали — большинство наборов данных содержат тысячи изображений, и только тогда их имеет смысл использовать для обучения модели.

После сбора изображений я закомментировал их с помощью программы Label IMG. Я создал каталог с изображениями и каталог для аннотаций. Затем я поставил аннотацию к каждому изображению, обведя в рамки все проплешины. Привожу ниже скриншот программы Label IMG, которую я использовал для аннотирования изображений.

Программа Label IMG.
Программа Label IMG.

Я, наконец, получил полный набор данных с  аннотациями и изображениями и был готов приступить к обучению своей модели. С набором данных и загруженными библиотеками у меня возникло много проблем, но мне удалось их решить, и я обучил свою первую модель за 15 эпох с размером пакета 4.

Набор данных 1. Результаты.
Набор данных 1. Результаты.

После тестирования модели на изображении моей лужайки перед домом у меня получился вот такой результат. Я так долго не мог добиться, чтобы программа хотя бы доходила до конца без ошибок, что был в восторге даже от того, что она, наконец, обвела проплешину рамкой! То, что полученный результат был ужасен и абсолютно бесполезен для работы системы, я понял уже позднее. Модель, в принципе, способна обозначать область с плохой травой. Однако получившиеся границы очень неточны, и такой результат практически бесполезен.

Наборы данных 2–4 / Последующие тесты

После оценки полученных на первом наборе данных результатов стало очевидно, что для правильной разработки модели мне не хватает изображений. Я понял, что мне нужно гораздо больше данных, но загружать изображения вручную…. нет уж, увольте.

Полистав Интернет, я обнаружил такую вещь, как парсеры (web scrapers). Парсер — это инструмент, способный извлекать данные и содержимое с веб-сайтов и загружать эти файлы на локальный компьютер. Это было как раз то, что мне нужно, и после изучения краткого руководства я создал элементарный парсер, загружающий изображения, содержащие ключевые слова «трава с проплешинами», «плохая трава» и «плохой газон». С помощью этого парсера я собрал папку из 180 изображений, и это был мой второй набор данных.

После удаления всех непригодных изображений у меня получился третий набор данных из 160 изображений. После обучения модели на третьем наборе данных результаты всё равно оставались нестабильными и неточными. Как и в прошлый раз, я подумал, что главная проблема заключается в отсутствии достаточного количества изображений в наборе.

Я обратился кое к кому за помощью, поизучал ещё теорию и вычитал, что есть такой хитрый приём — аугментация изображений (image augmentation), то есть процесс, с помощью которого набор данных может быть расширен посредством внесения изменений в существующие изображения. Количество изображений меняется за счёт того, что меняются их ориентация и RGB-значения пикселей. Пример аугментации изображений.

Пример аугментации изображений.
Пример аугментации изображений.
Пример дополненных и реальных данных.
Пример дополненных и реальных данных.

Для нас, людей, все приведённые выше изображения одинаковы, если не считать крохотных изменений; однако для компьютера, который рассматривает изображения как массивы значений пикселей, эти изображения совершенно разные. Попробуем использовать эту идею и создадим больше обучающих данных. И вот, я, страдавший от нехватки изображений, сразу получил их много больше, чем значительно улучшил свой набор данных. Для пополнения всего каталога изображений я использовал библиотеку Keras с определёнными параметрами и граничными значениями. Мой четвёртый набор данных содержал 300 изображений. Теперь я был уверен, что модель, наконец, заработает. Но неожиданно возникла ещё одна серьёзная проблема.

Проблема совместимости библиотек

В большинстве проектов по программированию, особенно проектов в области анализа и обработки данных, для работы определённых функций и инструментов требуется ряд библиотек и зависимостей. В этом конкретном проекте библиотека ImageAI потребовала установки определённых версий различных библиотек, в том числе tensorflow-gpu 1.13 и keras 2.4.

Разные версии библиотеки отличаются одна от другой, причём использование разных версий может повлиять на взаимодействие между библиотеками. В моём случае это было особенно актуально, так как обучение и работа модели были возможны только при использовании определённых версий библиотек.

В январе вышло обновление библиотеки ImageAI, и оно сразу поставило крест на работе других библиотек, которые я использовал в проекте, — оно было просто несовместимо с ними. И вот, время обучения, обычно составлявшее около 5 минут на эпоху, стало составлять более 14 часов. Кроме того, модель постоянно перестраивалась под данные, а это свидетельствовало о том, что она была неспособна генерализовывать новые данные.

Сначала я подумал, что такое длительное время обучения обусловлено большим количеством изображений в наборе данных, но скоро стало очевидно, что проблема кроется не в этом и она более серьёзная. Я ещё раз обратился к учебникам, но ничего путного найти не смог. Если бы вы знали, сколько различных вариантов я перепробовал, чтобы устранить проблему!.. Я пробовал менять способы извлечения набора данных, менять аппаратный ускоритель, менять размер пакета… Ни один из этих вариантов не снизил время обучения модели.

Но тут я наткнулся на недавно опубликованный пост в разделе проблем и вопросов на Github, в котором кто-то жаловался на такую же точно  проблему, как и у меня. Олафенва Мозес, создатель библиотеки, ответил на это пост и объяснил проблему, предложив собственное решение. Суть этого решения была такой: три основные библиотеки — Tensorflow, Keras и ImageAI — должны иметь чётко определённые версии.

Окончательный набор данных / Модель

После избавления от предыдущей проблемы я сначала протестировал набор данных из 300 изображений. Результаты улучшились, но ненамного, им не хватало стабильности. На некоторых изображениях газона с разных углов моя модель вообще не смогла обнаружить проплешин.

Набор данных 4. Результаты.
Набор данных 4. Результаты.

Я решил добавить ещё больше данных и в итоге получил набор из 1738 изображений. Чтобы обучить модель, мне пришлось  аннотировать каждое изображение, вручную очерчивая участки на каждом из них. К счастью, этой работой я занимался не один, а с друзьями. Менее чем за два часа нам удалось аннотировать все изображения.

Окончательный набор данных был разделён на 1400 тренировочных и 338 тестовых изображений. После обучения модели за 5 эпох я провел валидацию и получил впечатляющий результат — 0,7204, что, безусловно, стало моим лучшим результатом с начала проекта.

Набор данных 5. Результаты.
Набор данных 5. Результаты.

Окончательный  результат работы модели меня, наконец, удовлетворил. После обучения модели я приступил к разработке прототипа системы, которая могла бы целенаправленно поливать участки газона.

Создание спринклера

Схема системы.
Схема системы.

Чтобы контролировать полив, мне нужно было обеспечить вращение спринклера по двум осям — так я мог бы контролировать расстояние и направление разбрызгивания воды. Я использовал два шаговых двигателя NEMA с разными характеристиками мощности и крутящего момента. Нижний двигатель NEMA-23 использовался для управления направлением разбрызгивания воды. Верхний двигатель NEMA 14 вращал стержень с закреплённым на нём с помощью трубки из ПВХ спринклером, чтобы можно было управлять расстоянием, на которое разбрызгивается вода. Для управления этими двигателями я использовал Arduino, два регулятора частоты вращения двигателя A4988 и два адаптера питания 12 В.

Если бы я мог выяснить, на какое расстояние разбрызгивается вода и на какой угол поворачивается спринклер за определённое количество шагов, я мог бы рассчитать коэффициенты преобразования шагов в углы и шагов — в расстояние. Для того чтобы можно было использовать такие коэффициенты преобразования, мне потребовался скрипт, определяющий фактическое расстояние до проплешины и угол, на который надо повернуть спринклер для полива.

Я рассчитал угол, на который необходимо повернуть спринклер от начального места до центра проплешины, определил приблизительное количество пикселей/футов на моём изображении и после этого вычислил приблизительное расстояние до центра проплешины.

Результат работы скрипта управления двигателем.
Результат работы скрипта управления двигателем.

На рисунке выше показаны результаты работы скрипта управления двигателем. Их них следует, что спринклер должен повернуться на 42°, а расстояние до проплешины составляет примерно 3 м 89 см.

Согласно скрипту угол до проплешины составляет 42°.
Согласно скрипту угол до проплешины составляет 42°.

Длина рулетки — 3 м (10 футов); от центра проплешины до спринклера — примерно 12 футов 9 дюймов (3,8862 м), как и предсказал скрипт.

Я выполнил несколько тестов для определения коэффициентов преобразования шагов в углы и шагов — в футы, и это позволило мне создать скрипт Arduino для ориентирования спринклера на проплешину с использованием данных скрипта управления двигателем.

Готовность к окончательному тестированию

К сожалению, всю систему в итоге мне протестировать не удалось.

Перед окончательным тестом я стал проверять готовую конструкцию, чтобы убедиться, что она способна держать спринклер и поворачивать его. Но я был очень неосторожен: в моторы попала вода, и они сгорели. Двигатели были довольно дорогими, а покупать новые было непрактично.

Анализ кода / Краткий обзор

Google Colab PatchDetector

PatchDetector на Github

!wget https://github.com/fazalmittu/PatchDetection/raw/master/BlackedOutLawn.jpg !wget https://github.com/fazalmittu/PatchDetection/raw/master/BlackedOutLawn_Detected.jpg  !wget https://github.com/fazalmittu/PatchDetection/releases/download/v3.0/detection_model-ex-04--loss-25.86.h5 !wget https://github.com/fazalmittu/PatchDetection/releases/download/v3.0/detection_config1700_v1.json  !wget https://github.com/fazalmittu/PatchDetection/raw/master/BlackedOutFullLawn.jpg !wget https://github.com/fazalmittu/PatchDetection/raw/master/BlackedOutFullLawn_Detected.jpg  !wget https://github.com/fazalmittu/PatchDetection/raw/master/SprinklerPOV.jpg !wget https://github.com/fazalmittu/PatchDetection/raw/master/SprinklerPOV_Detected.jpg  !wget https://github.com/OlafenwaMoses/ImageAI/releases/download/essential-v4/pretrained-yolov3.h5

Этот код используется для импорта модели и изображений (для тестирования), которые я хранил на Github, чтобы их можно было легко извлечь с помощью Google Colab. Последняя строка — импортирование предварительно обученной модели YOLO-v3, которая, в свою очередь, использовалась для обучения модели (трансферное обучение).

!pip uninstall -y tensorflow !pip install tensorflow-gpu==1.13.1 !pip install keras==2.2.4 !pip install imageai==2.1.0 !pip install numpy

Этот код импортирует определённые версии библиотек, необходимых при проектировании. Используемые библиотеки: tensorflow-gpu, keras, imageai и numpy.

%load_ext autoreload %autoreload 2    from google.colab import drive import sys from pathlib import Path drive.mount("/content/drive", force_remount=True) base = Path('/content/drive/MyDrive/PatchDetectorProject/') sys.path.append(str(base))  zip_path = base/'AugmentedDataSetFinal.zip' !cp "{zip_path}" . !unzip -q AugmentedDataSetFinal.zip !rm AugmentedDataSetFinal.zip

Этот код используется для получения набора данных из места, которое я определил для него на Google-диске. Для сохранения на Github набор данных был слишком велик, поэтому мне пришлось использовать альтернативный источник.

from imageai.Detection.Custom import DetectionModelTrainer from __future__ import print_function  trainer = DetectionModelTrainer() trainer.setModelTypeAsYOLOv3() trainer.setDataDirectory(data_directory="AugmentedDataSetFinal") trainer.setTrainConfig(object_names_array=["patch"], batch_size=4, num_experiments=5, train_from_pretrained_model="pretrained-yolov3.h5") trainer.trainModel()

В этом коде осуществляется обучение модели. В нём указывается объект для поиска («patch» (проплешина)), количество эпох (5), размер пакета (4) и используется трансферное обучение.

from imageai.Detection.Custom import DetectionModelTrainer  trainer = DetectionModelTrainer() trainer.setModelTypeAsYOLOv3() trainer.setDataDirectory(data_directory="AugmentedDataSetFinal") trainer.evaluateModel(model_path="AugmentedDataSetFinal/models", json_path="AugmentedDataSetFinal/json/detection_config.json", iou_threshold=0.5, object_threshold=0.3, nms_threshold=0.5)

Этот код используется для валидации модели. С окончательной моделью я получил оценку 72,04 %. Я считаю этот результат очень хорошим, учитывая, что обнаруживаемые мною объекты представляют собой проплешины без определённой формы, цвета или размера.

from imageai.Detection.Custom import CustomObjectDetection from PIL import Image, ImageDraw import numpy as np  detector = CustomObjectDetection() detector.setModelTypeAsYOLOv3() detector.setModelPath("/content/detection_model-ex-04--loss-25.86.h5") detector.setJsonPath("/content/detection_config1700_v1.json") detector.loadModel() detections = detector.detectObjectsFromImage(input_image="SprinklerPOV.jpg", output_image_path="SprinklerPOV_Detected.jpg", minimum_percentage_probability=30)   i = 0 coord_array = [] for detection in detections:     coord_array.append(detection["box_points"])     print(detection["name"], " : ", detection["percentage_probability"], " : ", detection["box_points"])     i+=1  print(coord_array)   detected = Image.open("SprinklerPOV_Detected.jpg") box = ImageDraw.Draw(detected)  for i in range(len(coord_array)):   box.rectangle(coord_array[i], width=10) detected

В этом коде я тестирую модель на новом изображении, чтобы проверить, сможет ли она найти проплешину. После этого, если проплешина будет найдена, модель сохраняет её координаты пикселей в массив, который будет использоваться скриптом управления двигателем.

!wget https://github.com/fazalmittu/PatchDetection/raw/master/FeetToPixel.JPG  img_ft = Image.open("FeetToPixel.JPG")  ft_line = ImageDraw.Draw(img_ft) ft_line.line([(175, 1351), (362, 1360)], fill=(0, 255, 0), width=10)  ft_distance = np.sqrt(9*9 + 187*187) print(ft_distance)  img_ft

С этого кода начинается скрипт управления двигателем. Код импортирует изображение, на нём — разложенная на траве рулетка. Я использовал это изображение для определения примерного количества пикселей в футе.

Пиксели/футы.
Пиксели/футы.
from PIL import Image, ImageDraw  #TOP LEFT = [0, 1] #BOTTOM LEFT = [0, 3] #TOP RIGHT = [2, 1] #BOTTOM RIGHT = [2, 3]  img = Image.open("SprinklerPOV_Detected.jpg") middle_line = ImageDraw.Draw(img) avg_1Line = ImageDraw.Draw(img) avg_2Line = ImageDraw.Draw(img)  avg_1 = (coord_array[1][1] + coord_array[1][3])/2 avg_2 = (coord_array[1][0] + coord_array[1][2])/2  middle_line.line([(2180, 0), (2180, 3024)], fill=(0, 255, 0), width=10) # avg_1Line.line([(coord_array[1][0], coord_array[1][1]), (coord_array[1][0], coord_array[1][3])], fill=(255, 0, 0), width=10) # avg_2Line.line([(coord_array[1][0], coord_array[1][3]), (coord_array[1][2], coord_array[1][3])], fill=(255, 0, 0), width=10)  def find_angle():   line_to_patch = ImageDraw.Draw(img)   line_to_patch.line([(avg_2, avg_1), (2180, 3024)], fill=(255, 0, 0), width=10)   length_1_vertical = 3024 - avg_1   length_2_horizontal = 2500 - avg_2   print("Distance = ", np.sqrt(length_1_vertical*length_1_vertical + length_2_horizontal*length_2_horizontal)/ft_distance, "ft")   angle_radians = np.arctan(length_2_horizontal/length_1_vertical)   angle = (180/(np.pi/angle_radians)) #Convert radians to degrees   return angle  print(avg_1, avg_2) print(find_angle())  img

Этот код используется для определения угла до проплешины. Я нарисовал треугольник от центра проплешины до места, где вначале находился спринклер. Для определения угла до центра проплешины я воспользовался тригонометрическими формулами и координатами каждой из точек. Для определения расстояния до центра проплешины в футах я также использовал тригонометрические функции и коэффициент пересчёта пикселей в футы.

/*  *   * Fazal Mittu; Sprinkler Control  *   */  const int ROTATEstepPin = 3;  const int ROTATEdirPin = 4;   const int ANGLEstepPin = 6; const int ANGLEdirPin = 7;  const int ROTATEangle = 42.25191181;//TODO: Find Conversion: Steps --> Angle 1000 steps = 90 degrees const int ANGLEangle = 12.76187539;// pixels --> ft: 187 pixels = 1 feet  bool TURN = true;  float angleToSteps(float angle){   float steps = 1000/(90/angle);   return steps; }  float ftToSteps(float feet) {   float steps = 100/(8/feet);   return steps; } void setup() {   Serial.begin(9600);   pinMode(ROTATEstepPin,OUTPUT);    pinMode(ROTATEdirPin,OUTPUT);   pinMode(ANGLEstepPin,OUTPUT);    pinMode(ANGLEdirPin,OUTPUT); }   void loop() {   int ROTATEsteps = angleToSteps(ROTATEangle); //Angle was determined using Python Script   int ANGLEsteps = angleToSteps(ANGLEangle);   delay(7000);   if (TURN == true) {     for(int x = 0; x < ROTATEsteps; x++) {       digitalWrite(ROTATEstepPin,HIGH);        delayMicroseconds(500);        digitalWrite(ROTATEstepPin,LOW);        delayMicroseconds(500);      }     delay(5000);      for (int x = 0; x < 100; x++) { //100 steps = 8 ft, 0 steps = 14.5 ft       digitalWrite(ANGLEstepPin,HIGH);        delayMicroseconds(500);        digitalWrite(ANGLEstepPin,LOW);        delayMicroseconds(500);     }   }   TURN = false; }

Приведённый выше код использовался для управления обоими двигателями. Перед использованием любого кода сначала нужно определить взаимозависимости шаги/градусы и шаги/футы, что я и сделал посредством проведения тестов и измерений. В итоге у меня появился рабочий скрипт, который мог управлять работой двигателей в соответствии со значениями, полученными в результате работы скрипта управления.

Заключение

Даже несмотря на печальную судьбу двух двигателей, работа над этим проектом доставила мне истинное удовольствие. Я узнал, как собирать данные, как увеличивать количество изображений, как строить модели. Я понял, как интерпретировать результаты, как создавать систему управления, как подключать механические части, а также научился разгребать подводные камни на пути к успеху.

А если вы хотите научиться работать с данными и обрабатывать их помощью машинного обучения — обратите внимание на наш курс по ML или на его расширенную версию Machine Learning и Deep Learning, партнером которого является компания Nvidia.

Узнайте, как прокачаться и в других специальностях или освоить их с нуля:

Другие профессии и курсы

ссылка на оригинал статьи https://habr.com/ru/company/skillfactory/blog/554442/

Мир изменился — CQRS и ES встречаются в PHP чаще, чем кажется

Генри Форд чуть не прогорел на своей классической фразе про пятьдесят оттенков черного. General Motors стала предлагать разноцветные модели Chevrolet, Pontiac, Buick, Oldsmobile и Cadillac — и не прогадала. Глядя на это, даже упрямый Форд изменил свое мышление  — и разработал новый Ford A, вернувший его на автомобильный Олимп. Бывают времена, когда парадигма мышления должна стать новой — ибо человек умирает тогда, когда перестаёт меняться ©Генри Форд. 

Пришло время и для разработчиков. Command Query Responsibility Segregation (CQRS) и Event Sourcing (ES) уже не миф — они реально работают. Конечно, не для всех задач — как и классический черный цвет Форда, PHP никуда не исчез и нужен по-прежнему. Но теперь уже есть задачи, где мы встречаемся с CQRS и ES чаще, чем нам кажется. Антон Шабовта на PHP Russia 2021 расскажет, как смена парадигмы и взгляд с другой стороны помогают разработчикам. А перед конференцией мы расспросили Антона подробнее о его новых взглядах на разработку, PHP и, конечно, о CQRS и ES.

— Антон, расскажи о себе и о своей работе. Чем ты занимаешься?

— Последние 12 лет я в коммерческой разработке и большая часть времени занимался проектами связанными с E-Commerce. Но 3 года назад мне захотелось применить свои знания в проектах другой сферы. Так я пришел в сервисную команду Onliner’а — это крупнейший белорусский медиа портал с огромным количеством сервисов. Нашу команду разработки можно условно разделить на две части. Команда каталога занимается основном продуктом — каталогом товаров.  В нем почти два миллиона позиций от тысяч магазинов — а это десятки миллионов товарных позиций. И этот действительно большой и сложный E-Commerce продукт, который  продолжает развиваться и расти.

Команда сервисов, в которой я и работаю, занимается остальными нашими продуктами. Это  сервисы аренды и продажи квартир, сервис поиска и предоставления услуг, авто- и мотоклассифайды и т.д. Есть еще огромный новостной портал с кучей инфраструктуры и сервисов вокруг него (комментарии, система личных сообщений, идентификация пользователей и пр.) Конечно, есть и сервисы, связанные с оплатой банковскими карточками и т.д. То есть это огромное скопление проектов в разных сферах и предметных областях. 

По сравнению с E-Commerce это совершенно другой мир и другие задачи. И мне было интересно понять, могу ли я применить знания из предыдущих проектов — подстроить, преобразить и переложить опыт из одной сферы на другую. Но и новому тоже хотелось учиться.

— Твой доклад на конференции будет про долгий путь к CQRS и Event Sourcing. Это связано с твоей карьерой разработчика?

— Да. Впервые я столкнулся с подходами Command Query Responsibility Segregation (CQRS) и Event Sourcing (ES) еще при работе с E-Commerce в 2015 году. И это стало важной вехой в моей карьере разработчика. Информации о CQRS и ES было много, но столько же возникало вопросов, мифов и недопонимания. Что именно представляют собой эти технологии? Как их использовать? Где стоит применять и какие проблемы они действительно призваны решать? Так вот одна из моих целей на PHP Russia 2021 — развенчать часть этих мифов и показать, что мы сталкиваемся с CQRS и ES намного чаще, чем кажется, даже если раньше мы никогда не слышали эти слова.

В 2017 году, проработав два года с CQRS и ES, я сделал доклад об этом  в рамках митапов Минской PHP User Group. Но, пересмотрев слайды, я понял, что в корне неверно подходил к объяснению этих технологий. За пять лет мое понимание значительно преобразилось,  и я надеюсь, что на этот раз смогу лучше объяснить. Так что во многом доклад для PHP Russia 2021 — это еще и работа над ошибками.

—  У тебя есть опыт с Erlang и Java (про С/С++, C# и Python знаем), или же ты целенаправленно изучаешь практики оттуда, чтобы рассмотреть их для PHP?

— По-разному, it depends. Исторически так сложилось, что многие книги по архитектуре программных систем используют примеры и понятия из Java-мира. И чтобы не упустить какие-то ключевые моменты и важные нюансы, пришлось разбираться в Java. Недавно стряхнул пыль с этих знаний, когда искал решения для своих проектов и разбирался с фреймворками Axon и Akka. В целом же, практики из одного языка, по крайней мере, из Java, очень легко и просто переносятся на PHP. 

С# я начал изучать, когда разбирался в устройстве фреймворка NServiceBus. В нем реализовано много классных решений, связанных с MBA (message-based architecture), SOA (service-oriented architecture) и сопутствующими технологиями.

Erlang — это вообще отдельная история. Интерес к нему пришел в процессе изучения классического понятия ООП (объектно-ориентированного программирования) от Алана Кея и модели экторов. Это реально классный язык, совершенно непохожий на другие. Не могу сказать, что готов сейчас писать на нем production ready код, но изучать его концепции, конечно, продолжу.

— Получается, что ты изучаешь, условно говоря, не какие-то языки, а перенимаешь практики из других языков, которые там успешны?

— Не всегда то, что успешно работает в одном языке, будет работать в другом. Но в процессе изучения я вижу, когда какие-то практики можно попробовать. 

— Помогает ли знание других языков лучше писать на PHP?

— И да, и нет. С одной стороны, многие практики и идеи можно (и нужно!) применять в PHP, особенно из близких по духу по подходам языков (Java, C#). ООП-модель PHP очень близка к этим языкам. К тому же мир разработки в PHP очень сильно изменился, например, после выхода фреймворка Symfony 2. Команда Symfony проделала колоссальную работу по прививанию паттернов проектирования в PHP community. Но большинство паттернов были придуманы не для PHP, а для других языков, в том числе, для Smalltalk и Java.

С другой стороны, из-за технических ограничений, некоторые интересные концепции невозможно развивать и применять в PHP. Например, многие подходы из мира функционального программирования и модели экторов, пропагандируемые Erlang’ом. Мы ограничены технологиями своего времени. Но, возможно, часть этих технологий в будущем можно будет применить и в PHP.

— Когда нужны подходы из других языков, а когда лучше по старинке или попроще?

— Это самый сложный вопрос, независимо от технологии, который только может себе задать разработчик. И простого ответа тут нет.

Я стараюсь для себя придерживаться KISS-принципа, то есть «Keep it simple, stupid»: если есть возможность делать что-то проще и не усложнять, то лучше так и сделать. Такие серьезные подходы как CQRS и ES несут много изменений не только в коде, а даже в самой модели мышления программиста. Мы ставим себя в определенные рамки, и за это придется платить. Не бывает серебряной пули в программировании.

Поэтому внедрять CQRS и ES не глядя, просто потому что можем — очень-очень плохая идея. Можно получить намного больше проблем, чем пользы. Конечно, когда-то это оправдано, но не всегда. Поэтому нужно хорошее изучение problems face, чтобы понимать, зачем мы внедряем эту технологию и какую проблему бизнеса пытаемся ею решить. 

— Что дают эти подходы разработчику, в чем помогают? 

CQRS и ES ориентированы на то, чтобы разработчик больше думал именно о поведении системы в первую очередь, а не о хранении. Это очень часто помогает найти существующие взаимодействия, которые не видны на уровне данных. Эти подходы проявляют эти взаимодействия и позволяют с ними явно работать, упрощая какие-то штуки. Но в то же время очень сложно ментально перестроиться и сменить парадигму мышления. 

— Поэтому нет популярных фреймворков для CQRS и ES? 

— Строго говоря, их не может быть. Говоря о фреймворках, мы подразумеваем, в первую очередь, инверсию управления. Когда мы работаем с фреймворком, не мы вызываем его код, а он вызывает наш. Это вопрос инфраструктуры.

С другой стороны, ES и CQRS неразрывно связанны именно с моделированием домена приложения, то есть это доменная модель. А хорошая доменная модель не должна зависеть от фреймворка. Но мы можем ее внедрить в любой фреймворк, с котором нам удобно будет работать.

Создатель этих подходов Грег Янг любит повторять в своих докладах, что для реализации ES и CQRS достаточно двух операций:

  1. Сравнение по образцам (pattern matching);

  2. Лево-ассоциативная свертка списка (left fold) — функция высшего порядка.

И многие языки поддерживают эти операции уже на уровне стандартной библиотеки. Например, тот же left fold в PHP существует как array_reduce, и дополнительно можно придумать другие варианты реализации.  

Pattern matching, к сожалению, полностью в PHP еще не реализован, хотя работа в этом направлении ведется. Но та малая часть из pattern matching, которая нужна для имплементации ES, легко эмулируется в user-land коде. 

Есть также много технологий, которые работают вокруг и рядом с CQRS и ES — те же message-based architecture и service-oriented architecture. Для этих технологий уже есть фреймворки, хотя достаточно популярных в PHP-мире пока не сформировалось. Какие-то работы сейчас ведутся и какие-то фреймворки вырастают. Но enterprise production ready, решений уровня того же NServiceBus в C# либо Axon в Java, пока в PHP не сложилось. Ждем!

— А есть ли учебник, где на пальцах правильно объясняются эти подходы?

— Изучать CQRS и ES стоит с просмотра докладов отца-основателя Грега Янга, с его публичных выступлений, статей, материалов и записей в блоге. Он подробно пишет, как он пришел к этим подходам, и из каких проблем они возникли. Для продолжения есть его книга «Versioning in an Event Sourced System» — там вы найдете для себя кое-какие нюансы.

Много материалов по ES и CQRS подходам можно найти в документации Microsoft. У них есть даже более развернутый вариант, который вышел в виде отдельной книги «Exploring CQRS and Event Sourcing». Предисловие к книге написал тот же Грег Янг. 

Еще этим технологиям много внимания уделяют те, кто пишут и работают с DDD-подходом (Domain-Driven Design), например, Vaugh Vernon. И у него есть книга «Implementing Domain-Driven Design», в которой большая глава посвящена именно ES и CQRS.

— Кому можно верить, не проверяя, в мире разработки и PHP: Фаулеру, Мартину, кому-то еще?

— Никому. Серьезно. Мартин Фаулер, Роберт Мартин, тот же Грег Янг, а также другие авторы тратят сотни часов времени, чтобы поделиться своими знаниями в статьях, в записях блогов, в докладах и в книгах. Иногда пишутся целые научные работы по каким-то подходам. Это действительно круто, что мы имеем доступ к этой информации.

Но часто разработчик, прочитав статью или увидев доклад о той или иной технологии, тут же бежит её внедрять на своем проекте, забывая о проблеме, которую она должна решать. DDD, CQRS, ES и все другие сложные подходы появились для решения конкретных проблем, с которыми столкнулись их создатели. Вот что должно быть первоочередным для хорошего разработчика.

Я считаю, что безоговорочное доверие авторитетам, этот «аристократичный» синдром, наравне с «культом карго» — это одна из ключевых проблем современного IT.

— То есть ты сам не придерживаешься этого всего?

— Я, естественно, изучаю работы всех именитых разработчиков и с интересом наблюдаю за развитием технологий. Про них надо знать и помнить, но нельзя их применять не глядя. Надо сначала столкнуться с проблемой. Понять, что одна из технологий, про которую ты читал, вспомнил, увидел, решает эту проблему. И только тогда думать, как ее внедрять, и действительно ли она решит эту проблему.

Очень часто наш мозг нас немножко обманывает. Он помнит про какое-то изящное и красивое решение, про какую-то очень крутую технологию, и пытается подогнать нашу проблему под нее. С этим, конечно, нужно бороться. И понимание того, когда нужна та или иная технология, приходит только с опытом, с годами работы и ошибок.

Мы, программисты, реализуем идеи, с которыми к нам приходит бизнес. У бизнеса есть какая-то проблема, мы придумываем решение. Разработчики должны исходить из проблем бизнеса, а не использовать технологию ради технологии, для красоты.

— Чего ты ждёшь от конференции в этом году?

Онлайн-формат — это, конечно, интересно и круто. Но пока я не могу сказать, что он может заменить оффлайн. Поэтому в первую очередь я жду, конечно, отличных докладов, много профессионального общения и интересных обсуждений в кулуарах. Я считаю, что эти обсуждения даже более ценны, чем доклады. Зажав спикера в кольцо, можно ему задать важные вопросы, которые не всегда есть время раскрыть в докладе. Очень часто какие-то действительно problem spaces остаются за рамками докладов. 

Еще я жду новостей! С такими переносами, я думаю, к моменту начала конференции у нас их будет немало. Хотелось бы знать:

  • Что нас ждет в PHP 9?

  • Какая будет следующая большая цель на этот релиз? Возможно, это будет асинхронный PHP — это важный лично для меня вопрос. На прошлом PHP Russia я читал доклад именно про асинхронный PHP.

  • Вопрос, волнующий всех: появятся ли у нас Generic-типы? Недавно добавили Union-типы. Скорее всего, скоро добавят пересечения, но Generic — это то, что возникает так или иначе в вопросах на каждой PHP-конференции.

И афтепати, конечно!

PHP Russia 2021 пройдёт в гибридном формате —будет и офлайн, и онлайн. Онлайн-зрители смогут задавать вопросы спикерам в зале, принимать участие в дискуссиях и участвовать в активностях на стендах партнёров.

Мы с нетерпением ждём нашу встречу в офлайне 28 июня 2021 года. Сегодня последний день до повышения цены — сейчас стоимость очного участия 27 000 рублей

Подписывайтесь на наши соцсети, чтобы быть в курсе новостей (FB,VK,Telegram-канал,Twitter), общайтесь с коллегами в чате.

ссылка на оригинал статьи https://habr.com/ru/company/oleg-bunin/blog/548500/

После года разработки вышел эмулятор QEMU 6.0

Прошел ровно год с момента выхода эмулятора QEMU 5.0, и сейчас разработчики представили новую версию. Проект дает возможность запустить программное обеспечение, подготовленное для одной архитектуры, на аппаратной платформе с другой архитектурой.

Пример — выполнение приложения для ARM на ПК с процессором x86. Благодаря особенностям эмулятора приложение в изолированном окружении выполняется почти с той же эффективностью, что и в нативном окружении. Достигается это, в частности, за счет прямого выполнения инструкций на процессоре, а также за счет применения гипервизора Xen или модуля KVM. Сейчас эмулятор поддерживает 14 аппаратных архитектур и может эмулировать около 400 разных устройств. За год разработчики внесли свыше 3 тысяч изменений от 268 разработчиков.

Подробнее о ключевых изменениях


Понятно, что объем статьи не позволит внести все 3 тысячи изменений, поэтому ограничимся ключевыми, наиболее важными:

  • Эмулятор контроллеров NVMe теперь приведен к полному соответствию со спецификацией NVMe 1.4. Также он получил экспериментальную поддержку нескольких новых фич, включая зонированные пространства имен, multipath I/O и сквозное шифрование данных на накопителе.
  • Кроме того, добавлены экспериментальные опции "-machine x-remote" и "-device x-pci-proxy-dev", которые нужны для выноса эмуляции устройств во внешние процессы. В текущем режиме эмулятор поддерживает пока лишь SCSI-адаптер lsi53c895.
  • Есть экспериментальная поддержка снапшотов содержимого ОЗУ.
  • Появился новый FUSE-модуль, который необходим для экспорта блочных устройств. Он дает возможность примонтировать срез состояния практически любого блочного устройства, которое используется в гостевой системе. Эксперт при этом реализуется благодаря QMP-команде block-export-add или через опцию "—export" в утилите qemu-storage-daemon.
  • Важное обновление получил эмулятор архитектуры ARM — так, добавлены архитектуры ARMv8.1-M ‘Helium’ и процессоров Cortex-M55, а также расширенных инструкций ARMv8.4 TTST, SEL2 и DIT. А еще появилась поддержка ARM-плат mps3-an524 и mps3-an547, плюс добавлена дополнительная эмуляция устройств для плат xlnx-zynqmp, xlnx-versal, sbsa-ref, npcm7xx.
  • Что касается режимов эмуляции на уровне системы для ARM, то здесь появилась поддержка расширения ARMv8.5 MTE (MemTag, Memory Tagging Extension). Оно позволяет привязать теги к каждой операции выделения памяти, организовав при доступе к ней проверку указателя. Последний должен быть связан с корректным тегом. Для чего потребовалось расширение? Оно дает возможность блокировать эксплуатацию уязвимостей, которые вызваны обращением к уже освобожденным блокам памяти, переполнениями буфера, обращениями до инициализации и использованием вне текущего контекста.
  • В эмуляторе для 68k разработчики добавили новый тип эмулируемых машин virt. Нововведение позволяет использовать для оптимизации производительности устройства virtio.
  • В архитектуре x86 появилась возможность применения технологии AMD SEV-ES (Secure Encrypted Virtualization) для шифрования регистров процессора, используемых в гостевой системе. В итоге содержимое регистров недоступно для хост-окружения в том случае, если гостевая система не предоставляет к ним явный доступ.
  • Для архитектуры MIPS также добавлен новый тип эмулируемых машин «virt» с поддержкой новых китайских процессоров Loongson-3.
  • Для PowerPC, точнее, для эмулируемых машин добавлена поддержка внешних BMC-контроллеров. Если случается сбой с pseries из-за попытки горячего извлечения памяти и CPU, то обеспечивается информирование о сбоях.
  • Появилась поддержка эмуляции процессоров Qualcomm Hexagon c DSP.
  • Реализована поддержка хост-окружений macOS на системах с новым ARM-чипом Apple M1 в классическом генераторе кода TCG (Tiny Code Generator).
  • При эмуляции архитектуры RISC-V для плат Microchip PolarFire реализована поддержка QSPI NOR flash.
  • В эмуляторе Tricore добавлена поддержка новой модели плат TriBoard, эмулирующей SoC Infineon TC27x.
  • В ACPI-эмуляторе теперь можно назначать сетевые адаптеры в гостевых системах имен, которые не зависят от порядка подключения к шине PCI.

С полным списком изменений и дополнений можно ознакомиться вот здесь.

ссылка на оригинал статьи https://habr.com/ru/company/selectel/blog/554354/

Поговори сам с собой: ученые научили роботов самоанализу и улучшили результаты их работы

Многие из нас говорят с сами с собой, только не вслух, конечно, а мысленно. Психологи говорят, что это вполне нормально и даже полезно. Причем не только для человека, но и для роботов. Так, итальянские ученые сознательно научили человекоподобных роботов думать вслух. Благодаря экспериментам они доказали, что внутренний монолог помогает разобраться в сложных и неопределенных ситуациях даже автоматическим системам. Центральной фигурой эксперимента стал японский робот-помощник Pepper, разработанный корпорацией SoftBank Robotics.

Основа исследования — работа ученого и антрополога Льва Выготского, который в свое время создал концепцию внутренней речи. Он, кстати, заметил, что маленькие дети в первые годы жизни часто озвучивают мысли тогда же, когда учатся говорить с другими. Уже позднее эта речь переходит во внутренний монолог. Так вот, если с человеком все более-менее ясно, то что с роботами? Пришло время это узнать.

Суть эксперимента


Эксперимент провели двое ученых из Университета Палермо. Они интегрировали в операционную систему робота модель внутренней речи на основе ACT-R. Это система управления роботом, включающая стандартные инструменты преобразования текста в речь и наоборот.

Цели эксперимента:

  1. Научить робота сопровождать действия голосом: комментировать все итерации в моменте.
  2. Провести оценку результатов и понять, как влияет проговаривание на итоги.

Перед Pepper поставили задачу — накрыть обеденный стол в соответствии с правилами этикета и указаниями, полученными от человека. Последние иногда противоречили правилам этикета, «изученным» роботом. Предполагалось, что в ходе взаимодействия у робота могут возникнуть различные оценочные суждения и всплывут вопросы нравственности (нет, ничего противозаконного роботу делать не предлагали).

В ходе эксперимента оценивали полученные результаты, когда робот использовал и не использовал внутреннюю речь.

Что произошло?


Роботу показали схему, отвечающую за нормы этикета.

Выглядела она так:

Человек и робот разместились за столом. Слушая указания и помня про схему, робот должен был выполнять требуемые действия. При этом начальные данные могли быть любыми: все предметы на столе, каких-то не хватает, есть лишние. Всего провели 60 итераций по 30 в каждом из двух блоков: с озвучкой внутреннего монолога и без. В 40 случаях из 60 содержались противоречие и/или конфликт.

С Pepper взаимодействовали по трем сценариям:

  1. Простое и понятное выполнение указаний без противоречий. Здесь все логично.
  2. Наличие противоречия между действиями и требованиями. В этом случае робот видел проблему: выполнить действие, несмотря на противоречие, или нет (нарушить правила или нет).
  3. Ложное требование: положить предмет, который уже есть. Робот сталкивался с дилеммой.

Все проведенные попытки оценили по нескольким показателям:

  • время принятия решения;
  • время выполнения задания;
  • количество удачных попыток;
  • прозрачность операций.

Последний пункт анализировал человек. Под прозрачностью понимали степень ясности изложения роботом мыслей относительно решения задачи. Попытку считали успешной, если она завершалась требуемым действием.

Итоги


Как и ожидалось, в простых и понятных случаях, внутренний монолог никак не влиял на действия. Размышления робота текли в самом логичном русле: он искал требуемый предмет, брал его, передавал и опережал действия словами.

Однако совсем другая картина складывалась в ситуациях, когда робот сталкивался с конфликтом требований. В этом случае робот видел несоответствие и задавал уточняющие вопросы человеку. Только потом выполнял действие. Однако если внутренняя речь была отключена, то успехом попытка так и не завершалась. Почему? Робот видел конфликт и отказывался выполнять действие.

Самое интересное происходило в третьем сценарии. Робот сразу идентифицировал требование как ложное и отмечал, что действие, например, уже выполнено (салфетка находится на столе или вилка уже лежит). Но это не все. Робот высказывал тревогу и пытался убедиться, точно ли его партнер это видит. Тогда человек говорил, что вообще имел в виду другой предмет (нож, допустим), робот соглашался и успешно завершал итерацию.

Вот результаты эксперимента, здесь два блока по 30 итераций.

Первый блок с включенным внутренним монологом:

26 — число успешных попыток;
28 — число прозрачных итераций.

Второй блок с выключенным внутренним монологом:

18 — число успешных попыток;
12 — число прозрачных взаимодействий.

То есть действия робота были успешнее в том случае, если он анализировал происходящее. Получается, что самоанализ и рефлексия способны помочь роботам повысить качество работы, выйти из неопределенных ситуаций и успешно решить задачу. Кроме того, использование внутренней речи помогает роботу выйти на диалог с человеком и найти новые способы решения поставленных им задач.

ссылка на оригинал статьи https://habr.com/ru/company/selectel/blog/554752/