Записки программиста, обо всем и ни о чем. Но, наверное, больше профессионального.

2014-08-05

Getting Lots of Data and Artificial Data


Получилось так, что мое изложение материала последней, 10-ой недели обучения Machine Learning (тема «Large-scale Machine Learning») растянулось аж на четыре статьи. Stochastic Gradient Descent, Map-Reduce, Photo OCR app Example и эта, Getting Lots of Data and Artificial Data + Ceiling Analysis.

Сделав оговорку, что нам не всегда нужны огромные датасеты, можно сказать, что
low biased learning algorithm + masive training set может привести к успеху предприятия.

Есть два подхода к получению больших датасетов:
* генерация данных в дополнение к сбору (расширяя собранные данные);
* генерация данных с нуля.

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

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

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

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


Ceiling Analysis: What Part of the Pipeline to Work on Next
Самый ценный ресурс — это наше разработческое время. тратить его надо только на то, что принесет явную пользу. Очень плохо, когда мы тратим недели, месяцы на разработку направления, которое по итогам не даст серьезного улучшения в решении задачи.
Профессор Эндрю знает историю, когда два инженера работали полтора года над удалением фона с картинок (задача была – распознавание лиц или вроде того), сделали офигенную работу и опубликовали научный труд. Но для их задачи этот модуль был не важен, как оказалось. Увы.

Вопрос можно поставить так: на чем сконцентрироваться? Какая часть pipeline, в случае ее улучшения, даст максимальный эффект?
Тут появляется методика Ceiling Analysis.

Для начала нам нужна числовая метрика (например accuracy) для всей системы.
Теперь мы по очереди, один за одним имитируем достижение 100% точности каждого блока pipeline. И замеряем точность всей системы. Какой блок дает наибольший вклад в увеличение точности всей системы, тот блок и надо совершенствовать в первую очередь.


That's all Folks!


original post http://vasnake.blogspot.com/2014/08/getting-lots-of-data-and-artificial-data.html

2014-08-04

Machine Learning Example Application

