Следующий класс анализирует очень большую строку (весь текст) и разбивает ее на последовательные 4-символьные строки, которые хранятся в виде кортежа.Затем каждому кортежу может быть назначена вероятность на основе расчета.Я использую это как часть монте-карло / генетического алгоритма, чтобы обучить программу распознавать язык только на основе синтаксиса (только переходы символов).
Мне интересно, есть ли более быстрый способ сделать это.Требуется около 400 мс, чтобы найти вероятность любого данного 4-символьного кортежа.Соответствующий метод _Probablity () находится в конце класса.
Это сложная вычислительная проблема, связанная с другим моим постом: Алгоритм вычисления правдоподобия функции / Метод Монте-Карло
В конечном итоге я бы хотел сохранитьэти значения в 4d-матрице.Но, учитывая, что в алфавите 26 букв, это будет ОГРОМНАЯ задача.(26x26x26x26).Если я возьму только первые 15000 символов романа, производительность улучшится, но мои данные не так полезны.
Вот метод, который анализирует текст 'source':
private List<Tuple<char, char, char, char>> _Parse(string src)
{
var _map = new List<Tuple<char, char, char, char>>();
for (int i = 0; i < src.Length - 3; i++)
{
int j = i + 1;
int k = i + 2;
int l = i + 3;
_map.Add
(new Tuple<char, char, char, char>(src[i], src[j], src[k], src[l]));
}
return _map;
}
А вот метод _Probability:
private double _Probability(char x0, char x1, char x2, char x3)
{
var subset_x0 = map.Where(x => x.Item1 == x0);
var subset_x0_x1_following = subset_x0.Where(x => x.Item2 == x1);
var subset_x0_x2_following = subset_x0_x1_following.Where(x => x.Item3 == x2);
var subset_x0_x3_following = subset_x0_x2_following.Where(x => x.Item4 == x3);
int count_of_x0 = subset_x0.Count();
int count_of_x1_following = subset_x0_x1_following.Count();
int count_of_x2_following = subset_x0_x2_following.Count();
int count_of_x3_following = subset_x0_x3_following.Count();
decimal p1;
decimal p2;
decimal p3;
if (count_of_x0 <= 0 || count_of_x1_following <= 0 || count_of_x2_following <= 0 || count_of_x3_following <= 0)
{
p1 = e;
p2 = e;
p3 = e;
}
else
{
p1 = (decimal)count_of_x1_following / (decimal)count_of_x0;
p2 = (decimal)count_of_x2_following / (decimal)count_of_x1_following;
p3 = (decimal)count_of_x3_following / (decimal)count_of_x2_following;
p1 = (p1 * 100) + e;
p2 = (p2 * 100) + e;
p3 = (p3 * 100) + e;
}
//more calculations omitted
return _final;
}
}
EDIT - Я предоставляю больше деталей, чтобы прояснить ситуацию,
1) Строго говоря, я до сих пор работал только с английским языком, но это правда, что другие алфавиты должны будут рассматриваться.В настоящее время я хочу, чтобы программа распознавала только английский язык, подобно тому, что описано в этой статье: http://www -stat.stanford.edu / ~ cgates / PERSI /apers / MCMCRev.pdf
2) Я вычисляю вероятности n наборов символов, где n <= 4. Например, если я вычисляю общую вероятность строки «что», я бы разбил ее на эти независимые кортежи и вычислил вероятность каждогосначала индивидуально: </p>
[т] [ч]
[т] [ч] [а]
[т] [ч] [а] [т]
[t] [h] дается наибольший вес, затем [t] [h] [a], затем [t] [h] [a] [t].Поскольку я не просто рассматриваю 4-символьный кортеж как единое целое, я не смогу просто разделить экземпляры [t] [h] [a] [t] в тексте на общее число no.из 4-х кортежей в следующем.
Значение, присвоенное каждому 4-му кортежу, не может соответствовать тексту, потому что случайно многие настоящие английские слова могут никогда не появиться в тексте, и они не должны получать непропорционально низкие оценки.Усиление переходов между символами первого порядка (2 кортежа) облегчает эту проблему.Переходя к 3-кортежу, затем 4-кортеж просто уточняет расчет.
Я придумал Словарь, который просто подсчитывает, как часто в тексте встречается кортеж (аналогично тому, что предлагал Вилкс), вместо того, чтобы повторять идентичные кортежи, что является пустой тратой памяти.Это дало мне от ~ 400 мс на поиск до ~ 40 мс на поиск, что является довольно значительным улучшением.Однако я все еще должен рассмотреть некоторые другие предложения.