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

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

2014-07-17

Safe way to setup firewall

В сети можно найти массу инструкций по правильной настройке файрволла (говоря «файрволл» я подразумеваю интерфейс iptables в Linux). Но надо довольно долго искать, прежде чем найдется практически полезное руководство. В частности, как настроить файрволл на удаленной машине и не потерять коннект? Что будет, если вы подключились по SSH к станции, до которой три года на оленях и, настраивая файрволл, случайно зарубили порт 22?
Ага, то-то.

Предлагаю вашему вниманию инструкцию по безопасной настройке файрволла.

Сначала описание алгоритма действий:
1. create script for disabling firewall (disable_fw.sh)
2. add disable_fw.sh to crontab for run every 5 minutes
3. check if it's working
4. write iptables rules, test config
5. save rules to file
6. create startup script (e.g. /etc/rc.local) for loading rules
7. remove disable_fw.sh from crontab

Для дистров на базе RedHat все несколько упрощается, ибо старт/стоп файрволла там оформлен в виде службы iptables и настроечных файлов в /etc/sysconfig

Итак, скрипт для отключения файрволла
#!/bin/bash
# disable_fw.sh - Reset (disable) firewall
# ---------------------------------------------------------------------------------------------------------------
# Initially Written by Vivek Gite <vivek@nixcraft.com>
# Rewrited by Valentin Fedulov <vasnake@gmail.com>
# Source: http://www.cyberciti.biz/faq/turn-on-turn-off-firewall-in-linux/
#         https://gist.github.com/vasnake/de19b6162ed97b0fd92b
# ---------------------------------------------------------------------------------------------------------------
# You can copy / paste / redistribute this script under GPL version 2.0 or above
# =============================================================

# set to true if it is CentOS / RHEL / Fedora box
RHEL=false

### no need to edit below  ###

IPT=/sbin/iptables
IPT6=/sbin/ip6tables

main() {
    if [ "$RHEL" == "true" ];
    then
        # reset firewall using redhat script
        /etc/init.d/iptables stop
        /etc/init.d/ip6tables stop
    else
        # for all other Linux distro use following rules to reset firewall
        reset_iptables ${IPT} "/proc/net/ip_tables_names"
        reset_iptables ${IPT6} "/proc/net/ip6_tables_names"
    fi
}

reset_iptables() {
    local ipt_bin="${1}"
    local tables="${2}"

    $ipt_bin -P INPUT ACCEPT
    $ipt_bin -P OUTPUT ACCEPT
    $ipt_bin -P FORWARD ACCEPT
    $ipt_bin -F
    $ipt_bin -X
    $ipt_bin -Z

    for table in $(<$tables)
    do
        $ipt_bin -t $table -F
        $ipt_bin -t $table -X
        $ipt_bin -t $table -Z
    done
}

main

Теперь добавить скрипт в кронтаб для срабатывания каждые 5 минут
chmod +x /root/disable_fw.sh
nano /etc/crontab

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
*/5  *  *  *  * root /root/disable_fw.sh

Проверить, как работает предохранитель. Для этого создать какое-нибудь разрешительное правило
iptables -A INPUT -p tcp --dport ssh -j ACCEPT
и посмотреть, как оно исчезнет меньше чем через 5 минут
watch -d "iptables -L --line-numbers -nv"
Кстати, для IPv6 все почти также, только команда «ip6tables».

Теперь, когда мы убедились в работоспособности предохранителя, можно заняться составлением правил для файрволла и не бояться накосячить при этом. Правила лучше сразу писать в виде скрипта или файла в формате iptables-save/iptables-restore.
Если вдруг случится косяк, надо просто подождать 5 минут и все порты опять будут открыты.

После отладки лично у меня получился такой файл
/etc/sysconfig/iptables

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m recent --update --seconds 15 -j DROP
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m recent --set -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
Сравните с версией для IPv6
/etc/sysconfig/ip6tables

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p ipv6-icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m recent --update --seconds 15 -j DROP
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m recent --set -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited
COMMIT


