EngineerSpock

Так ли важна математика для программистов?

Автор оригинального текста: Steve Yegge

Так ли важна математика для программистов?

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

Давайте я расскажу вам об этом.

Общепринятое мнение ни о чем не говорит

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

И знаете, что? Они абсолютно правы. Можно быть хорошим, замечательным профессиональным программистом, не зная математики.

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

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

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

Так что они правы: вам не нужна математика, и вы можете прекрасно жить и без нее.

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

  1. Математику гораздо легче освоить, если вы умеете программировать. На самом деле, если вы хотя бы наполовину приличный программист, вы обнаружите, что это совсем несложно.
  2. В школе неправильно преподают математику. АБСОЛЮТНО неправильно. Если вы будете учить математику правильно, вы быстрее научитесь и будете дольше ее помнить, а также извлечете из нее больше полезного для себя как для программиста.
  3. Обладая хотя бы небольшими правильными математическими знаниями, вы сможете написать несколько довольно интересных программ, которые в противном случае были бы для вас слишком сложны. Другими словами, математику можно изучать понемногу, когда у вас есть свободное время.
  4. Никто не знает математику досконально, даже лучшие математики. Эта область постоянно расширяется, поскольку люди изобретают новые совокупности формул для решения различных задач. И любую математическую задачу, как и в программировании, можно решить несколькими способами. Вы можете выбрать тот, который вам больше всего нравится.
  5. Математика… хм, пожалуйста, никому не говорите, что я это сказал, иначе пока я жив, меня никогда больше не пригласят ни на одну вечеринку. А математика, ну…, пожалуй, я лучше скажу это шепотом, так что слушайте: (на самом деле,  это довольно-таки прикольно).

Математика, которую вы учили (и забыли)

Насколько я помню, в школе я изучал кое-что из математики.

Начальная школа: числа, счет, арифметика, предалгебраические задачи («сюжетные задачи»).

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

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

Как они вообще составили такой список для средней школы? В большинстве средних школ США программа более или менее одинаковая. Я думаю, что в других странах то же самое, за исключением того, что у учеников этих стран на изучение всего, что перечислено выше, уходит девять лет. (Однако американцы действительно хорошо себя показывают на соревнованиях на монстр-траках, так что это не полная потеря.)

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

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

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

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

Математика, которой вас не учили

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

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

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

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

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

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

Как ни странно, мой преподаватель не сказал мне, для чего это нужно. Или я не расслышал. Или что-то еще. Поэтому я не особо внимательно вникал: ровно настолько, чтобы пройти курс и навсегда забыть эту ненавистную тему, потому что не думал, что она имеет какое-либо отношение к программированию. И такое происходило со многими курсами по информатике, которые я проходил в колледже, возможно, с 25 % из них. Бедная моя голова! Мне пришлось самому выяснять, что важно, но позже, на собственном горьком опыте.

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

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

  • Статистика, часть которой описана в моем учебнике по дискретной математике, но на самом деле это отдельная дисциплина. Это тоже довольно важный момент, но, надеюсь, он не нуждается в представлении.
  • Алгебра и линейная алгебра (т. е. матрицы). Следовало бы преподавать линейную алгебру сразу после алгебры. Это довольно просто и удивительно полезно во всех областях, включая машинное обучение.
  • Математическая логика. У меня есть действительно крутая абсолютно нечитабельная книга на эту тему Стивена Клини, изобретателя звезды Клини и, насколько мне известно, клинекса. Не читайте ее. Клянусь, я пробовал раз 20 и так и не продвинулся дальше второй главы. Если кто-то может порекомендовать, как лучше изучить эту область, пожалуйста, оставьте под постом свой комментарий. Все-таки это, очевидно, важные вещи.
  • Теория информации и сложность по Колмогорову. Фигня какая-то, да? Могу поспорить, что нигде в средней школе такое не преподают. Оба предмета довольно новые. Теория информации (если уж совсем грубо) посвящена сжатию данных, а сложность по Колмогорову (тоже если говорить приблизительно) — алгоритмической сложности. То есть, насколько вы можете что-то сократить, сколько времени это займет, насколько элегантной может быть программа или структура данных и тому подобное. Оба эти раздела — увлекательные, интересные и полезные.

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

А что насчет математического анализа? Все это учат, так что это должно быть важно, верно?

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

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

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

Правильный способ изучения математики

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

Чтобы представить это в перспективе, подумайте о делении столбиком. Поднимите руку, если вы можете прямо сейчас выполнить деление столбиком на бумаге. Ну кто? Все? Я так не думаю.

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

Почему они вообще учат вас этому? Почему мы чувствуем смутную вину, если не помним, как это сделать? Нельзя сказать, что нам больше не нужно это знать. И кроме того, если бы на кону была ваша жизнь, вы знаете, что могли бы выполнить деление столбиком любых сколь угодно больших чисел. Представьте, вас бросили в грязную тюрьму где-нибудь в стране третьего мира, и диктатор не выпустит вас, пока вы не разделите 219308862 на 103503391. Как вы это будете делать? Да очень просто. Вы начнете вычитать знаменатель из числителя, сохраняя счетчик до тех пор, пока не сможете его вычитать, и это будет остаток. Если на вас будут давить, вы сможете найти способ продолжить вычисление, используя повторное вычитание для оценки остатка в виде десятичного числа (в данном случае, 0.1185678219, так мне подсказывает мой калькулятор Emacs M-x calc. Ну в общем сойдет!)

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

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

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

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

Но на самом деле это отличная новость, потому что легче прочитать об этой области и выучить названия всего, чем изучить реальные алгоритмы и методы моделирования и вычисления. В школе вас учат формуле сложной производной, и вы можете запомнить формулу и применять ее на экзаменах, но сколько учеников действительно знают, что это «значит»? Таким образом, они не смогут знать, как применять формулу, когда на практике столкнутся с задачей, где требуется формула сложной производной. Как это ни парадоксально, но легче понять, что это такое, чем запомнить и применить формулу. Формула сложной производной заключается в том, как получить производную «связанных в цепь» функций — то есть функция x() вызывает функцию g(), а вам нужна производная от x(g()). Что ж, программисты знают все о функциях; мы используем их каждый день, поэтому сейчас гораздо легче представить себе задачу, чем в школе.

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

Я думаю, что лучший способ начать изучать математику — это тратить 15–30 минут в день на просмотр Википедии. Она наполнена статьями о тысячах небольших разделов математики. Начинайте с любой статьи, которая кажется вам интересной (например, со статьи Теория струн, или Преобразование Фурье, или Тензоры, с чего-то, что вам понравится). Начните читать. Если вы чего-то не понимаете, нажмите на ссылку и прочитайте об этом. Делайте это рекурсивно, пока вам не надоест или вы не устанете.

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

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

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

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

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

И тогда вам следует достать калькулятор. Это может быть очень необычный калькулятор, например, R, Matlab, Mathematica или даже библиотека C для машин опорных векторов. Но почти все полезные разделы математики в значительной степени автоматизированы, так что в качестве помощи можно также воспользоваться и автоматическими помощниками.

Когда упражнения полезны?

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

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

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

Я думаю, именно так люди, склонные к математике (математики и любители), читают статьи по математике или любые старые статьи, содержащие много математического материала. Они выполняют те же проверки работоспособности, которые делаете и вы при чтении кода, но не более, если только они не намерены пристрелить автора.

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

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

Как это мне поможет?

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

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

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

И это хорошо.

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

 

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *