• Применение RFM-анализа в сегментировании клиентской базы

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



      Специально для хабраблога компании Unisender мы подготовили цикл материалов «Таргетинг и сегментация email-рассылок». Во второй статье мы переходим к рассмотрению конкретных методик сегментации и расскажем о применении RFM-анализа в сегментации клиентской базы.

      Читать дальше →
      • +16
      • 52.9k
      • 7
    • Устранение утечек памяти в приложении на Питоне

        imageНедавно мне довелось разобраться и устранить несколько утечек памяти в популярном фреймворке Торнадо. Не беда, если вы никогда его не использовали, потому что описанное будет мало связано с ним. Рассказать я хочу о методах, которые я использовал для поиска и устранения утечек.

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

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

        Формально, циклические ссылки нельзя назвать утечками: сборка мусора рано или поздно уничтожит такие объекты. Беда только в том, что Питон не может сам определить, когда еще рано, а когда уже поздно. В моем случае система просто прибивала процесс с Питоном, если сборка мусора не начиналась вовремя.
        Читать дальше →
        • +92
        • 35.7k
        • 8
      • Разработка и отладка приложений для Android Wear

        • Translation
        Носимые устройства – это передний край сегодняшних информационных технологий. Это – мощный тренд. Самые популярные «носимые компьютеры» работают под управлением ОС Android Wear от Google. Она не так уж сильно отличается от того Android’а, который знаком огромному количеству разработчиков. Как результат, любой из этих разработчиков может без особых сложностей начать создавать приложения для Android Wear и претендовать на свою долю внимания от весьма перспективного рынка «носимых приложений».



        В этой статье мы поговорим об ОС Android Wear, обратив особое внимание на устройства, работающие под её управлением, на типы приложений, на их разработку и отладку. В частности, рассмотрим два способа отладки с использованием ADB.
        Читать дальше →
        • +12
        • 14.6k
        • 3
      • Нейросеть в 11 строчек на Python

        • Translation

        О чём статья


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

        Дайте код!


        X = np.array([ [0,0,1],[0,1,1],[1,0,1],[1,1,1] ])
        y = np.array([[0,1,1,0]]).T
        syn0 = 2*np.random.random((3,4)) - 1
        syn1 = 2*np.random.random((4,1)) - 1
        for j in xrange(60000):
            l1 = 1/(1+np.exp(-(np.dot(X,syn0))))
            l2 = 1/(1+np.exp(-(np.dot(l1,syn1))))
            l2_delta = (y - l2)*(l2*(1-l2))
            l1_delta = l2_delta.dot(syn1.T) * (l1 * (1-l1))
            syn1 += l1.T.dot(l2_delta)
            syn0 += X.T.dot(l1_delta)
        


        Слишком сжато? Давайте разобьём его на более простые части.
        Читать дальше →
      • 3G Модем и MikroTik

          Все началось с того, что дома пропал интернет. У меня подключены два проводных оператора и оба стали недоступны. Позже оказалось, что в соседнем доме выключили электричество. Поскучав час другой без интернета, я вспомнил о 3G модеме ZTE MF112. Подключил к компьютеру, но этого было мало, хотелось еще и рабочий Wi-Fi в квартире. По этой причине я его подключил к своему MikroTik RouterBoard 951g-2hnd. Вот об этом я и расскажу.
          image
          Читать дальше →
        • Домашний интернет: маршрутизация двух (и боле) провайдеров на основе Bird Routing Daemon

          Наверное, многие пользователи домашнего интернета сталкивались с тем, как распараллелить два и более интернет-канала в домашней сети.
          Эта проблему можно решить и хардварно (используя любое дешевое либо дорогое оборудование) и софтверно.
          Какую же модель маршрутизации выбрать? Сразу можно отбросить RIP/OSPF/BGP, так как это домашний интернет и больше чем уверен (в моем случае и проверено), что вам не захотят делать поддержку на стороне провайдера бесплатно.
          Остановил выбор на bird.

          Итак, исходная позиция:
          • Домашний раутер с Debian GNU/Linux 6.0.5 (squeeze) на борту
          • 2 интернет канала (ISP1 и ISP2)
          • 2 прямые руки
          • чашка кофе

          Читать дальше →
        • Загрузка Linux с корнем на RAID

          Для того, чтобы загрузить ядро linux с корневой файловой системой лежащей на RAID-массиве нужно передать ядру следующие параметры (рабочий пример для Grub). Значимыми для нас опциями являются первая и вторая строка параметров.
          title Gentoo Linux 3.0.8 Hardened
          kernel (hd0,0)/linux-3.0.8-hardened/linux \
               root=/dev/md0 \
               md=0,/dev/sda1,/dev/sdc1 \
               rootfstype=ext4 \
               rootflags=nodelalloc,data=ordered,journal_checksum,barrier=1,acl,user_xattr \
               panic=15 \
               vga=792

          Значения параметров:
          1. root=/dev/md0 задает имя файла устройства с корневой ФС.
          2. md=0,/dev/sda1,/dev/sdc1
          На этом параметре хотелось бы остановиться подробнее. Он имеет следующий формат:
          md=md_device_number,raid_level,chunk_size_factor,fault_level,dev0,dev1,...,devn

          • md_device_number — номер md-устройства. Например, 0 означает /dev/md0, 1 это /dev/md1. Прошу обратить внимание — это именно НОМЕР устройства, а не количество дисков входящих в массив, как иногда встречается в описаниях в Сети.
          • raid_level — уровень RAID. Является обязательным для линейного режима (значение -1) и RAID-0 (значение 0). Для остальных типов массивов информация берётся из суперблока и это значение должно быть опущено.
          • chunk_size_factor — задает размер чанка. Минимальное значение 4кб (4k).
          • fault_level — насколько я понял из документации, этот параметр игнорируется драйвером MD (нафига тогда предусматривали?)
          • dev0,...,devn — список устройств, входящих в массив.

          Есть еще один важный момент.
          Читать дальше →
        • Введение в оптимизацию. Имитация отжига

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

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

          image


          Читать дальше →
        • Machine Learning. Курс от Яндекса для тех, кто хочет провести новогодние каникулы с пользой

          • Tutorial
          Новогодние каникулы – хорошее время не только для отдыха, но и для самообразования. Можно отвлечься от повседневных задач и посвятить несколько дней тому, чтобы научиться чему-нибудь новому, что будет помогать вам весь год (а может и не один). Поэтому мы решили в эти выходные опубликовать серию постов с лекциями курсов первого семестра Школы анализа данных.

          Сегодня — о самом важном. Современный анализ данных без него представить невозможно. В рамках курса рассматриваются основные задачи обучения по прецедентам: классификация, кластеризация, регрессия, понижение размерности. Изучаются методы их решения, как классические, так и новые, созданные за последние 10–15 лет. Упор делается на глубокое понимание математических основ, взаимосвязей, достоинств и ограничений рассматриваемых методов. Отдельные теоремы приводятся с доказательствами.



          Читает курс лекций Константин Вячеславович Воронцов, старший научный сотрудник Вычислительного центра РАН. Заместитель директора по науке ЗАО «Форексис». Заместитель заведующего кафедрой «Интеллектуальные системы» ФУПМ МФТИ. Доцент кафедры «Математические методы прогнозирования» ВМиК МГУ. Эксперт компании «Яндекс». Доктор физико-математических наук.
          Содержание и видео всех лекций курса
        • Распознаем штрихкоды на изображениях с помощью Python и OpenCV

          • Translation
          От переводчика: мы в компании Энтерра очень любим алгоритмы компьютерного зрения. Работаем чаще всего с OpenCv. Время от времени нам пишут разные разработчики с вопросами: «А как лучше начать работать с OpenCv?» или «Какую интересную задачу можно просто решить с помощью OpenCv?» В связи с чем мы решили перевести очень хорошую статью, которая будет полезна всем, кто интересуется компьютерным зрением.



          Черная Пятница близко.

          Толпы злых покупателей. Рой одинаковых теток среднего возраста, готовых сожрать практически всё, что угодно, в ближайшем супермаркете — главное, что со скидкой 75%. Они выстроятся в очереди перед дверьми магазинов в полночь Дня благодарения. Они будут ломиться внутрь, стучать в запертые двери кулаками и головами, пока не сплющат друг друга и не разобьют руки в кровь, став похожими на зомби из «28 дней спустя». Но вместо человеческой плоти, они жаждут удовлетворить инстинкт покупателя. Их боевые кличи о скидках и распродажах достигают небес. А их громовая поступь способна привести к землетрясению на Великой Равнине.

          Естественно, от СМИ помощи не жди — они будут смаковать каждую подробность. От обмороженных семейств, ночевавших в палатке на морозе, до старой леди, растоптанной охотниками за скидкой в момент, когда открылись двери. Что-то похожее случилось с галлимимусом в «Парке Юрского периода». А она просто хотела купить Halo для девятилетнего внука Тимми, чьи родители забыли это сделать в прошлом году. В Wal-Mart. Во время Черной Пятницы.

          И я обязан спросить: весь этот хаос и бедлам стоят того?

          Чёрт возьми, нет!

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

          Просто представьте, как глупо вы будете выглядеть, стоя в очереди в ожидании свободной кассы – только для того, чтобы после сканирования штрихкода последнего сезона «Игры Престолов» выяснить, что в Target его можно купить на 5 долларов дешевле?

          Собственно, далее я покажу, как можно обнаружить штрихкод на изображении, используя только Python и OpenCV.
          Читать дальше →
        • Реверс-инжениринг драйверов USB-устройств на примере машинки на радиоуправлении

            Перевод статьи DRIVE IT YOURSELF: USB CAR

            image

            Один из аргументов любителей Windows перед любителями Linux – недостаток драйверов для оборудования под эту ОС. С течением времени ситуация выправляется. Сейчас она уже гораздо лучше, чем 10 лет назад. Но иногда можно встретить какое-то устройство, которое не распознаётся вашим любимым дистрибутивом. Обычно это будет какая-нибудь USB-периферия.

            Красота свободного софта в том, что эту проблему можно решить самостоятельно (если вы программист). Конечно, всё зависит от сложности оборудования. С трёхмерной веб-камерой у вас может и не получится – зато многие USB-устройства довольно просты, и вам не придётся нырять в глубины ядра или закапываться в С. В этом уроке мы с вами при помощи Python по шагам изготовим драйвер к игрушечной радиоуправляемой машинке.

            Процесс по сути будет реверс-инженирингом. Сначала мы подробно изучим устройство, затем сохраним данные, которыми оно обменивается с драйвером в Windows, и попытаемся понять, что они означают. Для нетривиальных протоколов вам может потребоваться как опыт, так и удача.
            Читать дальше →
          • Настройка и понимание Bacula

              Иногда проснувшись утром отчетливо понимаешь — что то не так. Хотя ты побрился и даже ни разу не порезался, кофе не выкипел, на улице солнечное утро, добрался до работы быстро и без приключений, вроде бы все хорошо, а все равно что то не так. Но войдя в офис ты видишь общую панику, истеричные вопли, о том, что все пропало и «весь офисный планктон» умрет, а ты находишься во главе тех кто погибнет.
              Оказывается ночью отказали файловый и почтовый серверы. И тут понимаешь, что не с проста утро началось так хорошо. Работы предстоит достаточно, но данные надежно сохранены, ибо ты позаботился об их резервном копировании.
              Читать дальше →
            • Верстка email рассылок от А до Я для чайников

              Уже 3 с лишним года занимаюсь дизайном и версткой почтовых рассылок, которые ориентированы на англоязычных пользователей. За время работы перелопатили огромную кучу информации, перепробовали много вариантов верстки, набили достаточное количество шишек. Были найдены и исправлены типичные баги, которые в той или иной мере повторялись во всех почтовых клиентах. Также нашлись проблемы с некоторыми CSS свойствами — различные почтовые клиенты интерпретировали их по разному. Каждое письмо тестировалось на самых популярных почтовых клиентах: Gmail, Outlook, Yahoo, Android, iOS, MozillaThunderbird, Microsoft Outlook, The Bat. Рассылки ходят на сотни миллионов пользователей и приносят очень хорошие результаты. Итак, приступим к изучению.
              Читать дальше →
            • Рисуем знак рубля в Android приложении

              • Tutorial
              В последнее время перед разработчиками все чаще ставится задача использовать символ рубля в тексте. Однако, символ рубля был утвержден относительно недавно, символ получил свой код в стандате Unicode еще позже. Естественно, гарнитура Roboto на текущих платформах еще не содержит знака рубля.
              Читать дальше →
            • Дюжина дизайнерских косяков



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

                Спустя время я выделил несколько неочевидных вещей, на которые старался обращать внимание, и в большинстве случаев находил ошибки. Получился небольшой чеклист. Очень полезный как для самопроверки, так и для проверки чужого дизайна. Им с вами и спешу поделиться:
                Читать дальше →
              • Несколько интересных особенностей MySQL

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

                  Начнем с такого интересного типа, как ENUM.

                  mysql> CREATE TABLE enums(a ENUM('c', 'a', 'b'), b INT, KEY(a));
                  Query OK, 0 rows affected (0.36 sec)
                  
                  mysql> INSERT INTO enums VALUES('a', 1), ('b', 1), ('c', 1);
                  Query OK, 3 rows affected (0.05 sec)
                  Records: 3  Duplicates: 0  Warnings: 0
                  


                  Итак, у нас есть таблица, в ней есть два столбца. У первого, a, тип ENUM, у второго, b, INT. В таблице три строки, у всех трех значение b равно 1. Интересно, чему равны минимальный и максимальный элементы в столбце a?

                  mysql> SELECT MIN(a), MAX(a) FROM enums;
                  +--------+--------+
                  | MIN(a) | MAX(a) |
                  +--------+--------+
                  | c      | b      |
                  +--------+--------+
                  1 row in set (0.00 sec)
                  


                  Кажется странным, было бы разумно, если бы самым маленьким был 'a', а самым большим — 'c'.
                  А что если выбрать минимум и максимум только среди тех строк, где b = 1? То есть, среди всех строк?

                  mysql> SELECT MIN(a), MAX(a) FROM enums WHERE b = 1;
                  +--------+--------+
                  | MIN(a) | MAX(a) |
                  +--------+--------+
                  | a      | c      |
                  +--------+--------+
                  1 row in set (0.00 sec)
                  


                  Вот так мы заставили MySQL поменять свое мнение о том, как сравнивать поля в ENUM, просто добавив предикат.
                  Разгадка такого поведения заключается в том, что в первом случае MySQL использует индекс, а во втором нет. Это, конечно, не объясняет, почему MySQL сравнивает ENUMы по разному для сортировки в индексе, и при обычном сравнении.

                  Второй пример проще и лаконичнее:

                  mysql> (SELECT * FROM moo LIMIT 1) LIMIT 2;
                  +------+
                  | a    |
                  +------+
                  |    1 |
                  |    2 |
                  +------+
                  2 rows in set (0.00 sec)
                  


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

                  Интересно, что далеко не любой SELECT в скобках сработает, в частности, UNION в скобках — это синтаксическая ошибка:

                  mysql> (SELECT * FROM moo UNION ALL SELECT * FROM hru) LIMIT 2;
                  ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION ALL SELECT * FROM hru) LIMIT 2' at line 1
                  


                  Еще несколько интересных примеров под катом
                  Читать дальше →
                • Как собрать бинарный deb пакет: подробное HowTo

                    Сегодня я расскажу на абстрактном примере как правильно создать *.deb пакет для Ubuntu/Debian. Пакет мы будем делать бинарный. Пакеты, компилирующие бинарники из исходников здесь не рассматриваются: осилив изложенные ниже знания, в дальнейшем по готовым примерам можно понять суть и действовать по аналогии :)

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

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

                    Для тех, кто не хочет вдаваться в мощную систему установки софта в Linux, рекомендую посетить сайт проги CheckInstall: она автоматически создаёт deb-пакет из команды «make install» ;) А мы вместе с любопытными —
                    поехали дальше!
                  • Современный торнадо, часть 2: блокирующие операции

                    • Tutorial
                    Улучшаем наш распределённый хостинг картинок. В этой части мы поговорим о конфигурировании приложения и подключим защиту от csrf. Затем, на примере создания миниатюр картинок, научимся работать с блокирующими задачами, запускать корутины параллельно и обрабатывать возникающие в них исключения.
                    Читать дальше →
                    • +30
                    • 15.5k
                    • 8
                  • OpenLayers или делаем сервис мониторинга транспорта

                      Сейчас на рынке много предложений по продаже мобильных устройств, предназначенных для контроля движущихся объектов или трекеров. В большинстве из них есть функция передачи информации по GPRS на любой заданный веб-адрес через определенный интервал времени. Чаще всего формат передачи данных разный. Поэтому мы не будем рассматривать вопрос загрузки данных с трекера в базу. Предположим данные есть и мы хотим приступить к созданию сервиса мониторинга транспорта. Основу такой системы образуют возможности:
                      -выбор карты и ее отображение
                      -отображение точки или картинки и подписи к ней
                      -отображение полигона и его редактирование
                      -отображение линии и ее редактирование
                      -отображение информации связной с полигонами, линиями, точками (всплывающие подсказки)
                      -немного математики (подсчет пройденного пути, площадь полигона, принадлежность точки полигону)
                      Все эти функции легко реализовать с помощью OpenLayers, библиотеки на JavaScript.

                      Читать дальше →
                    • Deploy с помощью Salt


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

                        Чего обычно хочется:
                        • Возможность поднять проект локально на машине разработчика. Весь или хотя бы частями. Причем очень хочется, чтобы Dev конфигурация отличалась от Prod в минимуме параметров. Это позволит избежать “work on my machine” багов. Да и вообще, когда один разработчик работает на OS X, другой на Windows, а продакшен на Debian, то жди беды, это не считая того, что каждый делает работу по настройке окружения.
                        • Dev конфигурацию хочется разворачивать на любой машине и ОС в пару команд в консоли. Это опять же позволит уменьшить фактор “work on my machine” багов. А еще позволит привлекать других разработчиков в проект за минимальное время (vagrant up и поехали).
                        • Конфигурация должна быть понятна и программисту, и админу.

                        Всего этого мы добьемся на связке Salt + Vagrant на примере Django проекта. Но большинство техник будут полезны разработчикам не только на Python, но на других языках.
                        Читать дальше →