Я однажды сидел на каком-то не очень интересном докладе, что-то про организацию какой-то базы, как вдруг после слов докладчика "Если две последовательности похожи друг на друга более, чем 95%" весь зал вдруг проснулся и сразу же прозвучал вопрос "Как вы сравниваете последовательности?". Было видно, что весь зал внезапно проснулся, и, замерев, уставился на бедного докладчика. Он смутился и ответил "Ну, стандартным способом". - "Каким это еще таким стандартным способом?" - сразу же спросил кто-то в зале. Докладчик задумался и после долгой паузы выдал "Через blast". В зале поднялся шум, все стали обсуждать это.
О том, как сравнить между собой две последовательности и получить их некую меру схожести, это на самом деле очень хитрый и до сих пор толком не изученный вопрос.
Это только в теории все просто. Вот у нас есть две последовательности
CGGACACACAAA
и
CGACAACACAAT
Мы просто считаем минимальное количество вставок-замен и удалений, суммируем их и выясняем, что это 3. А три - это и есть наше искомое расстояние между ними.
Но ДНК - это формат хранения данных. Данные триплетами транслируются в аминокислоты, из которых уже собираются белки, которые и являются теми микромеханизмами, из которых все построено.
Что означает "триплетами транслируются в аминокислоты"? Нуклеотидная последовательность разбивается на тройки, которые потом по таблице конвертируются в аминокислоты
CGG ACA CAC AAA
| | | |
R T H K
Или так: CGG ACA CAC AAA ---> RTHK
Эти тройки называют кодонами. Все время забываю, сколько этих аминокислот, толи 20, толи 21. Существуют еще управляющие сигналы начала и конца трансляции кода и сама таблица трансляции слегка отличается у некоторых групп организмов.
А теперь представьте себе, что в коде произошла вставка, на третью позицию вклинился нуклеотид А.
CGGACACACAAA
CGAGACACACAAA
И оттранслируем его заново: CGAGACACACAAA ---> RDTQ
Все поломалось. Мы получили вообще другой набор аминокислот, которые, собравшись в белок, точно будут делать что-то совсем другое, чем от него ожидалось. Вставка и удаление всего одного нуклеотида это почти всегда означает полную поломку механизмов работы этой части генома, и, вполне возможно, даже смерть всего организма, если это произошло в критической и недублированной его части. Одна маленькая вставка или удаление ДНК вызывает огромную разницу в аминокислотной последовательности, если оно произошло в кодирующей части. То есть той, которая будет транслирована в аминокислоты. А если не в кодирующей, то, может, ничего и страшного. Буквой больше, буквой меньше, там все равно может быть забит давно не работающий ген, типа хвоста у человека или просто что-то для "форматирования" кода.
А вот замена нуклеотид вызывают куда меньше эффектов. Если посмотрите на таблицу, то видно, что меньше всего на выбор аминокислоты влияет третий нуклеотид. Он часто можно быть вообще любым. Можно даже подобрать совсем другую последовательность ДНК, которая будет транслирована в точно такой же набор аминокислот, то есть физически белок, который будет что-то делать в организме, будет точно такой же.
Например,
CGGACACACAAA ---> RTHK
AGAACGCATAAG ---> RTHK
одинаковые для организма, одинаковые для биолога и разные только для программиста. Поэтому биологи любят сравнивать оттранслированные последовательности. Сначала перевести ДНК в аминокислоты и сравнивать уже аминокислоты. Они называют это "сравнением в пространстве протеинов" - protein space. Что немного терминологически неверно и сбивает с толку. Белки - это уже следующий уровень, а тут мы пока смотрим только на аминокислоты.
Кстати, даже если замена нуклеотида приводит к замене аминокислоты, то реальный белок, состоящий из их цепочки, все равно может получиться вполне рабочим. В некоторых случаях замещение одной аминокислоты другой делает белок нерабочим, в некоторых - проходит вообще незамеченным. Еще в начале 90ых некоторые люди собрали статистику на тему какие аминокислоты могут замещать какие, а какие нет, и захардкодили это в некоторые утилиты сравнения аминокислотых последовательностей, но с тех пор, насколько мне известно, никто так глубоко не копал, чтобы перепроверить эти таблицы согласно современной статистике. Оно в общем-то как-то работает.
Ну хорошо, давайте просто оттранслируем ДНК в аминокислоты и будем сравнивать последовательности там. Но откуда мы знаем, откуда начинать трансляцию? Мы можем начать с первой буквы, со второй и третьей и получим вообще разные последовательности в итоге.
CGG ACA CAC AAA ---> RTHK
GGA CAC ACA AA ---> GHT
О том, как сравнить между собой две последовательности и получить их некую меру схожести, это на самом деле очень хитрый и до сих пор толком не изученный вопрос.
Это только в теории все просто. Вот у нас есть две последовательности
CGGACACACAAA
и
CGACAACACAAT
Мы просто считаем минимальное количество вставок-замен и удалений, суммируем их и выясняем, что это 3. А три - это и есть наше искомое расстояние между ними.
Но ДНК - это формат хранения данных. Данные триплетами транслируются в аминокислоты, из которых уже собираются белки, которые и являются теми микромеханизмами, из которых все построено.
Что означает "триплетами транслируются в аминокислоты"? Нуклеотидная последовательность разбивается на тройки, которые потом по таблице конвертируются в аминокислоты
CGG ACA CAC AAA
| | | |
R T H K
Или так: CGG ACA CAC AAA ---> RTHK
Эти тройки называют кодонами. Все время забываю, сколько этих аминокислот, толи 20, толи 21. Существуют еще управляющие сигналы начала и конца трансляции кода и сама таблица трансляции слегка отличается у некоторых групп организмов.
А теперь представьте себе, что в коде произошла вставка, на третью позицию вклинился нуклеотид А.
CGGACACACAAA
CGAGACACACAAA
И оттранслируем его заново: CGAGACACACAAA ---> RDTQ
Все поломалось. Мы получили вообще другой набор аминокислот, которые, собравшись в белок, точно будут делать что-то совсем другое, чем от него ожидалось. Вставка и удаление всего одного нуклеотида это почти всегда означает полную поломку механизмов работы этой части генома, и, вполне возможно, даже смерть всего организма, если это произошло в критической и недублированной его части. Одна маленькая вставка или удаление ДНК вызывает огромную разницу в аминокислотной последовательности, если оно произошло в кодирующей части. То есть той, которая будет транслирована в аминокислоты. А если не в кодирующей, то, может, ничего и страшного. Буквой больше, буквой меньше, там все равно может быть забит давно не работающий ген, типа хвоста у человека или просто что-то для "форматирования" кода.
А вот замена нуклеотид вызывают куда меньше эффектов. Если посмотрите на таблицу, то видно, что меньше всего на выбор аминокислоты влияет третий нуклеотид. Он часто можно быть вообще любым. Можно даже подобрать совсем другую последовательность ДНК, которая будет транслирована в точно такой же набор аминокислот, то есть физически белок, который будет что-то делать в организме, будет точно такой же.
Например,
CGGACACACAAA ---> RTHK
AGAACGCATAAG ---> RTHK
одинаковые для организма, одинаковые для биолога и разные только для программиста. Поэтому биологи любят сравнивать оттранслированные последовательности. Сначала перевести ДНК в аминокислоты и сравнивать уже аминокислоты. Они называют это "сравнением в пространстве протеинов" - protein space. Что немного терминологически неверно и сбивает с толку. Белки - это уже следующий уровень, а тут мы пока смотрим только на аминокислоты.
Кстати, даже если замена нуклеотида приводит к замене аминокислоты, то реальный белок, состоящий из их цепочки, все равно может получиться вполне рабочим. В некоторых случаях замещение одной аминокислоты другой делает белок нерабочим, в некоторых - проходит вообще незамеченным. Еще в начале 90ых некоторые люди собрали статистику на тему какие аминокислоты могут замещать какие, а какие нет, и захардкодили это в некоторые утилиты сравнения аминокислотых последовательностей, но с тех пор, насколько мне известно, никто так глубоко не копал, чтобы перепроверить эти таблицы согласно современной статистике. Оно в общем-то как-то работает.
Ну хорошо, давайте просто оттранслируем ДНК в аминокислоты и будем сравнивать последовательности там. Но откуда мы знаем, откуда начинать трансляцию? Мы можем начать с первой буквы, со второй и третьей и получим вообще разные последовательности в итоге.
CGG ACA CAC AAA ---> RTHK
GGA CAC ACA AA ---> GHT
GAC ACA CAA A ---> DTQ
Их называют соответственно, первый, второй и третий фрейм. А ведь есть еще обратно комплементарная сторона. Итого 6 разных вариантов - 6 фреймов. Какой выбрать? Проще всего не думать и сравнивать все со всеми. Итого 36 сравнений вместо одного. Так часто и делают.
Но интересно, что правильный фрейм можно угадать. Точно так же, как и в естественном языке, частоты троек нуклеотид сильно разные. Какие-то тройки используются сильно чаще других.
К примеру, слово "правильный". Имеет тройки пра, рав, ави, вил, иль, льн, ьны, ный. А слово "щшкуоатвцаь" тройки щшк, шку, куо, оат, атв, твц, вца, цаь.
Взглянув только на "цаь" можно сразу сказать, что такого слова в русском языке нет. Но можно более формально подойти. Взять большой текст на русском, посчитать статистику троект по нему и получить, допустим, такие цифры частот для данных троек
(где 10%% это 0.010)
пра 10%%
рав 20%%
ави 10%%
вил 5%%
иль 2%%
льн 1%%
ьны 5%%
ный 50%%
щшк 0%%
шку 4%%
куо 1%%
оат 1%%
атв 3%%
твц 1%%
вца 3%%
цаь 0%%
и ститаем (где логарифм двоичный)
complexity ("правильный") =
log(1/0.010) + log(1/0.020) + log(1/0.010) + log(1/0.005) + log(1/0.002) + log(1/0.001) + log(1/0.005) + log(1/0.050) =
log(100) + log(50) + log(100) + log(200) + log(500) + log(1000) + log(200) + log(20) ~= 7 + 6 + 7 + 8 + 9 + 10 + 8 + 4 = 59
А теперь complexity("щшкуоатвцаь") =
log(1/0) + log(250) + log(1000) + log(1000) + log(333) + log(1000) + log(333) + log(1/0) ~= 8 + 10 + 10 + 8 + 10 + 8 + 2log(1/0) = 54 + две бесконечности.
Даже если вдруг щшк и цаь будут иметь частоту в одну промилле, то мы получим минимум 74.
Если есть вопросы откуда здесь вообще берутся частоты и логарифмы, то советую погуглить на тему кодирования Хаффмана и его более современное и развитое применение - intra кодирования в кодеках.
Можно пойти даже еще на уровень выше и заметить, что тройки аминокислот тоже распределены неравномерно. Скорее всего из трех вариантов RTH, GHT или DTQ встречается в реальных белках в разы чаще остальных двух. Я здесь когда-нибудь вставлю реально посчитанную таблицу частот, а пока поверьте мне на слово.
В итоге можно посчитать сложность (complexity) кодирования в битах как двоичный логарифм единицы на частоту и можно просто выбрать фрейм с минимальной complexity. Это реально работает. Как правило, один из фреймов выглядит гораздо менее сложным, то есть состоит из гораздо более часто встречающихся троек, чем остальные. Но это не везде так. Есть области генома, которые не транслируются в аминокислоты. Там такого может и не быть. Но, может, тогда и не надо такие области сравнивать в пространстве аминокислот?
Биологи поступают обычно немного по другому. Они знают, что трансляция может начаться только с определенных мест. Их называют ORF - Open Reading Frame. И заканчивается трансляция тоже в определенном месте. Если с окончанием трансляции более-менее понятно - там просто идет стоп-триплет (стоп-кодон), то начало трансляции не гарантируется старт-кодоном и существует некий набор эвристик, который оценивает, действительно ли трансляция начинается в этом месте и заканчивается в другом. Очень часто биологи из всего генома выбирают только эти небольшие регионы и исследуют только их, потому что с остальным просто непонятно что делать. Отсюда и идет поверье, что, мол, в ДНК много мусора, который ничего не значит.
Пока что вся история с превращением ДНК в некие реально работающие молекулы-запчасти, которые, плавая, сами собираются, например, в клеточные стенки, выглядит достаточно стройной - есть определенные места в ДНК, откуда начинается трансляция в аминокислоты, цепочки из которых сворачиваются в белки, из которых все и состоит. Но тут есть один очень неприятный нюанс, который настолько все усложняет, что его обычно просто игнорируют. Называется он сплайсинг. Для программиста это выглядит как будто трансляция началась с какого-то места, идет-идет, потом, бац и перепрыгнула куда-то в другое место, идет, потом опять перепрыгнула куда-то и продолжилась с него. В основном такое творится только у эукариот, у бактерий этого обычно нет. Причина этого в том, что трансляция идет не напрямую с ДНК, потому что она двойная и просто не пролазит в машину для трансляции, а с её одинарной временной копии - РНК, которая нестабильная из-за отсутствия комплементарной последовательности, спутывается сама с собой, в результате чего из нее выпадают некоторые части.
Часто вы не знаете, читаете ли кусок ДНК или РНК, из которой некоторые части уже отвалились. Иногда в описании к данным написано что там, хотя не стоит этому сильно доверять, а, бывает, что просто смесь - и куски ДНК и РНК. Обе вещи полезны. С одной стороны ДНК - ровно то, что записано. С другой стороны рабочие белки будут оттранислированы именно с РНК. У бактерий проблем с вываливающимися кусками из РНК обычно нет, и это одна из многих причин, по которой приходится писать специализированный софт для бактерий и эукариот и почему бактерии исследовать гораздо проще.
Ну хорошо, мы можем сравнивать последовательность в пространстве нуклеотид, можем - в пространстве аминокислот, но, особенно при сравнении вирусов приходится идти в пространство более высокого уровня. Я называю его пространством функциональных элементов. Просто каким бы вирус ни был, ему все равно приходится решать ряд проблем, как проникновение в клетку и построение оболочки. Как бы вирусы ни мутировали, в них все равно можно обнаружить все эти части и построить меру схожести даже с оооочень отдаленными вирусами, например, вирус группа связан с вирусами, заражающими растения. Сравнение в пространстве функциональных элементов это тема отдельного поста или даже постов.
Кто-то наверняка может сказать - можно использовать Deep Learning для идентификации функциональных частей в вирусах. Да, можно, никто не запрещает. Но точно так же можно забороть эту проблему обычным матаном, который будет во многом очень похож на Deep Learning, просто более явный его вид без разного рода скрытых и непонятных вещей и подгоночных коэффициентов.
Но вернемся к более простым вещам. Те, кто занимается data science скажут, что один из вариантов сравнения - это сравнение фич. Мы можем придумать и посчитать некоторые характеристики последовательностей и сравнивать их. Самая часто используемая характеристика последовательности называется GC content. Это просто процент букв C и G в последовательности. Экспериментально установлено, что это мера стабильности ДНК. Разные организмы имеют разные механизмы поддержания стабильности ДНК (да и другие причины наверняка есть) из-за чего только по одному этому числу часто можно сразу же предположить к какому примерно семейству организмов может относиться данная последовательность. Если две достаточно длинные последовательности имеют сильно разный GC Content, то организмы, к которым они принадлежат, скорее всего сильно разные. Это число даже обычно публикуют рядом с любой последовательностью, чтобы ученый мог на глаз оценить, что перед ним.
Можно все известные последовательности ДНК просто отсортировать по GC Content и получить очень неплохую группировку по степени похожести этих организмов в реальности. Когда мы пытаемся оценить на что похожа какая-то неизвестная последовательность, можно просто посчитать её GC Content и посмотреть на каком месте она окажется и в какую группу попадет. У меня где-то есть эта самая таблица и надо бы наверное её тут опубликовать как-нибудь будет.
Но GC Content это все технологии прошлого, есть расширение этой идеи - оценить распределение букв A C T и G или даже лучше всех троек этих букв и получить не одно число, а вектор и сравнивать вектора соотвествующие последовательностям. Data scientist'ы узнают тут операцию свертки на некоторые простые базовые элементы из троек нуклеотид. Вычислительно это легкая задача и работает сравнение и группировка последовательностей только на основании похожести распределениё троек просто замечательно хорошо даже для сильно мутирующих вирусов. Если вы получили какой-то новый неизвестный вирус, который ну просто никак не похож ни на что другое, самое простое, что можно сделать - посчитать статистику распределений троек нуклеотид и найти группу известных вирусов с похожими характеристиками.
Можно идти выше и собирать статистику не троек, а, например 16ек или 32ок. В анализе текста их называют n-граммы, а в бионформатике больше устоялся термин k-mer. Хотя 32mer очень красиво умещается в int64, но все равно уже возникает проблема нехватки памяти и скорости обработки, как и общей избыточности таких k-mer и как это красиво обходится minhash я напишу уже где-то в последующей статье.
Какой-то мегапост уже получился. Я закончу его на одной простой вещи. Если вы получили два вектора, у вас существует, конечно, много способов их сравнения. Можно посчитать сумму модулей разности, можно корень из суммы квадратов разностей, но самым удобным и точным по многим причинам способом является сравнение через косинус.
a * b = |a| * |b| * cos( угла между a и b)
Косинус угла между векторами как отношение скалярного произведения на произведение норм (Евклидовых - корень из суммы квадратов) это и есть очень удобная мера схожести двух векторов. А задача сравнения двух последовательностей в итоге сводится к выборе пространства сравнения и вычисления координат последовательностей в этом пространстве.
Их называют соответственно, первый, второй и третий фрейм. А ведь есть еще обратно комплементарная сторона. Итого 6 разных вариантов - 6 фреймов. Какой выбрать? Проще всего не думать и сравнивать все со всеми. Итого 36 сравнений вместо одного. Так часто и делают.
Но интересно, что правильный фрейм можно угадать. Точно так же, как и в естественном языке, частоты троек нуклеотид сильно разные. Какие-то тройки используются сильно чаще других.
К примеру, слово "правильный". Имеет тройки пра, рав, ави, вил, иль, льн, ьны, ный. А слово "щшкуоатвцаь" тройки щшк, шку, куо, оат, атв, твц, вца, цаь.
Взглянув только на "цаь" можно сразу сказать, что такого слова в русском языке нет. Но можно более формально подойти. Взять большой текст на русском, посчитать статистику троект по нему и получить, допустим, такие цифры частот для данных троек
(где 10%% это 0.010)
пра 10%%
рав 20%%
ави 10%%
вил 5%%
иль 2%%
льн 1%%
ьны 5%%
ный 50%%
щшк 0%%
шку 4%%
куо 1%%
оат 1%%
атв 3%%
твц 1%%
вца 3%%
цаь 0%%
и ститаем (где логарифм двоичный)
complexity ("правильный") =
log(1/0.010) + log(1/0.020) + log(1/0.010) + log(1/0.005) + log(1/0.002) + log(1/0.001) + log(1/0.005) + log(1/0.050) =
log(100) + log(50) + log(100) + log(200) + log(500) + log(1000) + log(200) + log(20) ~= 7 + 6 + 7 + 8 + 9 + 10 + 8 + 4 = 59
А теперь complexity("щшкуоатвцаь") =
log(1/0) + log(250) + log(1000) + log(1000) + log(333) + log(1000) + log(333) + log(1/0) ~= 8 + 10 + 10 + 8 + 10 + 8 + 2log(1/0) = 54 + две бесконечности.
Даже если вдруг щшк и цаь будут иметь частоту в одну промилле, то мы получим минимум 74.
Если есть вопросы откуда здесь вообще берутся частоты и логарифмы, то советую погуглить на тему кодирования Хаффмана и его более современное и развитое применение - intra кодирования в кодеках.
Можно пойти даже еще на уровень выше и заметить, что тройки аминокислот тоже распределены неравномерно. Скорее всего из трех вариантов RTH, GHT или DTQ встречается в реальных белках в разы чаще остальных двух. Я здесь когда-нибудь вставлю реально посчитанную таблицу частот, а пока поверьте мне на слово.
В итоге можно посчитать сложность (complexity) кодирования в битах как двоичный логарифм единицы на частоту и можно просто выбрать фрейм с минимальной complexity. Это реально работает. Как правило, один из фреймов выглядит гораздо менее сложным, то есть состоит из гораздо более часто встречающихся троек, чем остальные. Но это не везде так. Есть области генома, которые не транслируются в аминокислоты. Там такого может и не быть. Но, может, тогда и не надо такие области сравнивать в пространстве аминокислот?
Биологи поступают обычно немного по другому. Они знают, что трансляция может начаться только с определенных мест. Их называют ORF - Open Reading Frame. И заканчивается трансляция тоже в определенном месте. Если с окончанием трансляции более-менее понятно - там просто идет стоп-триплет (стоп-кодон), то начало трансляции не гарантируется старт-кодоном и существует некий набор эвристик, который оценивает, действительно ли трансляция начинается в этом месте и заканчивается в другом. Очень часто биологи из всего генома выбирают только эти небольшие регионы и исследуют только их, потому что с остальным просто непонятно что делать. Отсюда и идет поверье, что, мол, в ДНК много мусора, который ничего не значит.
Пока что вся история с превращением ДНК в некие реально работающие молекулы-запчасти, которые, плавая, сами собираются, например, в клеточные стенки, выглядит достаточно стройной - есть определенные места в ДНК, откуда начинается трансляция в аминокислоты, цепочки из которых сворачиваются в белки, из которых все и состоит. Но тут есть один очень неприятный нюанс, который настолько все усложняет, что его обычно просто игнорируют. Называется он сплайсинг. Для программиста это выглядит как будто трансляция началась с какого-то места, идет-идет, потом, бац и перепрыгнула куда-то в другое место, идет, потом опять перепрыгнула куда-то и продолжилась с него. В основном такое творится только у эукариот, у бактерий этого обычно нет. Причина этого в том, что трансляция идет не напрямую с ДНК, потому что она двойная и просто не пролазит в машину для трансляции, а с её одинарной временной копии - РНК, которая нестабильная из-за отсутствия комплементарной последовательности, спутывается сама с собой, в результате чего из нее выпадают некоторые части.
Часто вы не знаете, читаете ли кусок ДНК или РНК, из которой некоторые части уже отвалились. Иногда в описании к данным написано что там, хотя не стоит этому сильно доверять, а, бывает, что просто смесь - и куски ДНК и РНК. Обе вещи полезны. С одной стороны ДНК - ровно то, что записано. С другой стороны рабочие белки будут оттранислированы именно с РНК. У бактерий проблем с вываливающимися кусками из РНК обычно нет, и это одна из многих причин, по которой приходится писать специализированный софт для бактерий и эукариот и почему бактерии исследовать гораздо проще.
Ну хорошо, мы можем сравнивать последовательность в пространстве нуклеотид, можем - в пространстве аминокислот, но, особенно при сравнении вирусов приходится идти в пространство более высокого уровня. Я называю его пространством функциональных элементов. Просто каким бы вирус ни был, ему все равно приходится решать ряд проблем, как проникновение в клетку и построение оболочки. Как бы вирусы ни мутировали, в них все равно можно обнаружить все эти части и построить меру схожести даже с оооочень отдаленными вирусами, например, вирус группа связан с вирусами, заражающими растения. Сравнение в пространстве функциональных элементов это тема отдельного поста или даже постов.
Кто-то наверняка может сказать - можно использовать Deep Learning для идентификации функциональных частей в вирусах. Да, можно, никто не запрещает. Но точно так же можно забороть эту проблему обычным матаном, который будет во многом очень похож на Deep Learning, просто более явный его вид без разного рода скрытых и непонятных вещей и подгоночных коэффициентов.
Но вернемся к более простым вещам. Те, кто занимается data science скажут, что один из вариантов сравнения - это сравнение фич. Мы можем придумать и посчитать некоторые характеристики последовательностей и сравнивать их. Самая часто используемая характеристика последовательности называется GC content. Это просто процент букв C и G в последовательности. Экспериментально установлено, что это мера стабильности ДНК. Разные организмы имеют разные механизмы поддержания стабильности ДНК (да и другие причины наверняка есть) из-за чего только по одному этому числу часто можно сразу же предположить к какому примерно семейству организмов может относиться данная последовательность. Если две достаточно длинные последовательности имеют сильно разный GC Content, то организмы, к которым они принадлежат, скорее всего сильно разные. Это число даже обычно публикуют рядом с любой последовательностью, чтобы ученый мог на глаз оценить, что перед ним.
Можно все известные последовательности ДНК просто отсортировать по GC Content и получить очень неплохую группировку по степени похожести этих организмов в реальности. Когда мы пытаемся оценить на что похожа какая-то неизвестная последовательность, можно просто посчитать её GC Content и посмотреть на каком месте она окажется и в какую группу попадет. У меня где-то есть эта самая таблица и надо бы наверное её тут опубликовать как-нибудь будет.
Но GC Content это все технологии прошлого, есть расширение этой идеи - оценить распределение букв A C T и G или даже лучше всех троек этих букв и получить не одно число, а вектор и сравнивать вектора соотвествующие последовательностям. Data scientist'ы узнают тут операцию свертки на некоторые простые базовые элементы из троек нуклеотид. Вычислительно это легкая задача и работает сравнение и группировка последовательностей только на основании похожести распределениё троек просто замечательно хорошо даже для сильно мутирующих вирусов. Если вы получили какой-то новый неизвестный вирус, который ну просто никак не похож ни на что другое, самое простое, что можно сделать - посчитать статистику распределений троек нуклеотид и найти группу известных вирусов с похожими характеристиками.
Можно идти выше и собирать статистику не троек, а, например 16ек или 32ок. В анализе текста их называют n-граммы, а в бионформатике больше устоялся термин k-mer. Хотя 32mer очень красиво умещается в int64, но все равно уже возникает проблема нехватки памяти и скорости обработки, как и общей избыточности таких k-mer и как это красиво обходится minhash я напишу уже где-то в последующей статье.
Какой-то мегапост уже получился. Я закончу его на одной простой вещи. Если вы получили два вектора, у вас существует, конечно, много способов их сравнения. Можно посчитать сумму модулей разности, можно корень из суммы квадратов разностей, но самым удобным и точным по многим причинам способом является сравнение через косинус.
a * b = |a| * |b| * cos( угла между a и b)
Косинус угла между векторами как отношение скалярного произведения на произведение норм (Евклидовых - корень из суммы квадратов) это и есть очень удобная мера схожести двух векторов. А задача сравнения двух последовательностей в итоге сводится к выборе пространства сравнения и вычисления координат последовательностей в этом пространстве.