В случае с CentOS или другим РедХатовским дистром, имея показанные файлы, делать больше ничего и не надо, эти правила загружаются при старте служб
iptables, ip6tables.
В других дистрах надо любым доступным способом (хоть в /etc/rc.local) прописать загрузку правил, типа
iptables-restore < /root/working.iptables.rules
предварительно сохранив рабочий набор правил
iptables-save > /root/working.iptables.rules

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

Дополнительная информация:
выключить/включить службу файрволла в РедХатских дистрах
chkconfig iptables off
chkconfig iptables on
Нечто вроде визарда/мастера по первичной настройке правил
system-config-firewall-tui
Полезные сцылки



original post http://vasnake.blogspot.com/2014/07/safe-way-to-setup-firewall.html

2014-07-16

PEP 20

У Python есть свой Дзен:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!


Как это применять на практике?


А дальше сами https://www.google.ru/search?q=pep20


original post http://vasnake.blogspot.com/2014/07/pep-20.html

2014-07-15

Фантомы / Shutter 2008

Третьего дня отсмотрел фильму «Фантомы», что в оригинале Shutter (2008).
Типа, мистический триллер, про то, как успешный фотограф и его новая (от слова «вчера поженились») жена не могут сделать ни одной толковой фотографии. На всех фотках проявляется какая-то мутная фигня.
Жена думает, это душа той чудачки, которую она сбила машиной. Но всё гораздо хуже.

А потом начинают умирать друзья мужа...

Я вообще триллеры не люблю, мне бы экшн, фантастику или детектив. А лучше, все вместе. И этот триллер не стал исключением, что там смотреть, удары скучные, защита не интересная?


Так себе, ничего особенного.


original post http://vasnake.blogspot.com/2014/07/shutter-2008.html

2014-07-14

Logging ProjectMate

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

Тогда клиент обратился ко мне. И вместе мы придумали простое решение проблемы — записывать изменения на уровне базы данных.

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

Подробнее можно почитать в тут: https://github.com/vasnake/pmate-log/blob/master/readme.pdf

А остальные подробности и код можно взять тут: ttps://github.com/vasnake/pmate-log

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

Решение должно работать практически в любой БД MS SQL и не только с ПрожектМейтом.



original post http://vasnake.blogspot.com/2014/07/logging-projectmate.html

2014-07-11

Recommender Systems


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

Что мы знаем про Recommender Systems.

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

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

К такой проблеме есть два подхода. Один называется Content-based recommender systems. Другой – Collaborative filtering.

Content-based reccomender systems так называются потому, что у нас есть информация о фильмах — фичи, свойства фильмов. Например — жанровая направленность.

Итак, у нас есть данные — фичи фильмов, имеющиеся рейтинговые оценки пользователей. Надо уметь предсказывать рейтинг фильмы i для пользователя j.

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

Другой подход называется Collaborative filtering. Это потому, что у нас есть только значения рейтингов, проставленных разными пользователями для разных фильмов. Алгоритм самостоятельно определит фичи фильмов, наиболее точно отвечающие показаниям рейтингов.

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

Поняв про прямое и обратное вычисление мы переходим к сути — у нас есть только рейтинги. Чтобы хоть с чего-то начать, мы произвольно выбираем Тета, находим фичи Х и считаем рейтинг. Потом, минимизируя ошибку считаем новую Тета и считаем рейтинг. И опять, минимизируя ошибку считаем фичи Х, … до схождения. Это и есть алгоритм Collaborative Filtering.

Итак, у нас есть проблема курицы и яйца

Но мы можем решить ее в один заход

Такая Cost Function позволяет нам одновременно найти оптимальные параметры Тета и фичи Х.

Так, алгоритм Collaborative Filtering в целом следующий

Предварительная инициализация Х и Тета произвольными малыми значениями; минимизация Cost Function; вычисление рейтинга перемножением Тета и Х.

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

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

А что же делать, если пользователь не поставил еще ни одной оценки? В таком случае мы считаем его среднестатистическим пользователем и нормализуем оценки по среднему значению  

Если же у фильма нет еще ни одной оценки, лучше убрать этот фильм из расчетов.


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


original post http://vasnake.blogspot.com/2014/07/recommender-systems.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) Manager (15) web-browser (15) Никонов (15) Klaipeda (14) 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) 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) serialization (1) spatial (1) tie (1) vim (1) Науру (1) крысы (1) налоги (1) пианино (1)