Продолжим.
Две предыдущие статьи (раз, два) содержат начало и продолжение рассказа о 10-ой неделе обучения (https://www.coursera.org/course/ml), тема «Large-scale Machine Learning». Были рассмотрены темы: Stochastic Gradient Descent, Mini-batch Gradient Descen, Online Learning, Map-Reduce and Data Parallelism.

Завершилась 10-я неделя обучения (и курс в целом) рассказом о построении комплексного приложения, использующего техники Machine Learning.
Приложение «Photo OCR» должно находить на фотографиях надписи и превращать их в текст.

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

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

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

В нашем Photo OCR пайплайн будет такой: Image → Text Detection → Character Segmentation → Character Recognition.

Задача Text Detection может быть решена применением техники известной как Sliding window classifier.

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

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

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

Так вот, с текстом практически также, только вместо пешеходов — буквы.

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

На такую картинку мы натравливаем Expansion Operator. Этот оператор работает так: для каждого пикселя он смотрит, нет ли в его окрестности белого пикселя, если есть, данный пиксель тоже окрашивается белым. Так мы получаем эффект размытия, что дает нам вместо отдельных букв границы надписей. Мы находим регионы с белым цветом и находим для них рамки/боксы. Далее убираем боксы с неправильным aspect ratio — обычно текст ширше чем выше. В результате получаем боксы/рамки для скармливания распознавателю текста.

Следующий этап в pipeline — это character segmentation.
Задача этого этапа: получив на вход изображения надписей (полученный на предыдущем шаге), найти пробелы между буквами. Лично я не очень понял, почему поиск пробелов между буквами проще/легче чем поиск самих букв.

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

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

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

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


original post http://vasnake.blogspot.com/2014/08/machine-learning-example-application.html

2014-08-01

Large-Scale Machine Learning & Example

Продолжим.
В предыдущей статье я начал рассказ о 10-ой неделе обучения, тема «Large-scale Machine Learning». Были рассмотрены темы: Stochastic Gradient Descent, Mini-batch Gradient Descen, Online Learning.

Как рассказывал профессор, есть два основных подхода к перевариванию больших датасетов:
Stochastic Gradient Descent и
Map Reduce (data parallelizm)

Посмотрим на Map Reduce and Data Parallelism.

В отличие от Stochastic Gradient Descent, который способен обрабатывать большие датасеты на одном вычислительном узле, техника Map-Reduce дает возможность задействовать много вычислителей. Данные делятся на порции, эти порции обрабатываются параллельно на разных процессорах/узлах и результаты обработки консолидируются.

Предположим, у нас есть четыре машины и мы хотим, используя Batch Gradient Descent, найти оптимальные значения параметров модели. Допустим, датасет у нас состоит из 400 записей. Тогда первая машина будет считать сумму для записей 1-100, вторая 101-200, третья 201-300 и четвертая 301-400. Все эти суммы высчитываются параллельно. Схема понятна, так можно раскидать любое количество записей на любое количество узлов. Этот шаг называется «Map».
Финальный результат получается складыванием четырех значений, полученных с четырех вычислительных узлов. И этот шаг называется «Reduce». Просто, не правда ли.

Очень многие алгоритмы Machine Learning сводятся к вычислению сумм по набору данных — датасету. Если датасет огромен, вычисление сумм можно параллелить в технике Map-Reduce.

Кстати, используя многоядерные процессоры, можно получать выгоду от Map-reduce даже на одной машине.

Вот, собственно, и все, что нам рассказал профессор о Big Data применительно к Machine Learning.





original post http://vasnake.blogspot.com/2014/08/large-scale-machine-learning-example.html

2014-07-31

Large-Scale Machine Learning & Example


А потом начались нейросети — Neural Networks.
Потом нас учили правильно применять изученные алгоритмы (Advice for Applying Machine Learning).
А потом нам рассказали про Support Vector Machines (SVMs) и Kernels.
А потом была неделя посвященная темам Clustering (K-Means) и Dimensionality Reduction (PCA).
А после были рассмотрены алгоритмы систем Anomaly Detection и Recommender Systems.

А потом наступила последняя, 10-я неделя обучения, на которой кратенько были рассмотрены способы масштабирования задач ML — Large-scale Machine Learning и, более подробно, пример решения практической задачи с применением инструментов ML.

Итак, Large-scale Machine Learning.

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

В чем заключаются проблемы огромных датасетов? В том, что алгоритм будет слишком долго заниматься расчетами. К примеру, gradient descent итеративно (в смысле многократно) вычисляет суммы расчетов по всем записям датасета. А записей — миллионы и даже миллиарды. Это реально долго.

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

Как проверить — имеет ли смысл увеличение датасета? Просто. Использовать learning curves. Кривые обучения от размера датасета показывают оверфиттинг / high variance на малых датасетах? Значит увеличение датасета может помочь (а может и нет, надо и к этому быть готовым, увеличение датасета это не серебряная пуля).


Допустим, решено использовать огромный датасет.
Есть два основных подхода к перевариванию больших датасетов:
Stochastic Gradient Descent и
Map Reduce (data parallelizm)

Широко используемый в ML метод оптимизации (нахождение оптимума/минимума) Batch Gradient Descent становится неподъемным при обработке огромных датасетов. Вычислительно очень дорогим из-за необходимости крутить циклы вычислений по всем записям датасета.


Модификация BGD называется Stochastic Gradient Descent.
В этом алгоритме убираются циклы по записям и вместо них ставится вычисление по одной случайной записи датасета.

В итоге получается интересная картина. Вместо плавного продвижения к оптимуму наблюдается нервная пляска вокруг дороги к этому оптимуму.

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

Как много повторений внешнего цикла надо сделать? Это зависит от размера датасета и определяется сходимостью результата тета. Обычно хватает 1-10 повторений.

Компромиссом между Batch Gradient Descent и Stochastic Gradient Descent является Mini-batch Gradient Descent.
Мини-батч GD использует не все и не одну запись, он использует поднабор b (mini-batch size) записей датасета.

Хорошо векторизованная реализация мини-батч GD может обогнать по производительности стохастический GD.

Недостаток мини-батч GD в том, что у нас появляется еще один параметр b, надо уделять время на его подбор и проверку.

Stochastic Gradient Descent Convergence. А как подобрать learning rate альфа для стохастик GD? Как убедиться в безглючности стохастик GD? Сходится ли стохастик GD?
Для этого используем уже известную технику — рисование графика зависимости цены (ошибки) от количества итераций. Правильный график должен снижаться. В данном случае цена представляет собой среднее значение для последних, скажем, 1000 итераций.

Свойство стохастического GD (обработка по одной записи) используется в отдельном классе задач — Online Learning. Суть алгоритма решения таких задач в том, что мы имеем дело с потоком записей, обрабатываем их по мере поступления и выбрасываем, не сохраняем.

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




original post http://vasnake.blogspot.com/2014/07/large-scale-machine-learning-example.html

2014-07-30

Open Source vs Proprietary

Намедни меня попросили сделать рекламную сводку, на страничку текста, для начальников разных. По теме «чем открытый софт лучше закрытого» в рамках ГИС-решений для относительно крупных компаний.
Вот что у меня получилось.

Доводы «за» Open Source.

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

2. Опять же, нынче модно быть патриотом. А патриот не будет финансировать зарубежных производителей софта, когда есть возможность закупить всё необходимое внутри страны.

3. Использование открытых решений снимает потребителя с крючка привязки к вендору. Развивать и поддерживать комплекс, построенный на открытых протоколах, стандартах и спецификациях; открытом коде – может любой квалифицированный разработчик. Для обслуживания системы нет нужды приглашать специалиста из Редмонда, США.

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

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

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

7. При использовании открытых решений можно рассчитывать на то, что всегда есть альтернатива и часто не одна. Не устраивает эта DBMS, возьмем другую; корпоративный стандарт предписывает использовать другую OS? Не беда, решения кроссплатформенные. Большинство проприетарных продуктов не могут похвастаться такой гибкостью и способностью к замене компонент на альтернативные.

Доводы «против» Open Source.

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

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


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


original post http://vasnake.blogspot.com/2014/07/open-source-vs-proprietary.html

2014-07-29

webcamfixer

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

Вот работающий пример кода на Python, где в дереве каталогов (папок) ищутся файлы определенного типа (JPG), список найденного сортируется по времени модификации файлА, найденное файлО копируется куда заказано и, в качестве бонуса, на картинку ставится временной штамп, чтобы видно было, когда сделана фоточка.


---
вон там внизу справа - таймштамп.


original post http://vasnake.blogspot.com/2014/07/webcamfixer.html

2014-07-28

Import VirtualBox machine

Давеча я наступил на глупые грабли при воссоздании старой виртуальной машины VirtualBox.

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


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

В файле machinename.ovf я обнаружил дубль:
      <StorageControllers>
        <StorageController name="IDE Controller" type="PIIX3" PortCount="2" useHostIOCache="true">
          <AttachedDevice type="HardDisk" port="0" device="0">
            <Image uuid="{c8c7052e-926c-4419-93ac-46756167604f}"/>
          </AttachedDevice>
          <AttachedDevice type="HardDisk" port="0" device="1">
            <Image uuid="{c8c7052e-926c-4419-93ac-46756167604f}"/>
          </AttachedDevice>
          <AttachedDevice passthrough="false" type="DVD" port="1" device="0"/>
        </StorageController>
        <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true">
          <AttachedDevice type="Floppy" port="0" device="0"/>
        </StorageController>
      </StorageControllers>
Очевидно, сообразил я, это неправильно. Недолгий поиск uuid-ов в этом файле
  <DiskSection>
    <Info>List of the virtual disks used in the package</Info>
    <Disk ovf:capacity="10737418240" ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" vbox:uuid="2d8c0bbc-ed2a-424a-9cfa-e8e922eb42ac"/>
    <Disk ovf:capacity="107374182400" ovf:diskId="vmdisk2" ovf:fileRef="file2" ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" vbox:uuid="c8c7052e-926c-4419-93ac-46756167604f"/>
  </DiskSection>
и я смог сделать такой вариант:
      <StorageControllers>
        <StorageController name="IDE Controller" type="PIIX3" PortCount="2" useHostIOCache="true">
          <AttachedDevice type="HardDisk" port="0" device="0">
            <Image uuid="{c8c7052e-926c-4419-93ac-46756167604f}"/>
          </AttachedDevice>
          <AttachedDevice type="HardDisk" port="0" device="1">
            <Image uuid="{2d8c0bbc-ed2a-424a-9cfa-e8e922eb42ac}"/>
          </AttachedDevice>
          <AttachedDevice passthrough="false" type="DVD" port="1" device="0"/>
        </StorageController>
        <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true">
          <AttachedDevice type="Floppy" port="0" device="0"/>
        </StorageController>
      </StorageControllers>
В общем, это и есть решение проблемы. Осталось упомянуть, что после правки файла OVF, надо в контрольном файле machinename.mf заменить строку, содержащую SHA1 дайджест файла OVF, иначе импорт будет ругаться.


Если после импорта окажется, что диски перепутаны местами, их легко переставить, используя GUI управлятора VirtualBox.


original post http://vasnake.blogspot.com/2014/07/import-virtualbox-machine.html

2014-07-25

NLP

NLP это Natural Language Processing.

Точка зрения:

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

с продолжением

Зашел я на эту статью с https://plus.google.com/u/0/+VicNgrail/posts/FPqMTvqbvFK
где упоминается также sentiment analysis http://habrahabr.ru/post/149605/

Поскольку я теперь типа эксперт в ML, я не мог пройти мимо такого замечательного описания проблемы. Статья прекрасна, без дураков, стоит прочесть. Хочу только уточнить, что, хотя и есть весомая доля истины в процитированном отрывке, на самом деле ML это не последнее прибежище отчаявшегося data scientist, нет. Это инструмент, с которым надо уметь обращаться. В частности, когда мы выбираем «немного не те критерии» и «все идет по хуям», нужно не отчаиваться и не бегать с бубном а применить методики отладки алгоритмов обучения. Хотя да, выбор правильных фичей (features) для скармливания машине, это, наверное, самая нетривиальная задача из тех, что приходится решать. Но и тут есть довольно простые методы, ведущие если не к успеху, так хоть в его направлении.

Вот такая реклама курсов получилась :)




original post http://vasnake.blogspot.com/2014/07/nlp.html

2014-07-24

Duck Jibe

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

Про виндсерфинг.

Сева Шульгин снимает фильм про волны

Что любопытно, анонс я увидел у доктора

И там же нашел цынк на набор шуток юмора про серфингистов

Q: How do surfers clean themselves?
A: They wash up on shore!
Q: What detergent do surfers use to wash their wet suit?
A: Tide!
Q: How do people surfing say HI to each other?
A: They Wave!



Разворот Duck Jibe














original post http://vasnake.blogspot.com/2014/07/duck-jibe.html

2014-07-23

2.5 тонны

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

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

Я проверил, это единственное место в ПДД, где используется число 2.5 тонны вместо 3.5 для отделения грузовиков от легковушек. Во всех остальных случаях (их 5) разделителем классов служит 3.5 тонны.

Полагаю, это была опечатка, которую до сих пор никто не исправил.

Вообще, в наших ПДД постепенно становится все больше трудных для запоминания правил и, особенно, исключений. Вот, к примеру, знаки про поворот налево и разворот.
Знак 4.1.3 Движение налево — разрешает и разворот: «... разрешающие поворот налево, разрешают и разворот».

Знак 6.3.1 Место для разворота — запрещает поворот налево: «Поворот налево запрещается».

