-Поиск по дневнику

Поиск сообщений в rss_rss_hh_new

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 51

Habrahabr/New








Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://habrahabr.ru/rss/new/.
Данный дневник сформирован из открытого RSS-источника по адресу http://feeds.feedburner.com/xtmb/hh-new-full, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

О смарт-контрактах простыми словами

Пятница, 15 Сентября 2017 г. 11:55 + в цитатник
Ramon сегодня в 11:55 Разработка

О смарт-контрактах простыми словами

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

    Итак давайте попробуем сегодня разобраться, что такое смарт-контракты (умные контракты). Сначала мы достаточно общо обсудим сам концепт, а потом немного копнем в реализацию смарт-контрактов на примере блокчейна Ethereum.

    О концепте смарт-контрактов


    Термин «смарт-контракт» уже устоялся и по сути обозначает определенный код, который выполняется на какой-либо блокчейн-платформе таким образом, что его выполнение проверяется независимыми сторонами.

    Что это значит? Это распределенные вычисления? В привычном нам понимании все же нет.

    image

    Когда мы говорим о распределенных вычислениях, обычно подразумевается распределение нагрузки. Скажем, у нас есть задача посчитать в огромном текстовом файле вхождения определенного слова. Мы режем файл на несколько частей, раздаем эти части на разные ноды (например, используя Hadoop), каждая выполняет подсчет и выдает ответ. Мы суммируем ответы и получаем результат. Таким образом мы значительно ускоряем выполнение задачи.

    Если же говорить о смарт-контрактах, то тут совсем другая ситуация. Тут мы не режем файл на отдельные части, мы каждой ноде отдаем весь файл целиком, и каждая нода выдает нам один и тот же результат (в идеале). Вернемся к нашему вопросу: попадает ли такое действие под определение распределенных вычислений? Ну в целом почему нет? Они же распределены и они же вычисления? Только в данном случае мы говорим не о распределении нагрузки, а о распределении доверия.

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

    Классический пример подобного контракта, описанный еще в 1996 году Ником Сабо, — вендинг-машина. Она работает всегда автоматически по строгому набору правил: вы вносите деньги, делаете выбор — машина отдает товар. Внеся деньги, вы не можете передумать и попросить их вернуть. В случае с умным контрактом код становится своего рода законом, его нельзя оспорить, и он всегда будет выполняться при наступлении необходимых условий.

    Здесь необходимо сделать уточнение, что текущие реализации смарт-контрактов (далее мы будем говорить о сети Ethereum) все же по сути история, замкнутая в блокчейн-среде. Что это значит? Нельзя написать контракт, который будет получать данные извне (например, от поставщиков данных о погоде) и реализовывать логику на этих данных. Тут есть определенный подвижки, например Microsoft работает над концептом криплетов или существуют, так называемые, ораклы, но пока, думаю, там есть куда расти.

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

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

    Положим, у вас есть определенное сообщество, в котором необходимо принять какое-то решение. Допустим, это решение крайне важное, и сообщество не склонно просто так довериться отдельным своим членам. Возьмем как пример консорциум банков. Логично предположить, что ни один член консорциума не захочет делегировать проведение вычислений одному банку, особенно когда на основании этих вычислений будет приниматься наше «самое важное решение». Ведь, отдав и данные, и возможность проводить эти вычисления в одни руки, вы можете поставить свой бизнес в рискованное положение, и даже открытый код вычислений не убедит вас в правильности выполнения этого кода на чужом сервере. Вы захотите это выполнение проверить. И вот тут мы получаем ту самую пользу из концепта проверяемого исполнения: участники способны объединяться для выполнения общей задачи или принятия решения без центрального оператора и таким образом повышать эффективность своих бизнесов.

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

    Техническая сторона вопроса


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

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

    Сам код выполняется в так называемом Ethereum Virtual Machine (EVM). Надо обратить внимание, что код выполняется и проверяется всеми участниками системы, потому необходим некий механизм, который как-то ограничит потребление ресурсов каждым смарт-контрактом (иначе можно бесконечный цикл написать). Потому в Ethereum введена сущность gas (топливо). Контракт в Ethereum может выполнять любые инструкции, вызывать другие контракты, писать и читать данные и так далее. Все эти операции потребляют топливо, топливо оплачивается криптовалютой (Ether). Цена на топливо криптовалюты Ethеr формируется динамически рынком. Триггером выполнения контракта является транзакция. Стоимость топлива, которое сжигается в определенной транзакции, снимается с аккаунта, который транзакцию запустил. Кроме того, есть лимит потребления топлива, сделан он для того, чтобы защитить аккаунт от ошибок в написании контракта, которые могут привести к бесконтрольному сгоранию всей криптовалюты на данном аккаунте.

    Важно отметить, что среда смарт-контрактов все же сильно отличается от привычной нам среды выполнения кода. Ошибка может стоить очень дорого, сами операции дорогие и медленные. Затруднен механизм обновления смарт-контракта. Вы, по сути, пишете новый и должны убедить стороны использовать этот новый смарт-контракт. Нельзя сказать, что никак не перейти на новую версию своего контракта, но это часто новый общественный договор. Если вдуматься — разительное отличие, когда вы привыкли просто выкатывать апдейты вашей централизованной системы потребителям, не слишком интересуясь их мнением. Строя какую-то систему для работы в реальных жизненных сценариях на смарт-контрактах, стоит понимать эти ограничения.
    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/337984/


    Метки:  

    Пару слов о неминуемом повороте в развитии IT-отрасли

    Пятница, 15 Сентября 2017 г. 10:44 + в цитатник
    botyaslonim сегодня в 10:44 Управление

    Пару слов о неминуемом повороте в развитии IT-отрасли

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

      Мол, какой-то девайс, фреймворк или способ работы резко поднимает успешность предприятия. Например, «мы все используем MacBook, и у нас уже третий раунд инвестиций». Или «мы решили открыть travel-агентство, и нанимаем только тех программистов, которые не вылезают из путешествий; мы хотим, чтобы все сотрудники разделяли наши ценности, и у нас уже оборот 100 млн долларов». Или «как только мы внедрили React + Vue + Angular, наши дела пошли в гору, и нас купил Google». И так далее.

      На первый взгляд кажется абсурдом? — Да, но признаем: хайп и гвалт есть несомненные сопутствующие элементы современного IT-мира. Любое явление, находящееся на острие общественного внимания, а IT, безусловно, из таких, не может не впитать в себя характерные черты социума своего времени. В частности, тенденцию к превалированию формы над содержанием.

      image

      Частенько происходит типичная выдача желаемого за действительное. Рынок буквально сходит с ума, чтобы залить деньгами хоть кого-то, кто сможет выдать краткосрочный результат. Те, кому повезло с подливой от инвесторов, могут программировать хоть стоя на голове: для достижения быстрого результата, который нужно предъявить спекулятивному рынку, компаниям не обязательно, а иногда даже вредно выстраивать правильные, выверенные бизнес-процессы. Путь к первому успеху виден, а всерьёз займётся делом уже портфельный инвестор или крупный IT-гигант, который за миллиарды приобретёт выстреливший стартап. Пока все ждут роста акций и очередного рекорда в показателе «сумма, уплаченная за компанию / количество разработчиков», можно, не стесняясь, заявлять о любых своих капризах. Проблемы в человеческих капризах нет, но есть в том, что только ими теперь стараются обосновать успех всего предприятия.

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

      Любой, кто работает на работе хотя бы лет 10-15, наверное, вспомнит, как и он читал в своё время книжки про «100 секретов успеха», «200 причин бросить всё и сделать» и тому подобное. Единственный достоверный результат, к которому приводит следование этим остеровским советам, заключается в том, что вы болтаетесь ровно посередине. Нет, всегда есть пример васи, который выстрелил, но единичные выбросы статистики никогда не опровергали генеральную совокупность. Стало быть, теория не подтверждается практикой, и поэтому является не более чем спекуляцией.

      Парируя очевидные возражения, автор сего памфлета, безусловно, разделяет тот подход, что программист так или иначе учится на протяжении всей своей карьеры. Появляются новые языки, фреймворки, подходы к работе. Никто не желает верстать таблицами, как 15 лет назад, и SPA легче и эффективнее писать на специальных фреймворках, а не на старом родном jQuery. Развитие орудий труда неостановимо, как и человеческий прогресс в целом.

      Однако, суть нового орудия труда редко находится в прямой зависимости от маркетинговых факторов, которые способствуют его внедрению. Между «новый, стильный, прикольный» и «эффективный, разумный, достойный» нет прямой связи.

      Рискнём произнести весьма очевидные соображения насчёт секретов долговременного успеха в IT-отрасли. Рано или поздно, когда пузырь сдуется, и интерес мирового капитала переместится в новую отрасль (космос, биологию, медицину?), IT ждёт неминуемый консервативный поворот. Вдруг окажется, что любитель путешествий и кодинга из-под пальм элементарно работает 20 часов в неделю вместо 30-40. Вдруг окажется, что от программирования стоя через 10 лет разовьётся варикоз вен (спросите у любого парикмахера), а сидение на пуфиках, скрючившись над своим любимым макбуком, означает немалые затраты на невролога и мануального терапевта в будущем. Люди с удивлением обнаружат, что Agile не является панацеей от всех бед, и вообще должен применяться в весьма ограниченном круге задач, а новомодная геймификация прежде всего является способом саморазвлечения скучающих без реальной работы сотрудников кадровых отделов. Выяснится, что любимый лектор в очках в роговой оправе являлся обычным мошенником и смылся за границу с собранными через краудфандинг деньгами.

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

      Кто-то скажет, что станет скучнее. Возможно, кому-то новые времена покажутся пресными. Там, где качество кода компании не зависит от пятничной пиццы и настольного хоккея в офисе, ровно как и от командировок лучших сотрудников в Долину, прикольным весёлым ребятам делать особо нечего. Новыми героями статей вокруг IT-отрасли станут деловитые инженеры, копающие каждый свою тему, и добивающиеся пусть небольших, но фундаментальных улучшений для всех. Обществу станет всё-равно, добился тот или иной герой успеха в 19 лет или в 50. Станет неважным лейбл на корпусе ноутбука и умение держать себя на презентациях. Передовые разработчики перестанут называть друг друга «гуру», и станут просто инженерами.

      Крепкие IT-профессионалы, которые действительно имеют опыт решения самых разнообразных задач, возможно, как и работники других отраслей, станут задавать своим работодателям правильные вопросы: насчёт переработок, необходимой инсоляции и организации правильного питания в офисе. Возможно, ответом на вытеснение работников на надомную работу и прочие сокращения реальных благ, которые они получают, станет создание профсоюзов.

      Взрыв инноваций и нововведений диалектически превратится в свою противоположность, сняв (в гегелевском смысле) все те реальные противоречия, которые накопились в отрасли в момент бурного роста. Возможно, настанет время решить давно назревшие вопросы, ведь следующий виток развития IT-технологий уже по-настоящему затронет всех и каждого: интернет вещей или кибер-терроризм не оставят выбора в вопросе «сделать быстро в надежде на будущие доработки» или «сделать сразу хорошо».
      Original source: habrahabr.ru (comments, light).

      https://habrahabr.ru/post/337878/


      Метки:  

      Что общего у крупных успешных Open Source-проектов?

      Пятница, 15 Сентября 2017 г. 08:40 + в цитатник
      shurup сегодня в 08:40 Управление

      Что общего у крупных успешных Open Source-проектов?



        В организации The Linux Foundation задались вопросом, что объединяет проекты с открытым кодом, которым удалось собрать вокруг себя большое сообщество и добиться быстрых темпов разработки. Чтобы ответить на него, Дэн Кон (Dan Kohn), возглавляющий одно из многочисленных подразделений организации — CNCF (Cloud Native Computing Foundation), и его коллега-разработчик (Lukasz Gryglicki) создали визуализацию для 30 самых активно развивающихся Open Source-проектов, по статистическим данным с мая 2016 по апрель 2017 года. В качестве численных показателей, которые были учтены для выборки самих проектов и их визуализации, авторы использовали:

        1. количество коммитов (ось x на графике ниже);
        2. количество pull requests + issues (ось y);
        3. количество авторов, участвующих в разработке (величина цветного круга у названия проекта).



        (Картинка с кликабельными названиями проектов и подробностями по их численным показателям доступна на сайте Linux Foundation.)

        Лидер по двум показателям (количество авторов и PRs + issues) вряд ли кого удивил — это проект ядра Linux. Его ближайшие преследователи по количеству авторов — Homebrew и DefinitelyTyped. Лидер по числу коммитов, обошедший даже ядро Linux, — Chromium, а замыкает условный пьедестал по этому показателю Cloud Foundry, причём с большим отрывом от всех преследователей. И последний проект, попавший в топ-3 уже по другому показателю (числу PRs + issues), — это Kubernetes.

        Кстати: Исходный код инструментов, с помощью которых собиралась эта статистика, и документация по ним опубликованы на GitHub (язык Ruby, лицензия Apache License 2.0).

        Если проанализировать, кто стоит за всеми ведущими 30 проектами, то выяснится:

        • 9 проектов (включая ядро Linux, Kubernetes, Cloud Foundry и др.) — создаются независимой организацией/фондом (для перечисленных примеров — Linux Foundation, CNCF и Cloud Foundry соответственно), причём 3 из них приходятся на OpenStack (Nova, Neutron и Cinder);
        • 15 проектов (включая Chromium, React, Docker/Moby…) — создаются коммерческой компанией (Google, Facebook, Docker…);
        • 6 проектов (включая Homebrew, DefinitelyTyped, Vue.js…) — создаются сообществом без явных компаний/фондов.

        В Linux Foundation приводят слова своего исполнительного директора Джима Землина (Jim Zemlin), который считает, что управление успешным Open Source-проектом во многом зависит от качественного выполнения «функций уборщицы»: сортировки багов, ответов на вопросы новых пользователей и разработчиков, решения юридических вопросов и, конечно, урегулирования всевозможных трений, которые неизбежно возникают при любом масштабном сотрудничестве.

        Очевидно, фонды и крупные компании выделяют специальных людей и средства, чтобы наладить процессы решения обозначенных проблем. Можно даже сказать, что наличие подобной организации, стоящей за проектом, — это и есть то общее, что объединяет крупные и успешные Open Source-продукты. Статистика, полученная из топ-30, подтверждает это: у 80 % проектов есть свой «покровитель». (Компания-покровитель «превращается» в фонд в тот момент, когда другие значимые игроки рынка видят для себя перспективы коммерциализации кодовой базы и ищут пути реального влияния на ход развития проекта ­— через общий совет, членами которого и становятся заинтересованные стороны-компании.)

        Однако оставшиеся исключения — это 20 %, которые, пусть и являясь явным меньшинством, всё же доказывают, что успех проекта возможен усилиями сообщества и без явных спонсоров.

        P.S. Напоследок, к вопросу о компаниях и фондах — попробуйте угадать компанию, сотрудник которой является ведущим контрибьютором в кодовую базу Kubernetes.
        Итак, по данным Libraries.io, это…


        Если вы удивились слишком сильно, то успокою, что в действительности всё несколько сложнее. Автор (Brendan Burns) присоединился к команде Microsoft Azure лишь прошлым летом, а до этого годами работал над Kubernetes в Google.
        Original source: habrahabr.ru (comments, light).

        https://habrahabr.ru/post/337968/


        Метки:  

        Немного из истории криптографии СССP: M-105 под кодовым названием Агат

        Пятница, 15 Сентября 2017 г. 07:45 + в цитатник
        TashaFridrih сегодня в 07:45 Разработка

        Немного из истории криптографии СССP: M-105 под кодовым названием Агат

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


          Кабинет перлюстрации при почтовом отделении в Российской империи

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

          M-105: Под кодовым названием Агат


          M-105 (кодовое название: Aгат) — это русская, автономная шифровальная машина, которая была разработана и создана в СССР в конце 1960 годов. Предшественницей этой криптомашины была почти идентичная M-104 (Аметист и Аметист-2). Такие машины использовались всеми странами Варшавского договора (ГДР, Чехословакия, Венгрия, Румыния, Югославия), они представляли собой электромеханические шифраторы текстовой информации с записью на бумажную перфоленту: СМ-1 Василек, СМ-2, М-104 Аметист, М-105 Агат, М-125 Фиалка, М-130 Коралл.


          СМ-1 Василек


          М-104 Аметист


          М-105 Агат


          М-125 Фиалка


          М-130 Коралл

          M-105 Агат — криптомашина, в которой применялся OTT – One-Time-Tape шифрование, суть такого шифрования проста: применяемый ключ одноразовый и по длине равен передаваемым данным, текст зашифрован и без ключа его никто расшифровать не сможет.

          В отличие от Фиалки, в которой для генерирования ключа использовались 10 шифровальных колес (роторов), в M-105 встроен генератор механических ключей, который выводит случайные ключи на 11-уровневую перфоленту. Находится он в верхней части машины.



          На первый взгляд машина несколько напоминает M-125 Фиалку. Электрическая машина, почти таких же габаритов, окрашена в серебристый серый цвет с клавиатурой на латинице/кириллице. Но на этом сходство заканчивается.

          M-105 выводила результаты непосредственно на лист бумаги, который находился в каретке сзади. Усовершенствованная матричная печатающая головка позволяла напечатать любой из 30 символов (5 x 6). В зависимости от языка, который использовался для печати, некоторые символы или цифры могли отсутствовать.

          Сзади справа находилось устройство для вставки перфоленты и ввода ключа (стандартная 5-уровневая перфолента), правда код Бодо не применялся.
          Код Бодо — равномерный телеграфный 5-битный код, использующий два отличающихся друг от друга электрических сигнала.

          Вместо него использовалась та же схема кодирования, что и в Фиалке. Спереди M-105 находилось устройство считывания с бумажной перфоленты. Перфолента направлялась через линейку, которая проходила по всей ширине машины. Для запуска и остановки — две клавиши (Запуск, Стоп), расположенные спереди справа.



          На изображении ниже показано расположение полной клавиатуры: на каждой клавише — буква кириллицы и латиницы. 30 клавиш, черный одношаговый ключ внизу слева и черный управляющий символ возврата катерки CR/LF внизу справа, есть пробел (внизу).



          В режиме шифрования, при вводе текста использовался пробел, а клавиша Й2 блокировалась. В режиме расшифровки все наоборот: пробел заблокирован, клавиша Й2 — доступна. Когда аппарат использовался в режиме обычного текста (MODE установлен на «O»), можно было использовать как клавишу пробела, так и клавишу Й2. Две черные клавиши («шаг » и CR/LF) не зашифрованы. Они работали только в текстовом режиме для форматирования вывода. Недостающую «Й» спокойно можно заменить на «И». Идентично Фиалке, на клавиатуре М-105 присутствуют только 30 наиболее используемых букв.

          Знаков препинания — кроме символа SPACE с применением клавиши «Й» в верхнем левом углу — нет. Переключение между латиницей и кириллицей означало замену печатающей головки.

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



          Переключение режимов работы


          Спереди слева, сразу над клавиатурой находится черный поворотный регулятор, с его помощью можно выбрать необходимый режим работы:«O» для набора текста (Открытый текст), «3» для шифрования (зашифровать) и «P» для расшифровки (расшифровывать).



          В режиме текста M-105 функционировала, как обычная пишущая машинка или телепринтер и использовалась для печати текста, создания 5-уровневых перфолент (5 дыр на строку). Были доступны все клавиши, включая пробел, ШАГ каретки и CR/LF.

          При установке режимов шифрования (3) или расшифровки (P) происходил ряд механических изменений внутри устройства. Как и писалось ранее — в режиме шифрования клавиша Й2 заблокирована, доступен пробел, в режиме расшифровки — все наоборот.

          Аббревиатуры, используемые для разных режимов, идентичны для всех машин (M-125 или M-130), как показано ниже.





          На передней части 11-уровневого считывателя ключей — рычаг с тремя возможными настройками: П, ПК и К. Использовался он для выбора адресата (перфоратор, принтер, перфоратор и принтер) кодированного, декодированного или обычного текстового вывода.

          Блок питания




          Существовало несколько версий M-105, наиболее распространенная — устройство питалось от источника постоянного тока напряжением 24 В.



          Специально, для подключения к сети постоянного тока напряжением 110 В была доступна иная версия АГАТ.







          Стандартный блок питания, который использовался в M-105, подходил для сетей любого уровня напряжения (как правило, в диапазоне напряжений 110 – 220 В), мог использоваться практически в любой точке мира. Такой же блок питания применялся с M-125 Фиалка в большинстве стран Варшавского договора.



          Рычаг выполнял несколько функций. С его помощью можно было работать с машиной вручную в случае сбоя питания. Поскольку процесс шифрования носил чисто механический характер, машина могла считывать 5-уровневые перфоленты, ленты с ключами, печатать на бумаге и без электричества. Рычаг также использовался для «перезагрузки» механизма, если его заклинивало.


          Рычаг

          В M-105 использовалась матрица 5 x 6 (5 строк, 6 столбцов) для адресации 30 символов. Каждый 5-битный символ переводился в строку (6 бит) и столбец (5 бит), в итоге получалось 11 внутренних «бит», потому ключевая перфолента — 11-уровневая.



          11-битный код с ключевой перфоленты добавлялся к 11-битовому потоку данных, результат после преобразовывался обратно в 5-разрядный цифровой код (выводился на пятиуровневые перфокарты).



          В Восточной Германии (DDR) М-105 была введена в эксплуатацию в 1968 году и использовалась для связи с государствами-партнерами Варшавского договора, а также руководством ГДР для обмена сообщениями на самом высоком правительственном уровне.

          В 1986 году M-105 стала полностью электронной машиной M-205 D, но многие M-105 оставались в эксплуатации до немецкого воссоединения. М-105 была заменена на Т-353 (Dudek) в 1987 году для коммуникации ГДР с Венгрией.


          Т-353 (Dudek)

          Найти материалы о данной криптомашине на просторах рунета крайне тяжело, потому информация была взята вот здесь: Сrypto museum и bplaced.net. Скорее всего такое скудное публичное освещение достижений в области криптографии времен СССР обусловлено рядом причин: только частичное рассекречивание, недофинансирование и другие проблемы. Будем надеяться, что в скором времени отечественные научные достижения и выдающиеся криптографы страны выйдут из под грифа «совершенно секретно».
          На правах рекламы.Акция! Только сейчас получите до 4-х месяцев бесплатного пользования VPS (KVM) c выделенными накопителями в Нидерландах и США (конфигурации от VPS (KVM) — E5-2650v4 (6 Cores) / 10GB DDR4 / 240GB SSD или 4TB HDD / 1Gbps 10TB — $29 / месяц и выше, доступны варианты с RAID1 и RAID10), полноценным аналогом выделенных серверов, при заказе на срок 1-12 месяцев, условия акции здесь, cуществующие абоненты могут получить 2 месяца бонусом!

          Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?
          Original source: habrahabr.ru (comments, light).

          https://habrahabr.ru/post/335904/


          Народная Политика конфиденциальности

          Пятница, 15 Сентября 2017 г. 07:13 + в цитатник
          image

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

          Решились на такой шаг, потому что данная форма Политики не предусматривает обработку персональных данных, и в результате не предполагает большой вариативности решения. Важно помнить, что она не подходит для сайтов, на которых обрабатываются ПДн. Например, интернет-магазины и прочие сервисы, на которых помимо номера телефона или email пользователем дополнительно предоставляются иные сведения о себе, требуют большего внимания к вопросам обработки персональных данных.

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

          Смотрим, что получилось. Читать дальше ->

          https://habrahabr.ru/post/337970/


          Вторая встреча амазоновцев в Москве

          Пятница, 15 Сентября 2017 г. 02:45 + в цитатник
          Всем привет!

          Если вы интересуетесь Amazon Web Services, или кратко AWS, то приглашаем вас посетить вторую встречу AWS Usergroup Moscow.

          Что?
          Темы докладов, возможно, будут меняться: но предварительно такие:
          1) Программируем инфраструктуру через CloudFormation
          2) Lambda + ApiGateway = ServerLess в AWS
          3) Облачная автоматизация «из коробки”
          4) Что можно сделать на Free Tier

          Где?
          Встреча будет проходить в главном офисе компании Крок по адресу:
          Москва, ул. Волочаевская, д. 5, корп. 1

          Когда?
          28 сентября в 19.00

          На объекте действует пропускная система, поэтому не забудьте прислать номера автомобилей и Фамилию/Имя своих спутников (и свои, если они на этой платформе отличаются от того что в документах).

          Ссылка на встречу: www.meetup.com/awsmsk/events/242828973

          Ссылка на группу: www.meetup.com/AWSmsk

          https://habrahabr.ru/post/337966/


          Метки:  

          RPM-репозиторий — своими руками

          Пятница, 15 Сентября 2017 г. 01:19 + в цитатник
          tnt4brain сегодня в 01:19 Администрирование

          RPM-репозиторий — своими руками

            Итак, начнём.


            При внедрении DevOps-процесса в компании одним из возможных вариантов хранилища артефактов сборки может стать rpm-репозиторий. По существу — это просто веб-сервер, раздающий определённым образом организованное содержимое. Есть, конечно, коммерческие варианты maven-репозиториев, которые имеют плагины для поддержки rpm, но мы же не ищем лёгких путей?


            image


            Задача


            Написать сервис, который будет принимать готовые rpm-пакеты по протоколу HTTP, парсить их метаданные, раскладывать файлы пакетов по каталогам в соответствии с внутренней структурой репозитория и обновлять метаданные репозитория после обработки очередного пакета. Что из этого получилось — описано под катом.


            Анализ


            В моей голове задача почти мгновенно распалась на несколько частей: первая — принимающая, которая должна принять rpm-пакет по HTTP; вторая — обрабатывающая, которая должна принятый RPM-пакет обработать. Ну и где-то ещё должен быть веб-сервер, который будет раздавать содержимое репозитория.


            Принимающая часть


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


            часть конфигурации Nginx, которая принимает файлы
            location /upload {
                proxy_http_version 1.1;
                proxy_pass http://127.0.0.1:5000;
                proxy_pass_request_body off;
                proxy_set_header X-Package-Name $request_body_file;
                client_body_in_file_only on;
                client_body_temp_path /tmp/rpms;
                client_max_body_size 128m;
            }

            Результат данной конфигурации — при приёме файла Nginx сохранит его в заданный каталог и сообщит исходное имя в отдельном заголовке.
            Для полноты картины — вторая крохотная


            часть конфигурации, которая раздаёт содержимое репозитория
            location /repo {
                alias /srv/repo/storage/;
                autoindex on;
            }

            Итак, у нас есть первая часть, которая умеет принимать файлы и отдавать их.


            Обрабатывающая часть


            Обрабатывающая часть напиcана на Python без особых премудростей и выглядит


            вот так:
            #!/usr/bin/env python
            import argparse
            import collections
            import pprint
            import shutil
            import subprocess
            import threading
            import os
            import re
            import yaml
            from flask import Flask, request
            from pyrpm import rpmdefs
            from pyrpm.rpm import RPM
            
            # Сервис для поддержания репозиториев (С) Sergey Pechenko, 2017
            # Лицензия - GPL v2.0. Никаких дополнительных гарантий или прав не предоставляется. 
            # Для лицензирования использования кода в коммерческом продукте свяжитесь с автором.
            
            class LoggingMiddleware(object):
                # Вспомогательный класс для логирования запросов и отладки
                def __init__(self, app):
                    self._app = app
            
                def __call__(self, environ, resp):
                    errorlog = environ['wsgi.errors']
                    pprint.pprint(('REQUEST', environ), stream=errorlog)
            
                    def log_response(status, headers, *args):
                        pprint.pprint(('RESPONSE', status, headers), stream=errorlog)
                        return resp(status, headers, *args)
            
                    return self._app(environ, log_response)
            
            def parse_package_info(rpm):
                # Обработка метаданных пакета
                os_name_rel = rpm[rpmdefs.RPMTAG_RELEASE]
                os_data = re.search('^(\d+)\.(\w+)(\d+)$', os_name_rel)
                package = {
                    'filename': "%s-%s-%s.%s.rpm" % (rpm[rpmdefs.RPMTAG_NAME],
                                                     rpm[rpmdefs.RPMTAG_VERSION],
                                                     rpm[rpmdefs.RPMTAG_RELEASE],
                                                     rpm[rpmdefs.RPMTAG_ARCH]),
                    'os_abbr': os_data.group(2),
                    'os_release': os_data.group(3),
                    'os_arch': rpm[rpmdefs.RPMTAG_ARCH]
                }
                return package
            
            # Объект приложения и его настройки
            app = Flask(__name__)
            settings = {}
            
            # Тестовый обработчик - пригодится в начале настройки
            @app.route('/')
            def hello_world():
                return 'Hello from repo!'
            
            # Обработчик конкретного маршрута в URL
            @app.route('/upload', methods=['PUT'])
            def upload():
                # Ответ по умолчанию
                status = 503
                headers = []
                # Этот нестандартный заголовок мы добавили в конфигурацию Nginx ранее
                curr_package = request.headers.get('X-Package-Name')
                rpm = RPM(file(unicode(curr_package)))
                rpm_data = parse_package_info(rpm)
                try:
                    new_req_queue_element = '%s/%s' % (rpm_data['os_release'], rpm_data['os_arch'])
                    dest_dirname = '%s/%s/Packages' % (
                        app.settings['repo']['top_dir'],
                        new_req_queue_element)
                    # Перемещаем файл в нужный каталог
                    shutil.move(curr_package, dest_dirname)
                    src_filename = '%s/%s' % (dest_dirname, os.path.basename(curr_package))
                    dest_filename = '%s/%s' % (dest_dirname, rpm_data['filename'])
                    # Переименовываем файл
                    shutil.move(src_filename, dest_filename)
                    # Готовим ответ, который получит загружавший клиент
                    response = 'OK - Accessible as %s' % dest_filename
                    status = 200
                    if new_req_queue_element not in req_queue:
                        # Кладём запрос на обработку этого пакета в очередь
                        req_queue.append(new_req_queue_element)
                    event_timeout.set()
                    event_request.set()
                except BaseException as E:
                    response = E.message
                return response, status, headers
            
            def update_func(evt_upd, evt_exit):
                # Ждёт события, затем запускает обновление метаданных
                while not evt_exit.is_set():
                    if evt_upd.wait():
                        # Выбираем следующий доступный запрос из очереди
                        curr_elem = req_queue.popleft()
                        p = subprocess.Popen([app.settings['index_updater']['executable'],
                                              app.settings['index_updater']['cmdline'],
                                              '%s/%s' % (app.settings['repo']['top_dir'], curr_elem)],
                                             shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                        res_stdout, res_stderr = p.communicate(None)
                        pprint.pprint(res_stdout)
                        pprint.pprint(res_stderr)
                        # Сбрасываем событие обновления
                        evt_upd.clear()
                return
            
            def update_enable_func(evt_req, evt_tmout, evt_upd, evt_exit):
                while not evt_exit.is_set():
                    # Ожидаем запрос
                    evt_req.wait()
                    # OK, дождались
                    # Теперь выдерживаем 30 секунд, а если в это время пришёл запрос....
                    while evt_tmout.wait(30) and (not evt_exit.is_set()):
                        evt_tmout.clear()
                    if evt_exit.is_set():
                        break
                    evt_upd.set()
                    evt_tmout.clear()
                    evt_req.clear()
                return
            
            def parse_command_line():
                # Разбор агрументов командной строки
                parser = argparse.ArgumentParser(description='This is a repository update helper')
                parser.prog_name = 'repo_helper'
                parser.add_argument('-c', '--conf', action='store', default='%.yml' % prog_name, type='file', required='false',
                                    help='Name of the config file', dest='configfile')
                parser.epilog('This is an example of Nginx configuration:\
              location /repo {\
                  alias /srv/repo/storage/;\
                  autoindex on;\
              }\
            \
              location /upload {\
                  client_body_in_file_only on;\
                  client_body_temp_path /tmp/rpms;\
                  client_max_body_size 128m;\
                  proxy_http_version 1.1;\
                  proxy_pass http://localhost:5000;\
                  proxy_pass_request_body off;\
                  proxy_set_header X-Package-Name $request_body_file;\
              }\
            ')
                parser.parse_args()
                return parser
            
            def load_config(fn):
                with open(fn, 'r') as f:
                    config = yaml.safe_load(f)
                return config
            
            def load_hardcoded_defaults():
                # Прибитые гвоздями настройки "по умолчанию"
                config = {
                    'index_updater': {
                        'executable': '/bin/createrepo',
                        'cmdline': '--update'
                    },
                    'repo': {
                        'top_dir': '/srv/repo/storage'
                    },
                    'server': {
                        'address': '127.0.0.1',
                        'port': '5000',
                        'prefix_url': 'upload',
                        'upload_header': ''
                    },
                    'log': {
                        'name': 'syslog',
                        'level': 'INFO'
                    }
                }
                return config
            
            if __name__ == '__main__':
                try:
                    cli_args = parse_command_line()
                    settings = load_config(cli_args['configfile'])
                except BaseException as E:
                    settings = load_hardcoded_defaults()
                req_queue = collections.deque()
                # Application-level specific stuff
                # Exit flag
                exit_flag = False
                # Событие, сигналящее о пришедшем запросе
                event_request = threading.Event()
                # Событие, сигналящее об окончании задержки
                event_timeout = threading.Event()
                # Событие, сигналящее о запуске обновления метаданных
                event_update = threading.Event()
                # Событие, сигналящее о завершении вспомогательных потоков
                event_exit = threading.Event()
                # Готовим начальное состояние событий
                event_request.clear()
                event_timeout.clear()
                event_update.clear()
                # Поток, который запускает обновление метаданных репозитория
                update_thread = threading.Thread(name='update_worker', target=update_func, args=(event_update, event_exit))
                update_thread.start()
                # Поток, отсчитывающий время задержки, и начинающий отсчёт сначала, если задержка прервана
                # Если задержка прервана - начинаем отсчёт сначала
                delay_thread = threading.Thread(name='delay_worker', target=update_enable_func,
                                                args=(event_request, event_timeout, event_update, event_exit))
                delay_thread.start()
                # Его Величество Приложение
                app.wsgi_app = LoggingMiddleware(app.wsgi_app)
                app.run(host=settings['server']['address'], port=settings['server']['port'])
                # Это событие заставит оба дополнительных потока завершиться
                event_exit.clear()

            Важный и, скорее всего, непонятный с первого взгляда момент — зачем же здесь нужны потоки, события и очередь.
            Они нужны для передачи данных между асинхронными процессами. Вот смотрите, ведь HTTP-клиент не обязан ждать какого-то разрешения, чтобы загрузить пакет? Правильно, он может начать загрузку в любой момент. Соответственно, в основном потоке приложения мы должны сообщить клиенту об успешности/неуспешности загрузки, и, если загрузка удалась, передать данные через очередь другому потоку, который выполняет вычитывание метаданных пакета, а затем перемещение его в файловой системе. При этом отдельный поток следит, прошло ли 30 секунд с момента загрузки последнего пакета, или нет. Если прошло — метаданные репозитория будут обновлены. Если же время ещё не вышло, а уже пришёл следющий запрос — сбрасываем и перезапускаем таймер. Таким образом, всякая загрузка пакета будет отодвигать обновление метаданных на 30 секунд.


            Как пользоваться


            Сначала нужно


            установить пакеты Python по списку:

            appdirs==1.4.3
            click==6.7
            Flask==0.12.1
            itsdangerous==0.24
            Jinja2==2.9.6
            MarkupSafe==1.0
            packaging==16.8
            pyparsing==2.2.0
            pyrpm==0.3
            PyYAML==3.12
            six==1.10.0
            uWSGI==2.0.15
            Werkzeug==0.12.1


            К сожалению, я не могу гарантировать, что это минимально возможный список — команда pip freeze просто берёт список доступных пакетов Python и механически переносит его в файл, не рассматривая, используется ли конкретный пакет в конкретном проекте или нет.


            Затем нужно установить пакеты с nginx и c createrepo:


            yum install -y nginx createrepo

            Запуск проекта выглядит вот так:


            nohup python app.py

            После того, как всё будет запущено, можно пробовать загрузить rpm-пакет в репозиторий вот такой командой:


            curl http://hostname.example.com/upload -T 

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


            Для удобства желающих код выложен на GitHub. Предложения по дополнению сервиса, а ещё лучше — pull-request'ы горячо приветствуются!


            Надеюсь, этот прототип окажется кому-то полезным. Спасибо за внимание!


            P.S.

            Ну и для тех, кому очень нужно, небольшой сниппет для укрощения SELinux:


            #!/bin/bash
            semanage fcontext -a -t httpd_sys_rw_content_t "/srv/repo/storage(/.*)?"
            restorecon -R -v /srv/repo/storage
            setsebool -P httpd_can_network_connect 1
            Original source: habrahabr.ru (comments, light).

            https://habrahabr.ru/post/337736/


            Метки:  

            Куда податься вендору, когда Amazon не по зубам: придумываем торговую площадку для нишевых гаджетов

            Четверг, 14 Сентября 2017 г. 23:16 + в цитатник
            HamsterMrkt сегодня в 23:16 Управление

            Куда податься вендору, когда Amazon не по зубам: придумываем торговую площадку для нишевых гаджетов

              Крупные торговые интернет-площадки вполне заслуженно заняли свое место под солнцем, но работа с ними имеет несколько нюансов. Например, Amazon, исходя из своей маркетинговой стратегии, ориентирован, в первую очередь, на привлечение крупных продавцов и производителей. А нам, хомякам, что делать?


              Подпись же картинке не нужна, правда?

              Представим ситуацию: вы изобрели очередной электровеник, с которым ваша команда вышла на «Кикстартер» и успешно собрала нужную сумму для производства тысячи изделий. Часть вы распродали сразу же в рамках краудфандинговой кампании, а часть – «зависла» на руках. В этот момент вы столкнулись с главной проблемой большинства энтузиастов и небольших производителей: вы слишком озабочены идеей закончить разработку, переходом от прототипирования к изготовлению рабочих устройств, и не особо задумываетесь, как вы это будете продавать.

              Фактически, чуть ли не каждый второй стартап или небольшое предприятие попадает в порочный круг «прежде чем что-то продавать, нужно это изготовить». Это является классической болезнью любого малого бизнеса, что в конечном итоге приводит к банкротству и прекращению деятельности. Конечно, от подобных телодвижений может уберечь толковый директор по продажам, который подготовит все необходимые «аэродромы», на которые в итоге и «десантируется» ваш продукт, но чаще выходит совершенно иначе. Вложив немало времени, сил и иногда денег, выполнив обязательства перед инвесторами, вы остаетесь с партией никому не нужных устройств, в которых и лежит мертвым грузом прибыль всего предприятия. В подобной ситуации небольшая часть производителей запускает собственные ритейл-площадки на базе своего сайта, а все остальные — идут к Amazon или другим крупным игрокам.

              И тут начинается самое неприятное.

              Трудно быть маленьким


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

              Давайте поговорим об Amazon, как о более очевидном пути продажи наших электровеников. Система продаж на этой площадке базируется на нескольких ключевых аспектах. Первое – детальное описание продукции по достаточно жесткой и регламентированной форме. Второе – на позиции продукта влияет количество положительных отзывов о нем. Третье – рядовые пользователи и подписчики Prime получают разную выборку товаров (благодаря этой и другим маркетинговым уловкам, товарооборот на Amazon в денежном выражении в 2015 составил $107 млрд, а в 2016 году — $135,98 млрд).

              И если с первым требованием гиганта по ведению торговли можно справиться, банально подсмотрев у других продавцов, то второй и третий пункт создают ощутимые проблемы. Если вы занимаетесь малотиражным производством и ваш оборот составляет несколько тысяч устройств в год (в лучшем случае), то есть товар является нишевым — у вас серьёзные проблемы. На Amazon, как, впрочем, и на любых других подобных площадках, существует система рейтингов, основанная на количестве и качестве положительных отзывов от реальных пользователей. Минимально необходимое количество положительных рецензий о товаре в случае американской площадки – 25 штук. Без этого числа отзывов ваш товар не будет отображаться в поисковой выдаче, а продвигать его нужно будет средствами площадки в виде баннерной рекламы или привлекать трафик извне. Подход с размещением рекламы на Amazon или в Сети оправдан, если речь идет о каком-то серийном продукте, продавать который планируется длительное время и в больших объемах. Тогда можно устроить и рекламную кампанию, привлечь СМИ, разместить рекламу в Google.

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

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

              Проблема не в производителях, а в продавцах


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

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

              Мы столкнулись с описанной выше ситуацией, когда занялись поставками, а в дальнейшем и производством, детских планшетов PlayPad. Недоступность классических площадок и рынков сбыта для мелких производителей создает парадоксальную ситуацию: существует спрос на какой-то специализированный товар, существует и сам товар. Но производитель и покупатель просто не могут встретиться, потому что последний не знает о самом факте существования первого.

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

              Зачем мы придумали Hamster Marketplace




              У нас уже есть опыт, альтернативный крупным интернет-площадкам уровня Amazon. Речь идет о собственном сайте и выстраивании персонального канала продаж. Однако, с ростом производства и доли рынка мы пришли к классической схеме сотрудничества с крупным оффлайновым ритейлером в лице М-ВИДЕО.

              Этот опыт нельзя назвать однозначно травматичным, но стоит понимать, что в этом «танце» роль ведущего отводится исключительно торговой сети. Мы могли лишь соглашаться или не соглашаться на предлагаемые нам условия работы.

              Именно поэтому и родилась идея создания торговой площадки, которая была бы реальным посредником между производителем и покупателем, а не псевдо-площадкой, коей сейчас является Aliexpress, Amazon, E-Bay все прочие. Почему мы заговорили о псевдо-площадке? Скажем так, глупо отрицать, что все вышеописанные ресурсы и компании, стоящие за ними, в первую очередь преследуют собственные интересы по росту и извлечению прибыли. Иногда эти интересы совпадают с интересами продавцов и производителей, а иногда – нет. Именно эту диктатуру площадки для мы и намереваемся устранить.

              Что такое Hamster Marketplace? За основу мы взяли популярную нынче идею децентрализации и самоуправления сообществом через механизмы блокчейна. В большинстве аспектов площадка копирует устоявшиеся бизнес-процессы того же Amazon, за одним большим исключением: управлять ею будут не условный совет директоров Amazon или Джефф Безос, а сами продавцы и производители товаров. Таким образом мы хотим достичь самоуправления, когда решения, принимаемые площадкой, будут отражать потребности реального большинства продавцов, а не нескольких производителей-гигантов.

              Вот основополагающие принципы работы Hamster Marketplace:

              • Hamster Marketplace не ставит своей целью получение прибыли;
              • Hamster Marketplace управляется непосредственно участниками со статусом «Производитель» с помощью токенов маркетплейса HMST;
              • Развитие и функционирование площадки осуществляется исходя из бюджета, принимаемого блокчейн-голосованием владельцами токенов HMST со статусом «Производитель»;
              • Бюджетные траты площадки прозрачны и зафиксированы в блокчейне.

              Если мир созрел для коллективного финансирования мелких проектов, то, вероятно, пришло время и коллективно управляемой торговой площадки.

              Инди-электронщики и DIY-щики всех стран, соединяйтесь!


              Взглянув на наш сайт свежим взглядом, мы вдруг поняли, что он как-то совсем про деньги. Сборы — это, конечно, важно, но ещё нам очень нужна обратная связь сообщества. Нужна ли вам такая площадка? Как она должна быть устроена, на каких условиях. работать — делитесь мнениями, сомнениями и предложениями.
              Original source: habrahabr.ru (comments, light).

              https://habrahabr.ru/post/337962/


              Метки:  

              Математика для программиста

              Четверг, 14 Сентября 2017 г. 19:00 + в цитатник
              htmlacademy сегодня в 19:00 Разработка

              Математика для программиста


                Нужна ли математика программисту?

                Нужна. А, кроме неё, нужна сферическая геометрия, география, музыка и банковское дело. И я сейчас не шучу.


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


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


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


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


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


                Например, правильность номера банковской карты определяется по алгоритму Луна — это теория кодирования.


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


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


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


                .neo {
                  transform: matrix(0, -1, 1, 0, 50px, 50px);
                }

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


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


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


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


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



                const firstDiv = document.querySelector('div');
                firstDiv.id === 'underdog';

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


                const people = [
                  { name: 'Иван', height: 183 },
                  { name: 'Марья', height: 155 },
                ];

                Первое решение, которое может прийти в голову — это с помощью метода map собрать другой массив, массив ростов этих людей, а потом с помощью метода reduce посчитать их сумму и поделить на количество.


                const averageHeight = people
                  .map(it => it.height)
                  .reduce((acc, it) => acc + it) / people.length;

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


                const averageHeight = people
                  .reduce((acc, it) => acc + it.height) / people.length;

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


                Итого: учите всё подряд, что попадётся вам под руку. Для начала изучите дискретку, потому что она будет вашим основным инструментом в работе, а потом сосредоточьтесь на задачах вашего бизнеса и вы откроете для себя очень много нового в бизнесе, математике, строительстве и медицине.


                Видеоверсия





                Вопросы можно задавать здесь.

                Original source: habrahabr.ru (comments, light).

                https://habrahabr.ru/post/337952/


                Метки:  

                Обмен информацией о кибер-угрозах в реальном времени: новая платформа от ServiceNow

                Четверг, 14 Сентября 2017 г. 18:58 + в цитатник
                it-guild сегодня в 18:58 Разработка

                Обмен информацией о кибер-угрозах в реальном времени: новая платформа от ServiceNow

                  В этом году компания ServiceNow представила облачную платформу Trusted Security Circles. Она помогает бороться с кибер-угрозами за счет обмена информацией между компаниями и специалистами в области безопасности.

                  / Flickr / Wikimedia Commons / CC

                  Как работает Trusted Security Circles


                  Вместе с новым релизом Jakarta платформа ServiceNow предложила предприятиям возможность делиться и получать релевантную информацию об угрозах в режиме реального времени. Обычно в борьбе с кибер-атаками сотрудники безопасности отдельных компаний оставались один на один с угрозой, однако теперь они могут запрашивать данные у поставщиков и партнеров. С помощью Trusted Security Circles организации контролируют, как и с кем они делятся своими данными.

                  Информация о кибер-угрозах зачастую не распространяется дальше пострадавшей компании из-за возможных репутационных потерь. Не все предприятия готовы признавать уязвимости систем безопасности, поэтому Trusted Security Circles позволяет делиться сведениями анонимно. Как поясняет пользователь ServiceNow Сьюзан Смит (Suzanne Smith), в режиме конфиденциальности компании могут выбрать возможность получать информацию об угрозах от своих коллег в конкретной индустрии или на основе местоположения. Так формируются своеобразные «круги информированности».

                  Когда команда безопасности видит подозрительную активность в своей сети, она может сформировать запрос в пределах определенного сообщества. Если количество таких запросов превысит установленный порог, инцидент автоматически перенаправляется в ServiceNow Security Operations, — внутренний сервис реагирования на угрозы, — что может ускорить ответ.

                  Таким образом, новая технология позволяет организациям-пользователям ServiceNow оставаться в курсе предстоящих атак и вооружаться необходимой информацией, поступающей от коллег.

                  Вице-президент ServiceNow Шон Конвери (Sean Convery) в августе рассказал о том, что основным инструментом кибер-безопасности компании является единая платформа, которая подразумевает интеграцию со сторонними поставщиками сервисов безопасности. По слова Шона, у ServiceNow на данный момент есть 40 поставщиков, которые помимо всего прочего генерируют полезную информацию для пользователей. Она лежит в основе Trusted Security Circlюes.

                  / Flickr / frankieleon / CC

                  Решения по обмену информацией — устоявшийся тренд


                  Помимо ServiceNow те или иные решения в той же области предлагали ранее как частные компании, так и правительственные департаменты. Например, в 2015 году компания IBM объявила о запуске своей платформы IBM X-Force Exchange на базе IBM Cloud. Это решение обеспечивает доступ к массивам данных IBM и информации о сторонних угрозах. Система работает на основе определенных индикаторов кибер-атак в реальном времени.

                  По схожему принципу работает Центр обмена и анализа информации в финансовом секторе от NC4. Аналогичную инициативу собирается реализовать Национальный банк Республики Беларусь для борьбы с компьютерными атаками на основе обмена информацией об угрозах. В Канаде также действует своя некоммерческая организация по добровольному обмену информации. Власти США, Великобритании и Гонконга на законодательном уровне поощряют и призывают к автоматизации предоставления сведений об угрозах.

                  Как отмечал руководитель отдела IT-безопасности Cubic Corp. Адам Райс (Adam Rice), основным препятствием для обмена информацией является доверие между конкурентами и партнерами на рынке. По его мнению, процесс должен гарантировать достоверность предоставляемых сведений об угрозах, инциденты должны быть доступными для проверки, и принадлежность каждого члена сообщества по обмену информацией также должна быть установлена.

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

                  P.S. Дополнительное чтение по теме в нашем корпоративном блоге:

                  Original source: habrahabr.ru (comments, light).

                  https://habrahabr.ru/post/337826/


                  Метки:  

                  Анализируем требования рынка для data scientist

                  Четверг, 14 Сентября 2017 г. 18:21 + в цитатник
                  alexmikh сегодня в 18:21 Разработка

                  Анализируем требования рынка для data scientist

                    В интернете много информации, что data sciencist должен знать и уметь. Но я решил, что становиться data sciencist надо сразу, поэтому мы выясним требования к специалистам при помощи анализа текста вакансий.


                    В первую очередь сформулируем задачу и разработаем план:
                    Задача:
                    Посмотреть все вакансии на рынке и узнать общие требования, указанные в них.
                    План:
                    1. Собрать все вакансии по запросу Datа Scientist в удобном для обработки формате,
                    2. Выяснить часто встречамые в описание слова и словосочетания.

                    Для реализации понадобится немного знаний в SQL и Python.
                    Если их нет, то вам сюда
                    Для изучения SQL рекомендую sqlbolt.com, а для Python мобильное приложение SoloLearn(GooglePlay и AppStore).

                    Сбор данных


                    Источник: hh.ru
                    Сначала я подумал, что можно спарсить сайт. К счастью, я обнаружил, что у hh.ru есть API.

                    Для начало напишем функцию, которая получает список id вакансий для анализа. В параметрах функция получает текст поиска (сюда мы будем отправлять 'Datа Scientist') и зону поиска (согласно документации api), а возвращает список id. Для получения данных мы используем функцию api поиска вакансий:
                    Здесь код
                    def get_list_id_vacancies(area, text):
                    
                        url_list = 'https://api.hh.ru/vacancies'
                        list_id = []
                        params = {'text': text, 'area': area}
                        r = requests.get(url_list, params=params)
                        found = json.loads(r.text)['found']; #кол-во всего найденных вакансий
                    
                        if found <= 500: # API не отдает больше 500 вакансий за раз (на странице). Если найденно меньше 500 то получим все  сразу. 
                            params['per_page'] = found
                            r = requests.get(url_list, params=params)
                            data = json.loads(r.text)['items']
                            for vac in data:
                                list_id.append(vac['id'])
                        else:
                            i = 0;
                            while i <= 3: # если больше 500 то "перелистываем" страницы с 0 по 3 и получаем все вакансии поочереди. API не отдаст вам больше 2000 вакансий, поэтому тут захардкожено 3.  
                                params['per_page'] = 500
                                params['page'] = i
                                r = requests.get(url_list, params=params)
                                if 200 != r.status_code:
                                    break
                                data = json.loads(r.text)['items']
                                for vac in data:
                                    list_id.append(vac['id'])
                                i += 1
                    
                        return list_id
                    


                    Для отладки я отправлял запосы напрямую в API. Рекомендую для этого использовать приложение chrome Postman.

                    После этого надо получить подробную информацию о каждой вакансии:
                    Здесь код
                    def get_vacancy(id):
                    
                        url_vac = 'https://api.hh.ru/vacancies/%s'
                        r = requests.get(url_vac % id)
                    
                        return json.loads(r.text)



                    Теперь у нас есть список вакансий и функция, которая получает подробную информацию о каждой вакансии. Надо принять решение куда записать полученные данные. У меня было два варианта: сохранить все в файл csv или создать базу данных. Так как мне проще писать запросы SQL, чем анализировать в Excel я выбрал базу данных. Предварительно нужно создать базу данных и таблицы в которые мы будем делать записи. Для этого анализируем, что отвечает API и принимаем решения, какие поля нам нужны.
                    Вставляем в Postman ссылку api, например api.hh.ru/vacancies/22285538, делаем GET запрос и получаем ответ:
                    Полный JSON
                    {
                        "alternate_url": "https://hh.ru/vacancy/22285538",
                        "code": null,
                        "premium": false,
                        "description": "

                    Мы занимаемся....", "schedule": { "id": "fullDay", "name": "Полный день" }, "suitable_resumes_url": null, "site": { "id": "hh", "name": "hh.ru" }, "billing_type": { "id": "standard_plus", "name": "Стандарт+" }, "published_at": "2017-09-05T11:43:08+0300", "test": null, "accept_handicapped": true, "experience": { "id": "noExperience", "name": "Нет опыта" }, "address": { "building": "36с7", "city": "Москва", "description": null, "metro": { "line_name": "Калининская", "station_id": "8.470", "line_id": "8", "lat": 55.736478, "station_name": "Парк Победы", "lng": 37.514401 }, "metro_stations": [ { "line_name": "Калининская", "station_id": "8.470", "line_id": "8", "lat": 55.736478, "station_name": "Парк Победы", "lng": 37.514401 } ], "raw": null, "street": "Кутузовский проспект", "lat": 55.739068, "lng": 37.525432 }, "key_skills": [ { "name": "Математическое моделирование" }, { "name": "Анализ рисков" } ], "allow_messages": true, "employment": { "id": "full", "name": "Полная занятость" }, "id": "22285538", "response_url": null, "salary": { "to": 90000, "gross": false, "from": 50000, "currency": "RUR" }, "archived": false, "name": "Математик/ Data scientist", "contacts": null, "employer": { "logo_urls": { "90": "https://hhcdn.ru/employer-logo/1680554.png", "240": "https://hhcdn.ru/employer-logo/1680555.png", "original": "https://hhcdn.ru/employer-logo-original/309546.png" }, "vacancies_url": "https://api.hh.ru/vacancies?employer_id=1475513", "name": "Аналитическое агентство Скориста", "url": "https://api.hh.ru/employers/1475513", "alternate_url": "https://hh.ru/employer/1475513", "id": "1475513", "trusted": true }, "created_at": "2017-09-05T11:43:08+0300", "area": { "url": "https://api.hh.ru/areas/1", "id": "1", "name": "Москва" }, "relations": [], "accept_kids": false, "response_letter_required": false, "apply_alternate_url": "https://hh.ru/applicant/vacancy_response?vacancyId=22285538", "quick_responses_allowed": false, "negotiations_url": null, "department": null, "branded_description": null, "hidden": false, "type": { "id": "open", "name": "Открытая" }, "specializations": [ { "profarea_id": "14", "profarea_name": "Наука, образование", "id": "14.91", "name": "Информатика, Информационные системы" }, { "profarea_id": "14", "profarea_name": "Наука, образование", "id": "14.141", "name": "Математика" }] }



                    Все, что не планируем анализировать удаляем из JSON.
                    JSON только с нужным
                    {
                        "description": "

                    Мы занимаемся....", "schedule": { "id": "fullDay", "name": "Полный день" }, "accept_handicapped": true, "experience": { "id": "noExperience", "name": "Нет опыта" }, "key_skills": [ { "name": "Математическое моделирование" }, { "name": "Анализ рисков" } ], "employment": { "id": "full", "name": "Полная занятость" }, "id": "22285538", "salary": { "to": 90000, "gross": false, "from": 50000, "currency": "RUR" }, "name": "Математик/ Data scientist", "employer": { "name": "Аналитическое агентство Скориста", }, "area": { "name": "Москва" }, "specializations": [ { "profarea_id": "14", "profarea_name": "Наука, образование", "id": "14.91", "name": "Информатика, Информационные системы" }, { "profarea_id": "14", "profarea_name": "Наука, образование", "id": "14.141", "name": "Математика" }] }



                    На основе этого JSON делаем БД. Это несложно, поэтому я это опущу :)

                    Реализуем модуль взаимодействия с базой данных. Я использовал MySQL:
                    Здесь код
                    
                    def get_salary(vac): #зарплата не всегда заполена. Поэтому при обращение внутрь будет ошибка, для этого пишем отдельную функцию, которая вернет словарь с None, если данные пустые. 
                    
                        if vac['salary'] is None:
                            return {'currency':None , 'from':None,'to':None,'gross':None}
                        else:
                            return {'currency':vac['salary']['currency'],
                                    'from':vac['salary']['from'],
                                    'to':vac['salary']['to'],
                                    'gross':vac['salary']['gross']}
                    
                    def get_connection():
                        conn = pymysql.connect(host='localhost', port=3306, user='root', password='-', db='hh', charset="utf8")
                        return conn
                    
                    def close_connection(conn):
                        conn.commit()
                        conn.close()
                    
                    def insert_vac(conn, vac, text):
                        a = conn.cursor()
                    
                        salary = get_salary(vac)
                    
                        print(vac['id'])
                        
                        a.execute("INSERT INTO vacancies (id, name_v, description, code_hh, accept_handicapped,  \
                                     area_v,  employer, employment, experience, salary_currency, salary_from, salary_gross,  \
                                     salary_to, schedule_d, text_search)  \
                                     VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
                                     (vac['id'], vac['name'], vac['description'],
                                     vac['code'], vac['accept_handicapped'], vac['area']['name'],
                                     vac['employer']['name'],
                                     vac['employment']['name'], vac['experience']['name'], salary['currency'],
                                     salary['from'], salary['gross'],
                                     salary['to'], vac['schedule']['name'], text))
                    
                        for key_skill in vac['key_skills']:
                            a.execute("INSERT INTO key_skills(vacancy_id, name) VALUES(%s, %s)",(vac['id'], key_skill['name']))
                    
                        for spec in vac['specializations']:
                            a.execute("INSERT INTO specializations(vacancy_id, name, profarea_name) VALUES(%s, %s, %s)",
                                      (vac['id'], spec['name'], spec['profarea_name']))
                    
                        a.close()
                    


                    Теперь собираем все вместе, добавив в файл метод main()
                    Сбор данных
                    text_search = 'data scientist'
                    
                    list_id_vacs = get_list_id_vacancies(text_search)
                    vacs = []
                    
                    for vac_id in list_id_vacs:
                        vacs.append(get_vacancy(vac_id))
                    
                    conn = get_connection()
                    
                    for vac in vacs:
                        insert_vac(conn, vac, text_search)
                    
                    close_connection(conn)
                    


                    Меняя переменные text_search и area мы получаем разные вакансии из разных регионов.
                    На этом data mining закончен и переходим к интересному.

                    Анализ текста


                    Основным вдохновителем стала статья о поиске популряных фраз в сериале How I met your mother

                    Для начала будем получать описание всех вакансий из базы:
                    Здесь код
                    
                    def get_vac_descriptions(conn, text_search):
                    
                        a = conn.cursor()
                        a.execute("SELECT description FROM vacancies WHERE text_search = %s", text_search)
                        descriptions = a.fetchall()
                        a.close
                    
                        return descriptions
                    


                    Для работы с текстом мы будем использовать пакет nltk. По аналогии с расположенной выше статьей пишем функцию получения популярных фраз из текста:
                    Здесь код
                    def get_popular_phrase(text, len, count_phrases):
                        phrase_counter = Counter()
                        words = nltk.word_tokenize(text.lower())
                    
                        for phrase in nltk.ngrams(words, len):
                            if all(word not in string.punctuation for word in phrase):
                                phrase_counter[phrase] += 1
                    
                        return phrase_counter.most_common(count_phrases)
                    
                        descriptions = get_vac_descriptions(get_connection(), 'data scientist')
                    
                        text = ''
                    
                        for description in descriptions:
                                text = text + description[0]
                    
                        result = get_popular_phrase(text, 1, 20)
                        for r in result:
                            print(" ".join(r[0]) + " - " + str(r[1]))
                    
                    


                    Объединяем все описанные выше методы в методе main и запускаем его:
                    Здесь код
                    
                    def main():
                        descriprions = get_vac_descriptions(get_connection(), 'data scientist')
                    
                        text = ''
                    
                        for descriprion in descriprions:
                                text = text + descriprion[0]
                    
                        result = get_popular_phrase(text, 4, 20, stopwords)
                        for r in result:
                            print(" ".join(r[0]) + " - " + str(r[1]))
                    
                    
                    main()
                    


                    Выполняем и видим:
                    li — 2459
                    /li — 2459
                    и — 1297
                    p — 1225
                    /p — 1224
                    в — 874
                    strong — 639
                    /strong — 620
                    and — 486
                    ul — 457
                    /ul — 457
                    с — 415
                    на — 341
                    данных — 329
                    data — 313
                    the — 308
                    опыт — 275
                    of — 269
                    для — 254
                    работы — 233

                    Видим, что в результат попало очень много слов, которые характерны для всех вакансий и теги, которые используются в описание. Уберем эти слова из анализа. Для этого нам нужен список стоп слов. Сформируем его автоматически, проанализровав вакансии из другой сферы. Я выбрал «повар», «уборщица» и «слесарь».

                    Вернемся к началу и получим вакансии по этим запросам. После этого добавим функцию получения стоп слов.
                    Здесь код
                    def get_stopwords():
                        descriptions = get_vac_descriptions(get_connection(), 'повар') \
                                       + get_vac_descriptions(get_connection(), 'уборщица') + \
                                       get_vac_descriptions(get_connection(), 'слесарь')
                    
                        text = ''
                    
                        for description in descriptions:
                                text = text + descriprion[0]
                    
                        stopwords = []
                    
                        list = get_popular_phrase(text, 1, None, 200) #размер списка стоп слов
                        for i in list:
                            stopwords.append(i[0][0])
                    
                        return stopwords



                    Так же видим английские the и of. Поступим проще и уберем вакансии на английском.
                    Внесем изменения в main():
                    Заголовок спойлера
                    for description in descriptions:
                        if detect(description[0]) != 'en':
                        text = text + description[0]
                    


                    Теперь результа выглядит так:
                    данных — 329
                    data — 180
                    анализа — 157
                    обучения — 134
                    машинного — 129
                    моделей — 128
                    области — 101
                    алгоритмов — 87
                    python — 86
                    задач — 82
                    задачи — 82
                    разработка — 77
                    анализ — 73
                    построение — 68
                    методов — 66
                    будет — 65
                    статистики — 56
                    высшее — 55
                    знания — 53
                    learning — 52

                    Ну это одно слово, оно не всегда отражает истину. Посмотрим что покажут словосочетания из 2 слов:
                    машинного обучения — 119
                    анализа данных — 56
                    machine learning — 44
                    data science — 38
                    data scientist — 38
                    big data — 34
                    математических моделей — 34
                    data mining — 28
                    алгоритмов машинного — 27
                    математической статистики — 23
                    будет плюсом — 21
                    статистического анализа — 20
                    обработки данных — 18
                    английский язык — 17
                    анализ данных — 17
                    том числе — 17
                    а также — 17
                    методов машинного — 16
                    области анализа — 15
                    теории вероятности — 14

                    Результаты анализа.


                    Более явно выдает результат запрос по двум словам, нам надо знать:

                    • Машинное обучение
                    • Математические модели
                    • Data mining
                    • Python
                    • Математическую статистику
                    • Английский язык
                    • Теория вероятности

                    Ничего нового, но было весело :)

                    Выводы.


                    Это далеко от идеального решения.
                    Ошибки:
                    1. Не надо исключать вакансии на английском, надо их перевести.
                    2. Не все стоп слова исключены.
                    3. Нужно привести все слова к базовой форме (машинного -> машинное, анализа -> анализ и т.п).
                    4. Придумать метод по которому вычислить более оптимальный список стоп слов. Ответить на вопрос «почему 200?», «почему уборщица?».
                    5. Надо придумать как анализировать результат автоматически, понимать, что одно или два слова несут смысл или больше.
                    Original source: habrahabr.ru (comments, light).

                    https://habrahabr.ru/post/337124/


                    Метки:  

                    Использование различных метрик для кластеризации ключевых запросов

                    Четверг, 14 Сентября 2017 г. 17:30 + в цитатник

                    Метки:  

                    Как соответствовать требованиям к системе менеджмента качества по ISO 9001:2015

                    Четверг, 14 Сентября 2017 г. 17:01 + в цитатник
                    Cloud4Y сегодня в 17:01 Управление

                    Как соответствовать требованиям к системе менеджмента качества по ISO 9001:2015



                      15 сентября 2015 года был официально опубликован стандарт ISO 9001:2015. Почти сразу же стала доступна сертификация систем менеджмента качества на соответствие этой версии стандарта. ISO 9001:2008 будет действовать до сентября 2018 года, а это значит, что для организаций, которые хотят сохранить сертификацию систем менеджмента качества по стандарту ISO 9001, но ещё не перешли на неё, остался только один год для модернизации существующей системы. Но давайте начнём по порядку, а в качестве простого примера иногда будем размышлять о процессе транспортировки воды по трубе, чтобы тема статьи была понятна даже далёкому от менеджмента читателю.



                      Что такое ISO 9001?


                      Этот стандарт является одним из трех основополагающих стандартов, разработанных техническим комитетом Международной Организации по Стандартизации ISO/TS 176.

                      Кратко о стандартах
                      ISO 9000 Системы менеджмента качества. Основные положения и словарь создает основы для надлежащего понимания и внедрения ISO 9001. Принципы менеджмента качества, подробное описание которых дается в ISO 9000, были учтены в процессе разработки стандарта ISO 9001. Сами эти принципы не являются требованиями, но они формируют основу для требований. ISO 9000 также определяет термины, определения и основные понятия, используемые в настоящем стандарте.

                      ISO 9001 (сабж) устанавливает требования, направленные главным образом на создание доверия к продукции и услугам, предлагаемым организацией, и, посредством этого, на повышение удовлетворенности потребителей. Можно также ожидать, что надлежащее внедрение этого стандарта принесет другие выгоды для организации, такие как улучшенный внутренний обмен информацией, лучшее понимание и управление процессами организации.

                      ISO 9004 Менеджмент для достижения устойчивого успеха организации. Подход на основе менеджмента качества содержит руководящие указания для организаций, стремящихся превзойти требования стандарта ISO 9001, охватывая более широкий спектр вопросов стем, чтобы это могло вести к улучшению общих результатов деятельности организации. ISO 9004 включает методическое руководство по самооценке с тем, чтобы организации имели возможность оценивать уровень зрелости своих систем менеджмента качества.

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

                      Процессный подход


                      Стандарт направлен на применение «процессного подхода». Понимание и менеджмент взаимосвязанных процессов как системы способствует результативности и эффективности организации в достижении намеченных результатов.

                      Процесс — совокупность взаимосвязанных или взаимодействующих видов деятельности, которая использует входы для производства запланированных результатов (выходов, продуктов или услуг). Входы в процесс обычно являются выходами других процессов, а выходы процессов, как правило, являются входами других процессов. Процессы в организации обычно планируются и выполняются в контролируемых условиях для добавления ценности. Этим устанавливается один из общих и основных терминов в теории менеджмента качества. Любой бизнес будет рассматриваться совокупность взаимосвязанных или взаимодействующих процессов для достижения целей.

                      Рисунок 1 дает схематичное изображение любого процесса и иллюстрирует взаимосвязь элементов процесса. Контрольные точки мониторинга и измерения, необходимые для управления, являются специфическими для каждого процесса и будут варьироваться в зависимости от соответствующих рисков.



                      В примере с трубой: входом в процесс будет вода в точке А, соответствующая определённым требованиям; выходом из процесса будет вода в точке Б. Этот процесс мы отделяем от другого, так как за него есть ответственный сотрудник. За участок трубы от точки А до Б отвечает слесарь-сантехник Иванов. Источником входов в процесс будет вода из участка трубы, за который отвечает другой сотрудник. Получателем выходов будет житель квартиры, то есть конечный потребитель.

                      Применение процессного подхода в системе менеджмента качества позволяет:

                      1. понимать и постоянно выполнять требования;
                      2. рассматривать процессы с точки зрения добавления ими ценности;
                      3. достигать результативного функционирования процессов;
                      4. улучшать процессы на основе оценивания данных и информации.

                      Если процессный подход внедрен, то минимально

                      • процессы должны быть идентифицированы (у организации есть перечень процессов)
                      • определены связи между процессами (кто и для какого процесса внутри организации является поставщиком или клиентом)
                      • установлены показатели результативности для каждого процесса (процессные индикаторы)

                      Не всякая организация, внедрившая процессный подход, соответствует ISO 9001, но в каждой соответствующей этот подход внедрён. Для соответствия стандарту ISO 9001-2015 организация должна определять процессы, а также:

                      (первые три пункта повторяют названные выше, но в иных формулировках)

                      1. определять требуемые входы и ожидаемые выходы этих процессов;
                      2. определять последовательность и взаимодействие этих процессов;
                      3. определять и применять критерии и методы (включая мониторинг, измерения и соответствующие показатели результатов деятельности), необходимые для обеспечения результативного функционирования этих процессов и управления ими;
                      4. определять ресурсы, необходимые для этих процессов, и обеспечить их доступность;
                      5. распределять обязанности, ответственность и полномочия в отношении этих процессов;
                      6. учитывать риски и возможности;
                      7. оценивать процессы и вносить любые изменения, необходимые для обеспечения того, что процессы достигают намеченных результатов;
                      8. улучшать процессы и систему менеджмента качества.

                      Требование учёта рисков и возможностей в таком виде сформулировано впервые именно в стандарте 2015 года. В стандарте 2008 года говорилось о предупреждающих действиях.

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


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

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

                      Новая концепция риск ориентированного мышления, по мнению автора статьи, призывает менеджмент рассматривать будущее как совокупность сценариев развития, каждый из которых в будущем может существовать, но с разными вероятностями. Зачастую люди проявляют необоснованную надежду на то, что реализуется именно нужное им событие. Это противоречит теории вероятности, по которой из закона больших чисел следует, что эмпирическое среднее (среднее арифметическое) достаточно большой конечной выборки из фиксированного распределения близко к теоретическому среднему (математическому ожиданию) этого распределения. Если процесс в вашем бизнесе повторяется достаточное количество раз, принося по рублю, и существует вероятность 2%, что процесс приведёт к убытку в 100 рублей, сказанное выше означает, что после 1000 повторений, вы получите убыток в (1000*1)-(1000*100*2%)=-1000 рублей. Если это основной процесс, создающий добавленную стоимость, то такой бизнес лучше не начинать. Качественное управление рисками приведёт к тому, что вероятность благоприятного сценария возрастёт, а вероятность нежелательных сценариев уменьшится до незначительной. Правильная работа системы менеджмента качества приводит к тому, что организация может получать прибыль, а её клиенты удовлетворять свои потребности.

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

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

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

                      Качество = Ценность товара или услуги / Стоимость товара или услуги

                      Для того чтобы удовлетворять потребности человека, товар дол­жен иметь определенные свойства, а степень соответствия между свойствами товара и удовлетворяемыми с его помощью потребностя­ми определяет качество товара. В настоящее время мерой качества товара служит степень удовлетворенности потребителя, определяемая соотношением стоимости и ценности (потребительной стоимости) товара или услуги.

                      Для потребителя ожидаемая стоимость — это стоимость ценного (правильно сделанного с точки зрения потребителя), бездефектного товара. Люди будут пользоваться продуктом производителя, если они удовлетворены его ценностью Ц (необходимостью его приобретения и совокупностью предлагаемых параметров качества) и стоимостью С. Компании, которые не удовлетворяют потребностей потребителей либо по Ц, либо по С, вскоре обнаруживают, что клиенты ушли от них, и они потеряли свою область рынка из-за более профессиональ­ных конкурентов, которые лучше поняли потребности клиентов. Чем выше уровень удовлетворенности потребителя, тем выше возможно­сти развития бизнеса.

                      Исходя из этого подхода, следует рассмотреть три ситуации.

                      1. Ц = С. Это нейтральная ситуация. Ожидания потребителя подтвердились, а производитель окупил свои затраты и получил за­планированную прибыль, как он предполагал, в соответствии с реа­лизованными параметрами качества. Это имеет место только тогда, когда значения Ц и С, установленные производителем, совпадут с ожидаемыми значениями потребителя.

                      2. Ц > С. Потребитель удовлетворен. В то же время производи­тель заинтересован в получении большей прибыли за счет увеличе­ния стоимости продаж своей продукции, и в этом случае его больше устраивало бы соотношение Ц < С. Конкуренция с другими произво­дителями уравнивает интересы потребителя Ц > С и интересы произ­водителя Ц < С.

                      3. Ц < С. Потребитель не удовлетворен, и в большинстве случа­ев покупка товара может не совершиться. Производитель начинает терять приобретенных потребителей. Вот почему бизнес с таким со­отношением Ц и С всегда считался плохим бизнесом.

                      Высшее руководство должно демонстрировать лидерство и приверженность в отношении ориентации на потребителей посредством обеспечения того, что:

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

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

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



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

                      За что не любят СМК?


                      Организация должна в необходимом объеме:

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

                      Документированная информация это новый термин 2015 года, раньше в стандарте 2008 года говорилось о «документации, руководстве по качеству, документированной процедуре, записях». Документированная информация, требуемая системой менеджмента качества и стандартом ISO, должна находиться под управлением в целях обеспечения:

                      1. ее доступности и пригодности, где и когда она необходима;
                      2. ее достаточной защиты (например, от несоблюдения конфиденциальности, от ненадлежащего использования или потери целостности).

                      Зачем? Слесарь-сантехник Иванов, не сообщив никому уехал в неизвестном направлении, под его ответственность с течением времени перешёл водопровод значительной протяжённости. Только он один знал подробности инфраструктуры и произошедшая авария может быть устранена только с пониманием особенностей строения системы водоснабжения. Новым специалистам нужно время, потребители страдают без воды и требуют отдать управление водопроводом конкурентам.



                      Попав в такую ситуацию, у менеджмента появляется более ясное понимание этого требования стандарта. К этой же проблематике относится и требование к компетентности:

                      Организация должна:

                      1. определять необходимую компетентность лиц(а), выполняющих(его) работу под ее управлением, которая оказывает влияние на результаты деятельности и результативность системы менеджмента качества;
                      2. обеспечивать компетентность этих лиц на основе соответствующего образования, подготовки и(или) опыта;
                      3. там, где это применимо, предпринимать действия, направленные на получение требуемой компетентности, и оценивать результативность предпринятых действий;
                      4. регистрировать и сохранять соответствующую документированную информацию как свидетельство компетентности.

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

                      А зачем сертификация?


                      Максимально эффективно удовлетворять потребности клиентов можно и без сертификации.
                      Получать более выгодные условия кредитования, выполнять условия тендеров и конкурсов, повышать лояльность к компании со стороны органов власти и партнеров? Возможно поможет.

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

                      Cloud4Y не реже одного раза в год проходит аудит и оценку для подтверждения действия сертификата соответствия системы менеджмента качества стандарту ГОСТ Р ИСО 9001-2015. Приведённые в статье примеры не относятся к нашей основной деятельности. Как облачный провайдер вместо водопровода у нас оптическое кольцо высокой доступности с дублированными каналами связи, а вместо воды обрабатываемые на нашей IT-инфраструктуре данные клиентов. Требования стабильности выходов из процессов особенно актуально по причинам юридических гарантий уровня качества предоставления услуг (SLA 99,95%). Многие клиенты могут почувствовать себя «как рыба без воды» в случае, если произойдёт сбой в работе облачного сервера или удалённого рабочего стола.

                      Думается стоит закончить с аналогиями и отметить, что эта статья не описывает все требования стандарта. Каждая новая версия ISO 9000 содержит изменения, как нам кажется, к лучшему. Так в версии 2015, говорится о потребности учитывать внешний и внутренний контекст, среду в которой находится организация. В перспективе это может привести к тому, что получить сертификат соответствия сможет только организация, которая разработала «документированную информацию», оценила риски и возможности именно в соответствии со своей спецификой/контекстом.
                      Original source: habrahabr.ru (comments, light).

                      https://habrahabr.ru/post/337666/


                      Вводим рейтинг участника Dribbble и Behance на «Моём круге»

                      Четверг, 14 Сентября 2017 г. 16:27 + в цитатник
                      moikrug сегодня в 16:27 Управление

                      Вводим рейтинг участника Dribbble и Behance на «Моём круге»

                        В июле мы на «Моём круге» ввели рейтинги участников «Хабра» и «Тостера», GitHub и StackOverflow. А сегодня рады сообщить о добавлении рейтингов участия ещё в двух сообществах: Dribbble и Behance.

                        На профиле пользователя это выглядит следующим образом:

                        image

                        На списках специалистов — на поиске кандидатов или в откликах на вакансию — пользователь с рейтингом участника Dribbble или Behance отмечается соответствующей иконкой.

                        Теперь раскрывать свой профиль во всей красе для потенциального работодателя смогут не только разработчики, но также и дизайнеры. Это важно, ведь дизайнеры составляют десятую часть нашего ИТ-сообщества, объединённого «Хабром». Кроме того, недавно проведённый нами опрос показал, что Dribbble и Behance важны для карьеры дизайнеров. Участие в этих сообществах нередко оказывает решающую роль в принятии решения о приглашении дизайнера на работу.

                        Чтобы вывести свои рейтинги этих сообществ, нужно привязать их учетные записи к своему профилю на «Моём круге». Делается это в кабинете своего профиля, в «Ключнице».

                        Далее расскажем, какие данные мы выводим из Dribbble и Behance и что они означают.

                        • Итак, блок участника Dribbble или Behance появляется на профиле пользователя «Моего круга», если у него есть хотя бы один шот или проект соответственно.
                        • Из блока участника можно перейти в профиль пользователя в данном сообществе и посмотреть подробней, какие именно работы и по каким направлениям он выкладывает.
                        • В блоке мы показываем, сколько всего работ выложено у дизайнера в сообществе и сколько суммарно они набрали лайков. Далее показываем 10 тем, по которым у него набрано больше всего лайков: впереди идут темы с наибольшим числом лайков. В блоке Dribbble каждую тему можно тыкнуть и перейти на страницу всех работ дизайнера по данной теме. В блоке Behance такого, к сожалению нет, их сервис не умеет так делать.
                        • Наконец, мы показываем до 5 работ пользователя, набравших в соответствующем сообществе больше всего лайков. Каждую работу можно тыкнуть и просмотреть в увеличенном размере.



                        Напоминалочка


                        Посмотреть всех пользователей, по которым в базе «Моего круга» есть информация об их участии в ИТ-сообществах, можно на поиске по специалистам, выбрав среди фильтров соответствующий пункт «Участник ИТ-сообществ».

                        Блоки участника ИТ-сообществ подключаются и отключаются в кабинете своего профиля на «Моём круге», в разделе «Ключница».
                        Original source: habrahabr.ru (comments, light).

                        https://habrahabr.ru/post/337950/


                        Обзор одной российской RTOS, часть 4. Полезная теория

                        Четверг, 14 Сентября 2017 г. 16:14 + в цитатник
                        EasyLy сегодня в 16:14 Разработка

                        Обзор одной российской RTOS, часть 4. Полезная теория

                          Здравствуйте, коллеги! Готова очередная публикация из неформальной «Книги знаний» ОСРВ МАКС.

                          Просьба к постоянным читателям отнестись ко мне лояльно и не минусить за небольшое повторение части материала из предыдущей статьи (про защиту стека) — здесь оно оказалось логичней. А там я уже удалил.

                          Общее содержание (опубликованные и пока неопубликованные статьи):

                          Часть 1. Общие сведения
                          Часть 2. Ядро ОСРВ МАКС
                          Часть 3. Структура простейшей программы
                          Часть 4. Полезная теория (настоящая статья)
                          Часть 5. Первое приложение
                          Часть 5. Средства синхронизации потоков
                          Часть 6. Средства обмена данными между задачами
                          Часть 7. Работа с прерываниями

                          Некоторые неочевидные сведения о данных


                          Несколько фактов о куче


                          Многие программисты почему-то считают, что операции new и delete достаточно легковесны и просты. Поэтому код часто изобилует выделением и освобождением динамической памяти. Это более-менее приемлемо на мощных системах (гигабайты ОЗУ и гигагерцы тактовой частоты), но при ограниченных ресурсах может создавать некоторые проблемы, особенно для программ, работающих в режиме 24/7.

                          • Самая очевидная проблема — фрагментация адресного пространства. В современной среде .NET массивы выделяются на куче по ссылке. Поэтому в любой момент времени, система может остановить работу программы и заняться сборкой мусора. При этом массивы вполне могут быть сдвинуты внутри памяти, ведь обращение к ним будет идти по ссылке, а таблица ссылок будет скорректирована. Язык С++, на котором чаще всего пишут для микроконтроллеров (как, собственно, и чистый Си, да и ассемблер) работает с массивами через указатели. Сколько указателей имеется в памяти — никто не знает (программа пользователя имеет право их копировать, передавать в качестве аргументов, даже складывать и вычитать). Значит данные двигать нельзя. Где массив или структура были выделены, там они и будут закреплены до самого удаления. Ну, и дальше возникает классический случай, когда в результате выделений и освобождений куча примет, скажем, такой вид:

                            Иллюстрация классического случая проблем, возникающих из-за фрагментации адресного пространства

                            Рис. 1. Иллюстрация классического случая проблем, возникающих из-за фрагментации адресного пространства

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

                          Из всего этого следует, что выделять память на куче следует с крайней осторожностью. В идеале, это следует делать на этапе инициализации программы. Если же требуется выделять память по ходу работы, то лучше это делать как можно реже. Не стоит увлекаться постоянным выделением и освобождением. Также стоит опасаться операций, которые выделяют память неявно, внутри себя. Автора коробит от кода подобного вида, особенно если учесть, что он исполняется в системе, где на всё про всё выделено 50 килобайт ОЗУ:

                              String output;
                              if (cnt > 0)
                                output = ',';
                          
                              output += "{\"type\":\"";
                              output += (entry.isDirectory()) ? "dir" : "file";
                              output += "\",\"name\":\"";
                              output += entry.name();
                              output += "\"";
                              output += "}";
                          


                          С точки зрения автора, гораздо спокойней, если код имеет подобный вид (хоть это и чуть менее красиво, зато — не теребит функции выделения и освобождения памяти):

                          char xml [768];
                          ...
                                xml[0] = 0;
                                if (cnt > 0)
                                {
                                  strcat (xml,",");
                                }
                            
                                strcat (xml,"{\"type\":\"");
                                if (entry.isSubDir())
                                {
                                  strcat (xml,"dir");
                                } else
                                {
                                  strcat (xml,"file");
                                }
                                strcat (xml,"\",\"name\":\"");
                                entry.getName(xml+strlen(xml),255);
                                strcat (xml,"\"}");
                          


                          Красоту этому коду придаст разработка класса StaticString, аналогичного по функциональности классу String, но хранящему саму строку не в динамической, а в статической памяти. Однако, это выходит за рамки данного документа, а суть доработки ясна и так:

                          Если можно отказаться от постоянного обращения к new/delete, то лучше это сделать.

                          Кратко про стековые переменные


                          Автору часто приходилось встречаться с программистами, которые не знают, как именно реализуются локальные переменные в языках Си и С++. При этом, те программисты прекрасно осведомлены, что такое стек, а также — о том, как в него сохраняется содержимое регистров (которые будут испорчены) и адреса возврата из подпрограмм (правда, в архитектуре ARM адрес возврата попадает в регистр LR). Возможно, это связано с тем, что все эти программисты закончили один и тот же ВУЗ (чего уж греха таить, сам автор закончил его же, и ещё лет 10 назад тоже до конца не представлял себе, что такое стековый кадр). Тем не менее, будет полезным кратко обрисовать, как же эти загадочные локальные переменные хранятся. В конце раздела, будет раскрыта интрига, каким образом это относится к ОСРВ МАКС.

                          Итак. Оказывается, стек используется не только для хранения адресов возврата (правда, не у ARM) и временного сохранения содержимого регистров процессора. Стек используется также для хранения локальных переменных.

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

                          ;;;723 static void _CopyRect(int LayerIndex, int x0, int y0, int x1, int y1, int xSize, int ySize) {
                          000000 e92d4ff0 PUSH {r4-r11,lr}
                          000004 b087 SUB sp,sp,#0x1c


                          Первая инструкция PUSH — с нею всё ясно. Она как раз сохраняет регистры в стеке, чтобы перед выходом их восстановить. А что это за вычитание константы 0x1C из SP? А это как раз выделение стекового кадра. Из курса информатики известно, что стек — это такая вещь, которая адресуется не непосредственно, а относительно указателя на вершину стека. Рассмотрим графически, что сделают эти две строки.

                          Рис. 2. Влияние преамбулы функции на стек

                          Рис. 2. Влияние преамбулы функции на стек

                          Что это за стековый кадр? Всё просто. Его размер таков, чтобы в нём уместились все локальные переменные функции (кроме тех, которые оптимизатор положит в регистры). Размер стекового кадра вычисляется компилятором. Каждая переменная получает своё смещение относительно начала кадра, а обращение к ним идёт примерно так:

                          ;;;728 BufferSize = _GetBufferSize(LayerIndex);
                          000016 4620 MOV r0,r4
                          000018 f7fffffe BL _GetBufferSize
                          00001c 9006 STR r0,[sp,#0x18]


                          Очевидно, что переменная BufferSize имеет смещение относительно начала кадра на 0x18 байт.

                          ;;;730 SrcAddr = Offset + (y0 * _xSize[LayerIndex] + x0) * _BytesPerPixel[LayerIndex];
                          000030 4816 LDR r0,|L8.140|
                          000032 f8500024 LDR r0,[r0,r4,LSL #2]
                          000036 fb076000 MLA r0,r7,r0,r6
                          00003a 4915 LDR r1,|L8.144|
                          00003c 5d09 LDRB r1,[r1,r4]
                          00003e fb005001 MLA r0,r0,r1,r5
                          000042 9005 STR r0,[sp,#0x14]


                          А переменная SrcAddr — смещение 0x14

                          Ну, и так далее. Переменная же LayerIndex явно помещена не в стековый кадр, а в регистр R4.

                          Само собой, в конце своей работы, компилятор всё быстренько восстанавливает (а также помещает бывшее содержимое LR в PC, тем самым, переходя на адрес возврата)

                          00007e b007 ADD sp,sp,#0x1c
                          000080 e8bd8ff0 POP {r4-r11,pc}


                          Из всего этого, становятся ясны некоторые вещи:

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


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

                          Защита стека задачи от переполнения


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

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

                          На уровне ОС также можно производить контроль стека на переполнение. В ОСРВ МАКС используются следующие методы защиты:

                          • Проверка текущего положения указателя стека при переключении задач. Почти не влияет на производительность, но обладает низкой надежностью. Во-первых, разрушение стека уже произошло, а во-вторых – за время системного такта программа могла не только войти в функцию, вызвавшую переполнение, но и выйти из неё, а значит — указатель мог успеть вернуться обратно в разрешенный диапазон.
                          • Если установлен размер стека больше минимального, то к нему автоматически добавляется одно слово на вершине, куда записывается «magic number» — 32 разрядное число случайного вида, которое вряд ли встретится при работе программы. При переполнении стека это число будет затерто данными приложения, что почти наверняка позволит зафиксировать факт переполнения стека даже после возвращения указателя в рабочую область.
                          • В том случае, когда процессор содержит блок MPU (Memory Protection Unit), сразу за границей стека помещается область памяти минимально допустимого размера с защитой от доступа. Это самый совершенный способ контроля, так как при любом обращении к защищённой области, произойдет аппаратное прерывание. Следует, однако, помнить, что в некоторых случаях, защитная зона может оказаться не тронутой. Например, если часть локальных переменных, которые попали именно в эту зону, зарезервированы, но не используются. Защита сделана для самоконтроля и не должна идти в ущерб основным задачам.


                          Детали для работы с защитой стека можно найти среди констант, заданы в классе Task (в файле MaksTask.h). Изучая комментарии к этим константам, можно понять конкретные величины параметров «минимальный стек», «защищаемая область» и т.п. При желании, этим параметры можно и изменить. Следует только помнить, что размер защищаемой области должен быть степенью двойки.

                          Всё, наконец-то необходимый минимум теории, без которой невозможно начинать практические опыты, закончен.

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

                          Поэтому перед тем, как начать пичкать читателя дальнейшей теорией, стоит немного попрактиковаться. Но для этого следует рассмотреть, как же правильно начать работу с ОСРВ МАКС. Давайте будем считать, что читатель знаком с тем, как скомпилировать и запустить программу под имеющийся у него микроконтроллер, иначе текст будет сильно перегружен.

                          Если это не так, то крайне рекомендую ознакомиться с замечательными руководствами от среды разработки Keil по работе с отладочными платами ST (к сожалению, на английском языке, но многое понятно и из рисунков):

                          http://www.keil.com/appnotes/files/apnt_253.pdf

                          http://www.keil.com/appnotes/files/apnt_261.pdf

                          И в следующей статье мы приступим к первому практическому опыту.
                          Original source: habrahabr.ru (comments, light).

                          https://habrahabr.ru/post/337476/


                          Метки:  

                          [Из песочницы] Как написать свой первый Linux device driver

                          Четверг, 14 Сентября 2017 г. 15:50 + в цитатник
                          Alexeynew сегодня в 15:50 Разработка

                          Как написать свой первый Linux device driver

                          Здравствуйте, дорогие хабрачитатели.

                          Цель данной статьи — показать принцип реализации драйверов устройств в системе Linux, на примере простого символьного драйвера.

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

                          Это моя первая статья, пожалуйста не судите строго!

                          P.S

                          Получилось слишком много букв, поэтому я принял решение разделить статью на три части:

                          Часть 1 — Введение, инициализация и очистка модуля ядра.
                          Часть 2 — Функции open, read, write и trim.
                          Часть 3 — Пишем Makefile и тестируем устройство.

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

                          Итак, начнем.

                          Подготовительные работы


                          Символьный драйвер (Char driver) — это, драйвер, который оперирует/работает с выделенной ядром областью памяти.

                          Драйвер представляет каждое устройство структурой scull_dev, а также интерфейс cdev к ядру.

                          struct scull_dev {
                          	struct scull_qset *data;  /* Указатель на первый кусок памяти */
                          	int quantum;		  /* Размер одного кванта памяти */
                          	int qset;		  /* Количество таких квантов */
                          	unsigned long size;	  /* Размер используемой памяти */
                          	struct semaphore sem;     /* Используется семафорами */
                          	struct cdev cdev;	  /* Структура, представляющая символьные устройства */
                          };
                          
                          struct scull_dev *scull_device;
                          

                          Устройство будет представлять связный список указателей, каждый из которых указывает на структуру scull_qset.

                          struct scull_qset {
                          	void **data;
                          	struct scull_qset *next;
                          };
                          

                          Для наглядности посмотрите на картинку.

                          image

                          Для регистрации устройства, нужно задать специальные номера, а именно:

                          MAJOR — старший номер (является уникальным в системе).
                          MINOR — младший номер (не является уникальным в системе).

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

                          После того как мы определили номера для нашего устройства, мы должны установить связь между этими номерами и операциями драйвера. Это можно сделать используя структуру file_operations.

                          struct file_operations scull_fops = {
                          	.owner = THIS_MODULE,
                          	.read = scull_read,
                          	.write = scull_write,
                          	.open = scull_open,
                          	.release = scull_release,
                          };
                          

                          В ядре есть специальные макросы module_init/module_exit, которые указывают путь к функциям инициализации/удаления модуля. Без этих определений функции инициализации/удаления никогда не будут вызваны.

                          module_init(scull_init_module);
                          module_exit(scull_cleanup_module);
                          

                          Здесь будем хранить базовую информацию об устройстве.

                          int scull_major = 0;		/* MAJOR номер*/
                          int scull_minor = 0;		/* MINOR номер*/
                          int scull_nr_devs = 1;		/* Количество регистрируемых устройств */
                          int scull_quantum = 4000;	/* Размера памяти в байтах */
                          int scull_qset = 1000;		/* Количество квантов памяти */
                          

                          Последним этапом подготовительной работы будет подключение библиотек.
                          Краткое описание приведено ниже, но если вы хотите копнуть поглубже, то добро пожаловать на прекрасны сайт: lxr

                          #include module.h> /* Содержит функции и определения для динамической загрузки модулей ядра */
                          #include init.h>  /* Указывает на функции инициализации и очистки */
                          #include fs.h>    /* Содержит функции регистрации и удаления драйвера */
                          #include cdev.h>  /* Содержит необходимые функции для символьного драйвера */
                          #include slab.h>  /* Содержит функцию ядра для управления памятью */
                          #include uaccess.h> /* Предоставляет доступ к пространству пользователя */
                          

                          Инициализация


                          Теперь давайте посмотрим на функцию инициализации устройства.

                          static int scull_init_module(void)
                          {
                          	int rv, i;
                          	dev_t dev;
                          
                          	rv = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull");	
                          	scull_major = MAJOR(dev);
                          
                          	if (rv) {
                          		printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
                          		return rv;
                          	}
                          
                          	scull_device = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
                          	
                          	if (!scull_device) {
                          		rv = -ENOMEM;
                          		goto fail;
                          	}
                          
                          	memset(scull_device, 0, scull_nr_devs * sizeof(struct scull_dev));
                          
                          	for (i = 0; i < scull_nr_devs; i++) {
                          		scull_device[i].quantum = scull_quantum;
                          		scull_device[i].qset = scull_qset;
                          		sema_init(&scull_device[i].sem, 1);
                          		scull_setup_cdev(&scull_device[i], i);
                          	}
                          
                          	dev = MKDEV(scull_major, scull_minor + scull_nr_devs);	
                          
                          	return 0;
                          
                          fail:
                          	scull_cleanup_module();
                          	return rv;
                          }
                          

                          Первым делом, вызывая alloc_chrdev_region мы регистрируем диапазон символьных номеров устройств и указываем имя устройства. После вызовом MAJOR(dev) мы получаем старший номер.
                          Далее проверяется вернувшееся значение, если оно является кодом ошибки, то выходим из функции. Стоит отметить, что при разработке реального драйвера устройства следует всегда проверять возвращаемые значения, а также указатели на любые элементы (NULL?).

                          rv = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull");	
                          	scull_major = MAJOR(dev);
                          
                          if (rv) {
                          	printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
                          	return rv;
                          }
                          

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

                          Выделяем память, делая системный вызов kmalloc и обязательно проверяем указатель NULL.

                          scull_device = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
                          	
                          if (!scull_device) {
                          	rv = -ENOMEM;
                          	goto fail;
                          }
                          
                          memset(scull_device, 0, scull_nr_devs * sizeof(struct scull_dev));
                          

                          Продолжаем инициализацию. Главная здесь функция — это scull_setup_cdev, о ней мы поговорим чуть ниже. MKDEV служит для хранения старший и младших номеров устройств.

                          for (i = 0; i < scull_nr_devs; i++) {
                          		scull_device[i].quantum = scull_quantum;
                          		scull_device[i].qset = scull_qset;
                          		sema_init(&scull_device[i].sem, 1);
                          		scull_setup_cdev(&scull_device[i], i);
                          	}
                          
                          	dev = MKDEV(scull_major, scull_minor + scull_nr_devs);
                          

                          Возвращаем значение или обрабатываем ошибку и удаляем устройство.

                          return 0;
                          
                          fail:
                          	scull_cleanup_module();
                          	return rv;
                          }
                          

                          Выше были представлены структуры scull_dev и cdev, которая реализует интерфейс между нашим устройством и ядром. Функция scull_setup_cdev выполняет инициализацию и добавление структуры в систему.

                          static void scull_setup_cdev(struct scull_dev *dev, int index)
                          {
                          	int err, devno = MKDEV(scull_major, scull_minor + index);
                          
                          	cdev_init(&dev->cdev, &scull_fops); 
                          
                          	dev->cdev.owner = THIS_MODULE;
                          	dev->cdev.ops = &scull_fops;
                          
                          	err = cdev_add(&dev->cdev, devno, 1);
                          
                          	if (err)
                          		printk(KERN_NOTICE "Error %d adding scull  %d", err, index);
                          }
                          

                          Удаление


                          Функция scull_cleanup_module вызывается при удаление модуля устройства из ядра.
                          Обратный процесс инициализации, удаляем структуры устройств, освобождаем память и удаляем выделенные ядром младшие и старшие номера.

                          void scull_cleanup_module(void)
                          {
                          	int i;
                          	dev_t devno = MKDEV(scull_major, scull_minor);
                          
                          	if (scull_device) {
                          		for (i = 0; i < scull_nr_devs; i++) {
                          			scull_trim(scull_device + i);
                          			cdev_del(&scull_device[i].cdev);	
                          		}
                          		
                          		kfree(scull_device);
                          	}
                          
                          	unregister_chrdev_region(devno, scull_nr_devs); 
                          }
                          

                          Полный код
                          #include module.h> 	
                          #include init.h> 	
                          #include fs.h> 		
                          #include cdev.h> 	
                          #include slab.h> 	
                          #include uaccess.h>
                          
                          int scull_major = 0;		
                          int scull_minor = 0;		
                          int scull_nr_devs = 1;		
                          int scull_quantum = 4000;	
                          int scull_qset = 1000;	
                          
                          struct scull_qset {
                          	void **data;			
                          	struct scull_qset *next; 	
                          };
                          
                          struct scull_dev {
                          	struct scull_qset *data;  
                          	int quantum;		 
                          	int qset;		  
                          	unsigned long size;	  
                          	unsigned int access_key;  
                          	struct semaphore sem;    
                          	struct cdev cdev;	 
                          };
                          
                          struct scull_dev *scull_device;
                          
                          int scull_trim(struct scull_dev *dev)
                          {
                          	struct scull_qset *next, *dptr;
                          	int qset = dev->qset; 
                          	int i;
                          
                          	for (dptr = dev->data; dptr; dptr = next) { 
                          		if (dptr->data) {
                          			for (i = 0; i < qset; i++)
                          				kfree(dptr->data[i]);
                          
                          			kfree(dptr->data);
                          			dptr->data = NULL;
                          		}
                          
                          		next = dptr->next;
                          		kfree(dptr);
                          	}
                          
                          	dev->size = 0;
                          	dev->quantum = scull_quantum;
                          	dev->qset = scull_qset;
                          	dev->data = NULL;
                          
                          	return 0;
                          }
                          
                          struct file_operations scull_fops = {		
                          	.owner = THIS_MODULE,			
                          	//.read = scull_read,
                          	//.write = scull_write,
                          	//.open = scull_open,
                          	//.release = scull_release,
                          };
                          
                          static void scull_setup_cdev(struct scull_dev *dev, int index)
                          {
                          	int err, devno = MKDEV(scull_major, scull_minor + index);	
                          
                          	cdev_init(&dev->cdev, &scull_fops);
                          
                          	dev->cdev.owner = THIS_MODULE;
                          	dev->cdev.ops = &scull_fops;
                          
                          	err = cdev_add(&dev->cdev, devno, 1);
                          
                          	if (err)
                          		printk(KERN_NOTICE "Error %d adding scull  %d", err, index);
                          }
                          
                          void scull_cleanup_module(void)
                          {
                          	int i;
                          	dev_t devno = MKDEV(scull_major, scull_minor);
                          
                          	if (scull_device) {
                          		for (i = 0; i < scull_nr_devs; i++) {
                          			scull_trim(scull_device + i);		
                          			cdev_del(&scull_device[i].cdev);	
                          		}
                          		
                          		kfree(scull_device);
                          	}
                          
                          	unregister_chrdev_region(devno, scull_nr_devs); 
                          }
                          
                          static int scull_init_module(void)
                          {
                          	int rv, i;
                          	dev_t dev;
                          
                          		
                          	rv = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull");	
                          	scull_major = MAJOR(dev);
                          
                          	if (rv) {
                          		printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
                          		return rv;
                          	}
                          
                          	scull_device = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);	
                          	
                          	if (!scull_device) {
                          		rv = -ENOMEM;
                          		goto fail;
                          	}
                          
                          	memset(scull_device, 0, scull_nr_devs * sizeof(struct scull_dev));		
                          
                          	for (i = 0; i < scull_nr_devs; i++) {						
                          		scull_device[i].quantum = scull_quantum;
                          		scull_device[i].qset = scull_qset;
                          		sema_init(&scull_device[i].sem, 1);
                          		scull_setup_cdev(&scull_device[i], i);					
                          	}
                          
                          	dev = MKDEV(scull_major, scull_minor + scull_nr_devs);	
                          	
                          	printk(KERN_INFO "scull: major = %d minor = %d\n", scull_major, scull_minor);
                          
                          	return 0;
                          
                          fail:
                          	scull_cleanup_module();
                          	return rv;
                          }
                          
                          MODULE_AUTHOR("Your name");
                          MODULE_LICENSE("GPL");
                          
                          module_init(scull_init_module);		
                          module_exit(scull_cleanup_module);	
                          


                          С удовольствием выслушаю конструктивную критику и буду ждать feedback'a.

                          Если вы нашли ошибки или я не правильно изложил материал, пожалуйста, укажите мне на это.
                          Для более быстрой реакции пишите в ЛС.

                          Спасибо!
                          Original source: habrahabr.ru (comments, light).

                          https://habrahabr.ru/post/337946/


                          Метки:  

                          [Перевод] Удивительно полезный инструмент: lsof

                          Четверг, 14 Сентября 2017 г. 14:59 + в цитатник

                          Метки:  

                          [recovery mode] Как мы делали небольшую охранную систему на RPi. Часть 2

                          Четверг, 14 Сентября 2017 г. 14:55 + в цитатник
                          iBlacksus сегодня в 14:55 Разработка

                          Как мы делали небольшую охранную систему на RPi. Часть 2

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

                          image

                          Охранная система будет располагаться за пределами действия wi-fi, и у нее будет только мобильный интернет с небольшой скоростью, поэтому я решил, что обмен данными нужно сделать как можно менее затратным. В данном случае самое простое решение, это использование цифровых кодов. Т.е. мы отправляем на сервер 1 и он понимает, что сработал датчик движение, 2 — датчик дыма и т.д., для каждого события свой код. В свою очередь сервер расшифровывает коды и отправляет то, что считает нужным, в виде push-уведомления в iOS приложение, уже в виде текста. При этом каждое событие записывается как в лог на стороне RPi, так и в лог сервера, этот лог так же можно посмотреть в приложении. Кстати, вся работа с сервером в Python осуществляется с помощью Requests.

                          Сервер написан на PHP, так же там присутствует MySQL, в ней хранится лог и текущие настройки, т.е. всего две таблицы, вот одна из них:



                          Все запросы принимаются с помощью обычного POST, и отдаются в JSON. Выглядит это примерно так:

                          print json_encode(getRequest($_POST));

                          Для работы серверу нужно не так много методов:

                          • Получать сообщение от RPi
                          • Отдавать лог
                          • Устанавливать настройки
                          • Отдавать настройки

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

                          Так же сервер следит за тем, чтобы RPi каждую минуту сообщал, что он в сети и с ним ничего не случилось. Если этого не происходит в течение 5 минут, то сервер начинает бить тревогу. Сделана эта проверка с помощью cron'а

                          */5 * * * * php /aliceserver/checkAlice.php

                          Он каждые 5 минут запускает простенький скриптик проверки

                          include_once $dir . 'defines.php';
                          include_once $dir . 'db.php';
                          
                          $db = new DataBase;
                          $db->connect();
                          
                          $query = "SELECT alice, UNIX_TIMESTAMP(online) online FROM " . SQLTableStatus;
                          $result = $db->query($query);
                          
                          $alice_is_on = $result[0]['alice'];
                          $online = (time() - $result[0]['online'] < 5*60);
                          
                          if ($alice_is_on and !$online) {
                          	include_once $dir . 'send_push.php';
                          	
                          	$text = "Alice offline!";
                          		
                          	$query = "INSERT INTO `" . SQLTableLog . "` (text, sender) VALUES ('$text', 1)";
                          	$db->query($query);
                          		
                          	send_push_message($text, AppToken, 'alice_offline.caf', $dir);
                          }
                          
                          $db->disconnect();

                          Отправка push-уведомлей реализована с помощью ApnsPHP. Те из вас, кто хоть раз сталкивался с отправкой push-уведомлений на сервера Apple, наверняка знакомы с этим замечательным open-sourse решением. Для тех, кто не знает что это, могу только сказать, что на текущий момент это одна из лучших оберток, которая позволяет легко отправлять уведомления, при этом для ее настройки нужно минимум времени и усилий.

                          На этом рассказ про серверную часть подходит к концу, в следующий раз я расскажу как делалось iOS приложение. Всем спасибо за внимание, по возможности отвечу на все вопросы по железу и софту в комментариях.
                          Original source: habrahabr.ru (comments, light).

                          https://habrahabr.ru/post/231963/


                          Метки:  

                          Нужна помощь в тестировании поддержки префикса таблиц в плигине Yii2 support для PhpStorm / Intellij

                          Четверг, 14 Сентября 2017 г. 14:53 + в цитатник
                          olegl84 сегодня в 14:53 Разработка

                          Нужна помощь в тестировании поддержки префикса таблиц в плигине Yii2 support для PhpStorm / Intellij

                            Привет, хабрсообщество.

                            Готовится апдейт yii2support плагина для PhpStorm — поддержка префиксов таблиц.
                            Нужны волонтеры для тестирования. Пишите в личку email, на выходных кину alpha версию c этим функционалом.
                            Original source: habrahabr.ru (comments, light).

                            https://habrahabr.ru/post/337944/


                            Метки:  

                            Ежемесячная рубрика «Читаем статьи за Вас». Август 2017

                            Четверг, 14 Сентября 2017 г. 14:09 + в цитатник
                            grisme сегодня в 14:09 Разработка

                            Ежемесячная рубрика «Читаем статьи за Вас». Август 2017

                              image


                              Привет, Хабр!
                              С этого выпуска мы начинаем хорошую традицию: каждый месяц будет выходить набор рецензий на некоторые научные статьи от членов сообщества Open Data Science из канала #article_essence. Хотите получать их раньше всех — вступайте в сообщество ODS!
                              Статьи выбираются либо из личного интереса, либо из-за близости к проходящим сейчас соревнованиям. Если вы хотите предложить свою статью или у вас есть какие-то пожелания — просто напишите в комментариях и мы постараемся всё учесть в дальнейшем.


                              Статьи на сегодня:


                              1. Fitting to Noise or Nothing At All: Machine Learning in Markets
                              2. Learned in Translation: Contextualized Word Vectors
                              3. Create Anime Characters with A.I. !
                              4. LiveMaps: Converting Map Images into Interactive Maps
                              5. Random Erasing Data Augmentation
                              6. YellowFin and the Art of Momentum Tuning
                              7. The Devil is in the Decoder
                              8. Improving Deep Learning using Generic Data Augmentation
                              9. Learning both Weights and Connections for Efficient Neural Networks
                              10. Focal Loss for Dense Object Detection
                              11. Borrowing Treasures from the Wealthy: Deep Transfer Learning through Selective Joint Fine-tuning
                              12. Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks

                              1. Fitting to Noise or Nothing At All: Machine Learning in Markets


                              Оригинал статьи
                              Автор: kt{at}ut{dot}ee


                              Это рецензия на статью, в которой диплернингом предсказываются финансовые рынки. Автор поста (далее — ZHD) указывает на следующие очевидные глупости данной и схожих статей:


                              • Притягивание за уши показателя accuracy методом взятия максимума из всех экспериментов. Медиана, наоборот, как раз соответствует случайному предсказанию.
                              • Хвастовство "хорошими результатами", которые получены на инструментах, которые сейчас вообще не торгуются (т.е. у них константная цена). В целом, ZHD рекомендует сравнивать трейдинговые модели не со случайным предсказателем, а со стратегией buy and hold.
                              • Авторы "симулируют" свою стратегию, предполагая отсутствие комиссий при сделках и то, что любую сделку можно выполнить по цене, равной среднему между high и low за последние пять минут. Из-за этого в симуляциях наилучшая прибыль получается у наименее ликвидных инструментов (которые на деле далеко не всегда продадутся по средней цене за пять минут, поэтому вся прибыль скорее всего "получена" за счет нечестного предположения о ликвидности). Вдобавок, авторы хвастаются только несколькими "удачными" моделями, умалчивая всё, что отсимулировалось в минус.
                              • Авторы не учитывают время работы бирж (в том числе, очные сессии для сделок (trading pits)) и по мнению ZHD это неправильно.

                              2. Learned in Translation: Contextualized Word Vectors


                              Оригинал статьи
                              Код
                              Автор: kt{at}ut{dot}ee


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


                              Авторы статьи предлагают углубить текстовый трансфер лернинг на один уровень следующим образом:


                              • Натренируем LSTM-based seq2seq модель (вида encoder + decoder with attention over encoder hidden states) для перевода, скажем, с английского на немецкий.
                              • Возьмем из неё только encoder (он будет простенького вида LSTM(Embedding(word_idxs)). Этот энкодер умеет превращать последовательность слов в последовательность LSTM hidden states. Т.к. эти hidden states взяты не случайно (их переводческая модель использует в своём аттеншене), то однозначно в них будет полезный сигнал.
                              • Ну и всё, давайте теперь строить любые другие текстовые модели, которым мы на вход будем скармливать не только GloVe векторы слов, но и приклеенные к ним соответствующие LSTM hidden векторы из нашего переводческого энкодера (их мы будем называть Context Vectors, CoVe).

                              Далее авторы наворачивают какую-то нетривиальную модель c biattention и maxout (видимо, завалялась с их прошлой работы) и сравнивают, как она работает в разных задачах, если ей на входе скормить случайный эмбеддинг, GloVe, GloVe+CoVe, GloVe+CoVe+CharNGramEmbeddings.


                              По результатам кажется, что добавление CoVe повышает точность голого GloVe примерно на 1%. Иногда эффект меньше, иногда отрицательный, иногда добавление вместо CoVe в модель CharNGrams работает так же или даже лучше. В любом случае, совмещение GloVe+CoVe+CharNGrams работает точно лучше всех других методов.


                              image


                              На мой взгляд, из-за того, что авторы навернули нехилую модель с аттеншеном поверх сравниваемых типов эмбеддинга (GloVe vs CoVe), замер эффекта полезности CoVe получился излишне зашумленным и не очень убедительным. Я бы предпочел увидеть более "лабораторный" замер.


                              3. Create Anime Characters with A.I. !


                              Оригинал статьи
                              Сайт
                              Автор: kt{at}ut{dot}ee


                              Существует сайт Getchu, на котором собраны "профили" анимешных героев различных японских игр с картинками-иллюстрациями. Эти картинки можно скачать.


                              Для нахождения лица на картинке можно использовать некую тулзу "lbpcascade animeface". Таким образом авторы получили 42к анимешных лиц, которые они потом ручками пересмотрели и выкинули 4% плохих примеров.


                              Имеется некая уже готовая CNN-модель Illustration2Vec, которая умеет распознавать на анимешных картинках свойства типа "улыбка", "цвет волос", итд. Авторы использовали её для того, чтобы отлейблить картинки и выбрали 34 интересующих их тэга.
                              Авторы запихнули это всё в DRAGAN (Kodali et al, где это отличается от обычных GAN авторы не углубляются, видимо, непринципиально).
                              Чтобы уметь генерировать картинки с заданными атрибутами, авторы делают как в ACGAN:


                              • Кормят генератору вектор атрибутов.
                              • Заставляют дискриминатор этот вектор предсказывать.
                              • Дополнительно штрафуют генератор пропорционально тому, насколько дискриминатор не угадал верный класс.

                              И генератор, и дискриминатор — довольно замороченные конволюционные SRResNet-ы (у генератора 16-блоковый, у дискриминатора 10-блоковый). У дискриминатора авторы убрали батчнорм-слои "since it would bring correlations within the mini-batch, which is undesired for the computation of the gradient norm." Я не очень понял эту проблему, поясните если вдруг кому ясно.
                              Тренировалось всё Адамом с уменьшающимся lr начиная от 0.0002, не очень понятно как долго.
                              Для вебаппа авторы сконвертировали сеть под WebDNN (https://github.com/mil-tokyo/webdnn) и поэтому генерят все картинки прямо в браузере на клиенте (!).


                              4. LiveMaps: Converting Map Images into Interactive Maps


                              [Оригинал статьи](http://dl.acm.org/citation.cfm?id=3080673, https://doi.org/10.1145/3077136.3080673)
                              Статья — победитель Best Short Paper Awart SIGIR 2017
                              Автор: zevsone


                              Предложена принципиально новая система (LiveMaps) для анализа изображений карт и извлечения релевантного viewport'a.


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


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


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


                              P.S. Совсем не ожидал получить best short paper award на такой маститой конфе (121 short paper в претендентах в этом году, все industry гиганты).


                              5. Random Erasing Data Augmentation


                              Оригинал статьи
                              Автор: egor.v.panfilov{at}gmail{dot}com


                              Статья посвящена исследованию одного из простейших методов аугментации изображений — Random Erasing (по-русски, закрашиванию случайных прямоугольников).


                              Аугментация параметризовалась 4-мя параметрами: (P_prob) вероятность применения к каждой картинке батча, (P_area) размер региона (area ratio), (P_aspect) соотношение сторон региона (aspect ratio), (P_value) заполняемое значением: случайные / среднее на ImageNet / 0 / 255.


                              image


                              Авторы провели оценку влияния данного метода аугментации на 3-х задачах: (A) object classification, (B) object detection, © person re-identification.


                              (A): Использовались 6 архитектур, начиная с AlexNet, заканчивая ResNeXt. Датасет — CIFAR10/100. Оптимальное значение параметров: P_prob = 0.5, P_aspect = в широком диапазоне, но желательно не 1(квадрат), P_area = 0.02-0.4 (2-40% изображения), P_value = random или среднее на ImageNet, для 0 и 255 результаты существенно хуже. Сравнили также с другими методами и аугментации (random cropping, random flipping), и регуляризации (dropout, random noise): в порядке снижения эффективности — всё вместе, random cropping, random flipping, random erasing. Drouput и random noise данный метод уделывет "в щепки". В целом, метод не самый мощный, но при оптимальных параметрах стабильно даёт 1% точности (5.5% -> 4.5%). Также пишут, что он повышает робастность классификатора к перекрытиям объектов :you-dont-say:.


                              (B): Использовалась Fast-RCNN на PASCAL VOC 2007+2012. Реализовали 3 схемы: IRE (Image-aware Random Erasing, также выбираем регион для зануления вслепую), ORE (Object-aware, зануляем только части bounding box'ов), I+ORE (и там, и там). Существенной разницы по mAP между этими методами нет. По сравнению с чистым Fast-RCNN, дают порядка 5% (67->71 на VOC07, 70->75 на VOC07+12), столько же, сколько и A-Fast-RCNN. Оптимальные параметры — P_prob = 0.5, P_area = 0.02-0.2 (2-20%), P_aspect = 0.3-3.33 (от лежачей до стоячей полоски).


                              ©: Использовались ID-discim.Embedding (IDE), Triplet Net, и SVD-Net (все на базе ResNet, предобученной на ImageNet) на Market-1501 / DukeMTMC-reID / CUHK03. На всех моделях и датасетах аугментация стабильно даёт не менее 2% (до 8%) для Rank@1, и не менее 3% (до 8%) для mAP. Параметры те же, что и для (B).


                              В целом, несмотря на простоту метода, исследование и статья довольно аккуратные и подробные (10 страниц), с кучей графиков и таблиц. Порадовали китайцы, ничего не скажешь.


                              6. YellowFin and the Art of Momentum Tuning


                              Оригинал статьи
                              Дополнительный материал про momentum
                              Автор: Arech


                              Давно я её читал, поэтому очень-очень поверхностно: после вдумчивого курения свойств классического моментума (он же моментум Бориса Поляка), на одномерных строго выпуклых квадратичных целях чуваки вывели (или нашли у кого-то?) неравенство, связывающее коэффициенты learning rate и моментума так, чтобы они попадали в некий "робастный" регион, гарантирующий наибыстрейшее схождение алгоритма SGD. Потом показали(?), что оное утверждение в принципе может как-то выполняться и для некоторых невыпуклых функций, по крайней мере в некоторой их локальной области, которую можно более-менее апроксимировать квадратичным приближением. После чего решили запилить свой тюнер YellowFin, который на основании знания предыдущей истории изменения градиента, апроксимировал бы нужные для неравенства характеристики поверхности функции ошибки (дисперсия градиента, некая "обощённая" кривизна поверхности и расстояние до локального минимума квадратичной апроксимации текущей точки) и, с помощью этих апроксимаций, выдавал бы подходящие значения learning rate и моментума для использования в SGD.


                              Также, изучив вопрос асинхронной (распределённой) тренировки сетей, чуваки предложили обобщение своего метода (Closed-loop YellowFin), которое учитывает, что реальный моментум в таких условиях оказывается больше запланированного.


                              Тестировали свёрточные 110- и 164-слойные ResNet на CIFAR10 и 100 соответственно, и какие-то LSTM на PTB, TS и WSJ. Результаты интересные (от х1.18 до х2.8 ускорения относительно Адама), но, как обычно, есть вопросы к постановке эксперимента — грубый подбор коэффициентов для компетиторов, + емнип, только один прогон на каждую архитектуру, + показаны результаты только тренировочного набора… Короче, есть к чему докопаться...


                              Как-то так, надеюсь, по деталям не сильно наврал.


                              Я подумывал запилить его к своей либине, но крепко влип в Self-Normalizing Neural Networks (SELU+AlphaDropout), которыми занялся чуть раньше и которые оказались мне крайне полезны, поэтому пока руки не дошли. Слежу за тем тредом в Lesagne (https://github.com/Lasagne/Lasagne/issues/856 — у человека возникли проблемы с воспроизводством результатов) и вообще, надеюсь, что будет больше инфы по воспроизводству их результатов. Так что если кто попробует — делитесь чокак.


                              7. The Devil is in the Decoder


                              Оригинал статьи
                              Автор: ternaus


                              Вопрос с тем, какой UpSampling лучше для различных архитектур, где есть Decoder, теребит умы многих, особенно тех, кто борется за пятый знак после запятой в задачах сегментации, super resolution, colorization, depth, boundary detection.


                              Ребята из Гугла и UCL заморочились и написали статью, где эмпирическим путем решили проверить кто лучше и найти в этом логику.


                              Проверили — выяснилось, что разница есть, но логика не очень просматривается.


                              Для сегментации:


                              [1] Transposed Conv = Upsampling + Conv и который все яростно используют в Unet норм.
                              [2] добрасывание skiped connections, то есть, трансформация SegNet => Unet железобетонно добрасывает. Это интуитивно понятно, но тут есть циферки.
                              [3] Такое ощущение, что Separable Transposed, которое Transposed, но с меньшим числом параметоров для сегментации, работает лучше. Хотелось бы, чтобы народ в #proj_cars это проверил.
                              [4] Хитроумный Bilinear additive Upsampling, который они предложили, на сегментации работает примерно как [3]. Но это тоже в сторону коллектива из #proj_cars проверить
                              [5] Они добрасывают residual connections куда-то, что тоже в теории может что-то добавить, но куда именно — не очень понятно, и добрасывает очень неуверенно и не всегда.


                              Для задач сегментации они используют resnet 50 как base и потом сверху добавляют decoder.


                              Для задачи instance boundary detection они решили выбрать метрику, при которой меньше оверфитишь на алгоритм разметки + циферки побольше получаются.
                              То есть, During the evaluation, predicted contour pixels within three from ground truth pixels are assumed to be correct. Что сразу ставит вопрос о том, как это все переносится на задачи, где важен каждый пиксель. (Тут вспоминается Костин трюк со спутников для поиска заборов толщиной в один пиксель и то, как народ борется за +-1 пиксель на границах в задаче про машинки)


                              [6] У всех сетей, что они тренируют, у весов используется L2 регуляризация порядка 0.0002
                              Карпатый, вроде, тоже в свое время говорил, что всегда так делает для более стабильной сходимости. (Это мне надо попробовать, если кто так делает и это дает что-то заметное, было бы неплохо рассказать об этом в тредике)


                              Summary:
                              [1] Вопрос о том, кто и когда лучше они подняли, но не ответили.
                              [2] Они предложили еще один метод делать Upsampling, который работает не хуже других.
                              [3] Подтвердили, что skipped connection однозначно помогают, а residual — в зависимости от фазы луны.


                              Ждем месяц, о том, что скажет человеческий GridSearch на #proj_cars.


                              8. Improving Deep Learning using Generic Data Augmentation


                              Оригинал статьи
                              Автор: egor.v.panfilov{at}gmail{dot}com


                              Эпиграф: Лавры китайцев не дают покоя никому, даже на чёрном континенте. Хороших компьютеров, правда, пока не завезли, но Тернаус велел писать, "и вот они продолжают".


                              Авторы попытались провести бенчмарк методов аугментации изображений на задаче классификации изображений, и выработать рекомендации по их использованию для различных случаев. В первом приближении, данные методы разделить на 2 категории: Generic (общеприменимые) и Complex (использующие информацию о домене / генеративные). В данной статье рассматриваются только Generic.


                              Все эксперименты в статье проводились на Caltech-101 (101 класс, 9144 изображения) с использованием ZFNet (половина информативной части статьи о том, как лучше всего обучить ванильную ZFNet). Обучали 30 эпох, используя DL4j. Рассматриваемые методы аугментации: (1) без аугмен-ции, (2-4) геометрические: horizontal flipping, rotating (-30deg и +30deg), cropping (4 угловых кропа), (5-7) фотометрические: color jittering, edge enhacement (добавляем к изображению результат фильтра Собеля), fancy PCA (усиливаем principal компоненты на изображениях).


                              Результаты: к бейзлайну (top1/top5: 48.1%/64.5%) (a) flipping даёт +1/2%, но увеличивает разброс точности, (b) rotating даёт +2%, © cropping даёт +14%, (d) color jittering +1.5/2.5%, (d-e) edge enhancement и fancy PCA по +1/2%. Т.е. среди геометрических методов впереди cropping, среди фотометрических — color jittering. В заключении авторы пишут, что существенное улучшение точности при аугментации cropping'ом может быть связано с тем, что датасет получается в 4 раза больше исходного (сбалансировать-то не судьба). Из положительного — не забыли 5-fold кросс-валидацию при оценке точности моделей. Почему были выбраны конкретно эти методы аугментации среди других (в т.ч. более популярных) узнаем, видимо, в следующей статье.


                              9. Learning both Weights and Connections for Efficient Neural Networks


                              Оригинал статьи
                              Автор: egor.v.panfilov{at}gmail{dot}com


                              Статья рассматривает проблему выского потребления ресурсов современными архитектурами DNN (в частности, CNN). Самый главный бич — это обращение к динамической памяти. Например, инференс сети с 1 млрд связей на 20Гц потребляет ~13Вт.


                              Авторы предлагают метод снижения числа активных нейронов и связей в сети — prunning. Работает следующим образом: (1) обучаем сеть на полном датасете, (2) маскируем связи с весами ниже определённого уровня, (3) дообучаем оставшиеся связи на полном датасете. Шаги (2) и (3) можно и нужно повторять несколько раз, так как агрессивный (за 1 подход) prunning показывает результаты немного хуже (для AlexNet на ImageNet, например, 5x против 9x). Хитрости: использовать L2-регуляризацию весов, при дообучении уменьшать dropout, уменьшать learning rate, прунить и дообучать CONV и FC слои раздельно, выкидывать мёртвые (non-connected) нейроны по результатам шага (2).


                              Эксперименты производились в Caffe с сетями Lenet-300-100, Lenet-5 на MNIST, AlexNet, VGG-16 на ImageNet. На MNIST: уменьшили число весов и FLOP'ов в 12 раз, а также обнаружили, что prunning проявляет свойство механизма attention (по краям режет больше). На ImageNet: AlexNet обучали 75 часов и дообучали 173 часа, VGG-16 прунили и дообучали 5 раз. По весам удалось сжать в 9 и 13 раз соответственно, по FLOP'ам — в 3.3 и 5 раз. Интересен профиль того, как прунятся связи: первый CONV-слой ужимается меньше чем в 2 раза, следующие CONV — в 3 и более (до 12), скрытые FC — в 10-20 раз, последний FC слой — в 4 раза.


                              В заключение, авторы приводят результаты сравнения различных методов prunning'а (с L1-, L2-регуляризацией, с дообучением и без, отдельно по CONV, отдельно по FC). Вкратце, есть лень прунить, то учите сеть с L1, и половину слоёв можно просто выкинуть. Если не лень — только L2, прунить и дообучать итеративно ~5 раз. И последнее, хранение весов в sparse виде у авторов давало overhead в ~16% — не то чтобы критично, когда у вас сеть в 10 раз меньше.
                              image


                              10. Focal Loss for Dense Object Detection


                              Оригинал статьи
                              Автор: kt{at}ut{dot}ee


                              Как известно, процесс поиска моделей в машинном обучении упирается в оптимизацию некой целевой функции потерь. Самая простая функция потерь — процент ошибок на тренинг-сете, но её оптимизировать сложно и результат статистически плох, поэтому на практике используют разные суррогатные лоссы: квадрат ошибки, минус логарифм вероятности, экспонента от минус скора, hinge loss и т.д. Все суррогатные лоссы являются монотонными функциями, штрафующими ошибки тем больше, чем больше величина ошибки. Любой лосс можно интерпретировать как вид распределения целевой переменной (например, квадрат ошибок соответствует гауссовому распределению).


                              Авторы работы обнаружили, что суррогатный лосс вида


                              loss(p, y) := -(1-p)^gamma log(p) if y == 1 else -p^gamma log(1-p)


                              ещё нигде не использовался и не публиковался. Зачем нужно использовать именно такой лосс, а не ещё какой-нибудь, и каков смысл подразумеваемого распределения, авторы не знают, но им он кажется прикольным, т.к. здесь есть лишний параметр gamma, с помощью которого можно как будто бы подкручивать величину штрафа "легким" примерам. Авторы назвали эту функцию "focal loss".


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


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


                              Альтернативное мнение
                              Следи за руками: чуваки взяли один из стандартных, довольно сложных датасетов, на которых меряются в детекции, взяли простенькую сеть без особых наворотов (то из чего все другие уже пробовали выжать сколько могли), приложили свой лосс и получили сходу результат single model без мультскейла и прочих трюков выше чем все остальные на этом датасете, включая все сети в одну стадию и более продвинутые двухстадийные. Чтобы убедиться, что дело в лоссе, а не чём-то ещё, они попробовали другие варианты, которые до этого были крутыми и модными техниками — балансирование кросс-энтропии, OHEM и получили результат стабильно выше на своём. Покрутили параметры своего и нашли вариант, который работает лучше всех и даже попробовали чуток объяснить почему (там есть график, где видно что гамма ниже 2 даёт довольно гладкое распределение, а больше двух уж очень резко штрафует (даже при двух там практически полка, удивительно что работает)).
                              Конечно, можно было им начать сравнивать 40 вариантов сетей, с миллионом вариантов гиперпараметров и на всех известных датасетах, да ещё и кроссвалидацию 10 раз по 10 фолдов, но сколько бы это времени тогда заняло и когда была бы публикация готова и сколько бы там было разных идей?
                              Тут всё просто — изменили один компонент, получили результат превосходящий SoTA на конкретном датасете. Убедились, что результат вызван изменением, а не чем-то ещё. Fin.


                              Альтернативное мнение
                              Наверное, стоит добавить, что если бы статья позиционировалась как представление RetinaNet, она бы смотрелась, по-моему, совсем по-другому. Она ведь и построена на самом-то деле в основном как пример применения RetinaNet. Зачем в неё внезапно вставили упор на лосс и странный заголовок, мне лично непонятно. Объективных замеров, подтверждающих высказанные про этот лосс тезисы там всё-таки нет.


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


                              В любом случае, я для себя никак не могу вынести из этой статьи обещанный в заглавии и тексте тезис "вкручивайте такой лосс везде и будет вам счастье".


                              Тезис "RetinaNet хорошо работает на COCO (с любым лоссом, причем!)" я, при этом, вынести вполне могу.


                              11. Borrowing Treasures from the Wealthy: Deep Transfer Learning through Selective Joint Fine-tuning


                              Оригинал статьи
                              Код
                              Автор: movchan74


                              image


                              Авторы сосредоточились на проблеме классификации изображений с небольшим датасетом. Типичный подход в таком случае следующий: взять предобученную CNN на ImageNet и дообучить на своем датасете (или даже дообучить только классификационные полносвязный слои). Но при этом сеть быстро переобучается и достигает не таких значений точности, каких хотелось бы. Авторы предлагают использовать не только целевой датасет (target dataset, мало данных, далее буду называть датасет T), но и дополнительный исходный датесет (source dataset, далее буду называть датасет S) с большим количеством изображений (обычно ImageNet) и обучать мультитаск на двух датасетах одновременно (делаем после CNN две головы по одной на датасет).


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


                              Получаем следующий фреймворк:


                              1. Берем два датасета: S и T. T — датасет с малым количеством примеров, для которого нам необходимо получить классификатор, S — большой вспомогательный датасет (обычно ImageNet).
                              2. Выбираем подмножество изображений из датасета S, такое, что изображения из подмножества близки к изображениям из целевого датасета T. Как именно выбирать близкие рассмотрим далее.
                              3. Учим мультитаск сеть на датасете T и выбранном подмножесте S.

                              Рассмотрим как предлагается выбирать подмножество датасета S. Авторы предлагают для каждого семпла из датасета T находить некоторое количество соседей из S и учиться только на них. Близость определяется как расстояние между гистограммами низкоуровневых фильтров AlexNet или фильтров Габора. Гистограммы берутся, чтобы не учитывать пространственную составляющую.


                              Объяснение, почему берутся низкоуровневые фильтры, приводится следующее:


                              1. Получается лучше обучить низкоуровневые сверточные слои за счет большего количества данных, а качество этих низкоуровневых фич определяет качество фич более высоких уровней.
                              2. Поиск похожих изображений по низкоуровневым фильтрам позволяет находить намного больше семплов для тренировки, т.к. семантика почти не учитывается.
                                Мне, если честно, эти объяснения не очень нравятся, но в статье так. Может я конечно что-то не понял или понял не так. Это все описано на 2 странице после слов "The motivation behind selecting images according to their low-level characteristics is two fold".

                              Еще из особенностей поиска близких изображений:


                              1. Гистограммы строятся так, чтобы в среднем по всему датасету в один бин попадало примерно одинаковое количество.
                              2. Расстояние между гистограммами считается с помошью KL-дивергенции.

                              Авторы попробовали разные сверточные слои AlexNet и фильтры Габора для поиска близких семплов, лучше всего получилось если использовать 1+2 сверточные слои из AlexNet.


                              Также авторы предложили итеративный способ подбора количества похожих семплов из датасета S для каджого семпла из T. Изначально берем некоторое заданое число ближайших соседей для каждого отдельного семпла из T. Затем прогоняем обучение, и если ошибка для семпла большая, то увеличиваем количество ближайших соседей для этого семпла. Как именно производится увеличение ближайших соседей понятно из уравнения 6.


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


                              Проведены эксперименты на следующих датасетах: Stanford Dogs 120, Oxford Flowers 102, Caltech 256, MIT Indoor 67. На всех датасетах получены SOTA результаты. Получилось поднять точность классфикации от 2 до 10% в зависимости от датасета.


                              12. Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks


                              Оригинал статьи
                              Код
                              Автор: repyevsky{at}gmail{dot}com
                              Статья про мета-обучение: авторы хотят научить модель объединять свой предыдущий опыт с малым количеством новой информации для решения новых заданий из некоторого общего класса.


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


                              В качество бенчмарка для классификации используются два датасета: Omniglot и miniImagenet. В первом рукописные буквы из нескольких алфавитов — всего около 1600 классов, 20 примеров на класс. Во втором 100 классов из Imagenet — по 600 картинок на класс. Ещё есть раздел про RL, но его я не смотрел.


                              Перед обучением все классы разбиваются на непересекающиеся множества train, validation и test. Для проверки, из test-классов (которые модель не видела при обучении) выбирается, например, 5 случайных классов (5-way learning). Для каждого из выбранных классов сэмплится несколько примеров, лейблы кодируются one-hot вектором длины 5. Дальше примеры для каждого класса делятся на две части A и B. Примеры из A показываются модели с ответами, а примеры из B используются для проверки точности классификации. Так формируется задание. Авторы смотрят на accuracy.


                              Таким образом, нужно научить модель адаптироваться к новому заданию (новому набору классов) за несколько итераций/новых примеров.


                              В отличии от предыдущих работ, где для этого пытались использовать RNN или feature embedding с непараметрическими методами на тесте (вроде k-ближайших соседей), авторы предлагают подход, позволяющий настроить параметры любой стандартной модели, если она обучается градиентными методами.


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


                              Суть в следующем. Пусть мы хотим, чтобы наша модель F(x, p) обучалась новому заданию за 1 итерацию (1-shot learning). Тогда для обучения нужно из тренировочных классов подготовить такие же задания как на тесте. Дальше на примерах из части A мы считаем loss, его градиент и делаем одну итерацию обучения — в итоге получаем промежуточные обновленные веса p' = p - a*grad и новую версию модели — F(x, p'). Считаем loss для F(x, p') на B и минимизируем его относительно исходных весов p. Получаем настоящие новые веса — конец итерации. Когда считается градиент от градиента :xzibit:, появляются вторые производные.


                              На самом деле, генерируется сразу несколько заданий, объединеных в metabatch. Для каждого находится свой p' и считается свой loss. Потом все эти loss суммируются в total_loss, который уже минимизируется относительно p.


                              Авторы применили свой подход к базовым моделям из предыдущих работ (маленькие сверточная и полносвязная сети) и получили SOTA на обоих датасетах.


                              При этом, итоговая модель получается без дополнительных параметров для мета-обучения. Зато используется большое количество вычислений, в том числе из-за вторых производных. Авторы пробовали отбросить вторые производные на miniImagenet. При этом accuracy осталась почти такой же, а вычисления ускорились на 33%. Предположительно это связано с тем, что ReLU — кусочно-линейная функция и вторая производная у неё почти всегда нулевая.


                              Код авторов на Tensorflow: https://github.com/cbfinn/maml. Там внутренний градиентый шаг делается вручную, а внешний с помощью AdamOptimizer.


                              За редактуру спасибо yuli_semenova.

                              Original source: habrahabr.ru (comments, light).

                              https://habrahabr.ru/post/336624/



                              Поиск сообщений в rss_rss_hh_new
                              Страницы: 1437 ... 1144 1143 [1142] 1141 1140 ..
                              .. 1 Календарь