Вот почему я задаю этот вопрос: В прошлом году я сделал некоторый код на С++ для вычисления задних вероятностей для определенного типа модели (описанной байесовской сетью). Модель работала неплохо, и некоторые другие люди начали использовать мое программное обеспечение. Теперь я хочу улучшить свою модель. Поскольку я уже кодирую несколько разные алгоритмы вывода для новой модели, я решил использовать python, потому что время выполнения не критично важно, и python может позволить мне сделать более элегантный и управляемый код.
Обычно в этой ситуации я искал существующий байесовский сетевой пакет в python, но алгоритмы вывода, которые я использую, являются моими собственными, и я также подумал, что это будет отличная возможность узнать больше о хорошем дизайне в python.
Я уже нашел отличный модуль python для сетевых графиков (networkx), который позволяет вам прикрепить словарь к каждому node и к каждому ребру. По сути, это позволило мне дать свойства узлов и краев.
Для конкретной сети и наблюдаемых данных мне нужно написать функцию, которая вычисляет вероятность неназначенных переменных в модели.
Например, в классической сети "Азия" (http://www.bayesserver.com/Resources/Images/AsiaNetwork.png), с состояниями "XRay Result" и "Dyspnea", Известно, что мне нужно написать функцию для вычисления вероятности того, что другие переменные имеют определенные значения (согласно некоторой модели).
Вот мой вопрос программирования: Я собираюсь попробовать несколько моделей, и в будущем это возможно, я захочу попробовать другую модель после этого. Например, одна модель может выглядеть точно так же, как сеть в Азии. В другой модели, направленный край может быть добавлен из "Посещения в Азию" на "Имеет рак легких". Другая модель может использовать исходный направленный график, но вероятностная модель для "Одышки" node с учетом узлов "Туберкулез или рак" и "Имеет бронхит" может отличаться. Все эти модели будут вычислять вероятность по-другому.
Все модели будут иметь существенное совпадение; например, множественные ребра, входящие в "Or" node, всегда будут делать "0", если все входы "0" и "1" в противном случае. Но некоторые модели будут иметь узлы, которые принимают целочисленные значения в некотором диапазоне, в то время как другие будут логическими.
В прошлом я боролся с тем, как программировать такие вещи. Я не собираюсь лгать; было достаточно скопированного и вставленного кода, и иногда мне нужно было распространять изменения в одном методе на несколько файлов. На этот раз я действительно хочу потратить время, чтобы сделать это правильно.
Некоторые параметры:
- Я уже делал это правильно. Код сначала, задавайте вопросы позже. Быстрее копировать и вставлять код и иметь один класс для каждой модели. Мир - темное и дезорганизованное место...
- Каждая модель является ее собственным классом, но также и подклассом общей байесовской модели. Эта общая модель будет использовать некоторые функции, которые будут переопределены. Страуструп гордился бы.
- Сделайте несколько функций в одном классе, которые вычисляют разные вероятности.
- Кодируйте общую библиотеку BayesianNetwork и реализуйте мои проблемы вывода как конкретные графики, читаемые этой библиотекой. Узлам и ребрам должны быть заданы такие свойства, как "Boolean" и "OrFunction", которые, учитывая известные состояния родительского node, могут быть использованы для вычисления вероятностей разных результатов. Эти строки свойств, такие как "OrFunction", могут даже использоваться для поиска и вызова правильной функции. Может быть, через пару лет я сделаю нечто похожее на версию Mathematica 1988 года!
Большое спасибо за вашу помощь.
Update: Объектно-ориентированные идеи очень помогают здесь (каждый node имеет назначенный набор узлов-предшественников определенного подтипа node, и каждый node имеет функцию правдоподобия, которая вычисляет его вероятность различных состояний результата, учитывая состояния предшественника узлы и т.д.). OOP FTW!