Лично мне неясно, зачем нагружать простой знак дополнительными неочевидными функциями — если поворот налево запрещен, поставь знак 3.18.2 «Поворот налево запрещен».

Зачем загружать голову нюансами, логика которых непонятна?

Или другой пример. Таблички 8.5.1 и 8.5.5 про «Субботние, воскресные и праздничные дни». Вроде понятно, красная снежинка — красный день календаря.


Но что делает красная снежинка на знаке 5.33 «Пешеходная зона»? Смущает неокрепшие умы?

Вот, вспомнил еще один жутко раздражающий пример: въезд на круговой перекресток и выезд с него. Везде в Правилах написано, что при повороте направо надо выруливать на самую правую полосу (при этом налево — на любую, о как). И только (единственное исключение!) при въезде на круговой перекресток можно полосу не менять. Вроде удобно. Авотхуй. Потому как при выезде с кругового необходимо полюбому перестроиться на самую правую полосу. Зачем? Зачем так усложнять? Или трусы наденьте или кресты снимите разрешите выезжать с кругового по той же полосе, что и въехал, или пусть въезжают на круговой уже на самую правую. Так безопаснее ехать и проще запомнить.

В целом, я полагаю, что хорошие ПДД должны быть простыми, логичными, короткими. Все тонкости и нюансы реализуются по месту (на дороге) с помощью табличек, знаков и разметки. Которые тоже должны быть простыми и однозначными.
А то придумали, понимаешь — сплошную пересекать нельзя, но если за ней обочина — то можно. Что за хуйня?
Простите, разгорячился :)


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


original post http://vasnake.blogspot.com/2014/07/25.html

2014-07-22

fb2tools

закончил оформление public версии инструментов обработки FB2 файлов. Кому интересно, зачем нужны эти струменты, читайте предисторию

Вкратце, пакет программ написан на Python 2 и содержит, помимо всякой мелочи, две основные функции:
1 – упаковка книг в грамотный архив fb2.zip книг fb2, с присвоением им имен по схеме «Автор — название книги».
2 – переименование файлов из «Автор — название книги.fb2.zip» в «название книги.fb2.zip», что имеет смысл после раскладывания книг по папкам с именами авторов.

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

В общем, учащимся есть на что посмотреть.


original post http://vasnake.blogspot.com/2014/07/fb2tools.html

2014-07-21

10 распространенных ошибок

На Топтале (toptal.com) есть подборка статей типа «10 наиболее распространенных ошибок у программеров на Х», где Х — некий язык программирования.
Нас, конечно, в первую очередь интересует Python

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

1. дефолтные значения аргументов
>>> def foo(bar=[]):        # bar is optional and defaults to [] if not specified
...    bar.append("baz")    # but this line could be problematic, as we'll see...
...    return bar
попробуйте вызвать функцию подряд несколько раз без параметра.
Фишка в том, что дефолтная переменная инициируется только один раз а не при каждом вызове.
Ну не знаю кто как, а нас учили, что писать во входные параметры — не православно. Посему на эти грабли я никогда не наступал.

2. переменные класса
>>> class A(object):
...     x = 1
...
>>> class B(A):
...     pass
...
>>> class C(A):
...     pass
...
>>> print A.x, B.x, C.x
1 1 1
>>> B.x = 2
>>> print A.x, B.x, C.x
1 2 1
>>> A.x = 3
>>> print A.x, B.x, C.x
3 2 3
What the $%#!&?? We only changed A.x. Why did C.x change too?
По моему тут всё очевидно, класс С наследует переменную от А. Опять же, нас учили использовать конструкторы при работе с классами, поэтому эти грабли тоже мне не знакомы.

3. параметры при отлове иксепшенов
>>> try:
...     l = ["a", "b"]
...     int(l[2])
... except ValueError, IndexError:  # To catch both exceptions, right?
...     pass
...
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
IndexError: list index out of range
чиста проблема с синтаксисом, см.документацию.
Правильный способ указать несколько отлавливаемых иксепшенов
>>> try:
...     l = ["a", "b"]
...     int(l[2])
... except (ValueError, IndexError) as e:  
...     pass
Должен признаться, грешен. Я, ленивая обезьяна, обычно отлавливаю одно наиболее общее исключение, хотя это и не православно. Зато работает. Грабли мимо.

4. запись в глобальные переменные
>>> x = 10
>>> def foo():
...     x += 1
...     print x
...
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'x' referenced before assignment
читать можно, писать уже не получается. Во первых, писать в глобальные переменные — mauvais ton, простите мой французский. Во вторых, учим матчасть, ключевое слово global. Обратно мимо.

5. перебирая список менять его
>>> numbers = [n for n in range(10)]
>>> for i in range(len(numbers)):
...     if odd(numbers[i]):
...         del numbers[i]  # BAD: Deleting item from a list while iterating over it
...
Traceback (most recent call last):
     File "<stdin>", line 2, in <module>
IndexError: list index out of range
Без комментариев. Что-то я начал раздражаться, что это за грабли они выкапывают?
Ну это вообще ни в какие ворота. Где они находят таких программистов? Руки за это отрывать сразу. Детский сад какой-то. Если это одна из наиболее частых ошибок программистов на Топтале, то не желаю иметь с ними никаких программистских дел.

6. позднее связывание
>>> def create_multipliers():
...     return [lambda x : i * x for i in range(5)]
>>> for multiplier in create_multipliers():
...     print multiplier(2)
...
You might expect the following output:
0
2
4
6
8

But you actually get:
8
8
8
8
8
На момент вызова лямбдоидов, переменная i уже посчитана и заново не высчитывается.
Как-то мне не попадались такие случаи. Можеть быть потому, что я лямбды не слишком уважаю? Опять же, зачем генерировать список, когда можно генерировать итератор?
Вообще, подтверждаю потенциальные грабли, увлекшись можно и наступить.

7. циклические зависимости в модулях
# In a.py:
import b
def f():
    return b.x
print f()

# And in b.py:
import a
x = 1
def g():
    print a.f()
Теоретически, такое случается. Если уж это произошло, следует разобраться с архитектурой, дизайном и прочей декомпозицией. Что-то тут не так. Надо переделать. А если переделывать лень, делайте импорт внутри функции, это спасет нерадивую обезьяну.
Не грабли это а грязный дизайн.

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

9. разница между Python 2 и Python 3
например, области видимости
import sys

def bar(i):
    if i == 1:
        raise KeyError(1)
    if i == 2:
        raise ValueError(2)

def bad():
    e = None
    try:
        bar(int(sys.argv[1]))
    except KeyError as e:
        print('key error')
    except ValueError as e:
        print('value error')
    print(e)

bad()
В Python 2 это работает как и ожидается. В третьем мы получим
UnboundLocalError: local variable 'e' referenced before assignment
Честно говоря, называть ошибками программиста то, что в Python 3 не работает код написанный для Python 2, это наглость. Но в данном конкретном случае мы наблюдаем опять нарушение гигиены. Для доступа к содержимому иксепшенов снаружи их блока необходимо сохранить значение во внешней переменной. И не называть ее тем же именем. Все таки, опыт написания программ на C/C++ сильно помогает не ходить по таким «граблям», поверьте. А лучше проверьте на себе.

10. порядок уничтожения объектов
import foo
class Bar(object):
        ...
    def __del__(self):
        foo.cleanup(self.myhandle)
при завершении интерпретатора он сначала зачистит глобальные объекты, поэтому foo.cleanup страшно обломается.
Теоретически, я могу представить себе ситуацию, когда в деструкторе надо вызвать внешний модуль. С другой стороны, нафига нужен деструктор, срабатывающий при закрытии интерпретатора? Все ресурсы будут освобождены по любому. В целом, настолько редкая ситуация, что мне ни разу не попадалась. Но, теоретически, может. Потенциальные грабли для меня №2.


Общий вывод: тесты, тесты и еще раз тесты. Не думайте, что вы знаете как работает ваша программа. Только тесты могут доказать, что работает она как задумано.


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


original post http://vasnake.blogspot.com/2014/07/10.html

2014-07-18

The Onion Movie 2008

Намедни отсмотрел фильму «Луковые новости», что в оригинале The Onion Movie (2008).
Эдакий забавный набор скетчей, с общим центром, приходящимся на студию теленовостей Onion News. По ходу фильмы происходит сатирическое осмеяние быта и нравов в США. Смешно.

Если кто любит незатейливый юмор — смотрите фильму на здоровье, не худший выбор.

А я смотрел кино из-за того, что в нем снялся Стивен Сигал.

А еще фильму хорошо отрекламировали на Тупичке http://oper.ru/news/read.php?t=1051613842



original post http://vasnake.blogspot.com/2014/07/the-onion-movie-2008.html

Архив блога

Ярлыки

linux (241) python (191) citation (186) web-develop (170) gov.ru (159) video (124) бытовуха (115) sysadm (100) GIS (97) Zope(Plone) (88) бурчалки (84) Book (83) programming (82) грабли (77) Fun (76) development (73) windsurfing (72) Microsoft (64) hiload (62) internet provider (57) opensource (57) security (57) опыт (55) movie (52) Wisdom (51) ML (47) driving (45) hardware (45) language (45) money (42) JS (41) curse (40) bigdata (39) DBMS (38) ArcGIS (34) history (31) PDA (30) howto (30) holyday (29) Google (27) Oracle (27) tourism (27) virtbox (27) health (26) vacation (24) AI (23) Autodesk (23) SQL (23) humor (23) Java (22) knowledge (22) translate (20) CSS (19) cheatsheet (19) hack (19) Apache (16) Klaipeda (15) Manager (15) web-browser (15) Никонов (15) functional programming (14) happiness (14) music (14) todo (14) PHP (13) course (13) scala (13) weapon (13) HTTP. Apache (12) SSH (12) frameworks (12) hero (12) im (12) settings (12) HTML (11) SciTE (11) USA (11) crypto (11) game (11) map (11) HTTPD (9) ODF (9) Photo (9) купи/продай (9) benchmark (8) documentation (8) 3D (7) CS (7) DNS (7) NoSQL (7) cloud (7) django (7) gun (7) matroska (7) telephony (7) Microsoft Office (6) VCS (6) bluetooth (6) pidgin (6) proxy (6) Donald Knuth (5) ETL (5) NVIDIA (5) Palanga (5) REST (5) bash (5) flash (5) keyboard (5) price (5) samba (5) CGI (4) LISP (4) RoR (4) cache (4) car (4) display (4) holywar (4) nginx (4) pistol (4) spark (4) xml (4) Лебедев (4) IDE (3) IE8 (3) J2EE (3) NTFS (3) RDP (3) holiday (3) mount (3) Гоблин (3) кухня (3) урюк (3) AMQP (2) Baltic (2) ERP (2) IE7 (2) NAS (2) Naudoc (2) PDF (2) address (2) air (2) british (2) coffee (2) fitness (2) font (2) ftp (2) fuckup (2) messaging (2) notify (2) sharepoint (2) ssl/tls (2) stardict (2) tests (2) tunnel (2) udev (2) APT (1) CRUD (1) Canyonlands (1) Cyprus (1) DVDShrink (1) Jabber (1) K9Copy (1) Matlab (1) Portugal (1) VBA (1) WD My Book (1) autoit (1) bike (1) cannabis (1) chat (1) concurrent (1) dbf (1) ext4 (1) idioten (1) join (1) krusader (1) license (1) life (1) migration (1) mindmap (1) navitel (1) pneumatic weapon (1) quiz (1) regexp (1) robot (1) science (1) seaside (1) serialization (1) shore (1) spatial (1) tie (1) vim (1) Науру (1) крысы (1) налоги (1) пианино (1)