Могу ли я применить модель PMML, которая включает DefineFunction, используя Augustus (Python)?

Я использую Augustus в качестве потребителя модели PMML. Я изменил пример добавления двух чисел, добавив в него элемент DefineFunction, например:

<PMML version="4.1" xmlns="http://www.dmg.org/PMML-4_1">
    <Header/>
    <DataDictionary>
        <DataField name="x" dataType="double" optype="continuous"/>
        <DataField name="y" dataType="double" optype="continuous"/>
    </DataDictionary>
    <TransformationDictionary>
        <DefineFunction dataType="float" optype="continuous" name="add">
            <ParameterField optype="continuous" name="first"></ParameterField>
            <ParameterField optype="continuous" name="second"></ParameterField>
                <Apply function="+" invalidValueTreatment="returnInvalid">
                    <FieldRef field="first"></FieldRef>
                    <FieldRef field="second"></FieldRef>
                </Apply>
        </DefineFunction>
        <DerivedField name="z" dataType="double" optype="continuous">
            <Apply function="add">
                <FieldRef field="x"/>
                <FieldRef field="y"/>
            </Apply>
        </DerivedField>
    </TransformationDictionary>
</PMML>

Я сохраняю эту модель в файле и пытаюсь запустить ее так:

from resources import add_two_numbers_file # this is just the path to my model file
from augustus.strict import modelLoader

# Load model
with open(add_two_numbers_file, 'r') as model_file:
    model_str = model_file.read()
    model = modelLoader.loadXml(model_str)

# Run model
print model.calc({'x':[1,2,3],'y':[4,5,6]}).look()

Однако я получаю сообщение об ошибке:

AttributeError: 'DefineFunction' object has no attribute '_setupCalculate'

Я использую последний ствол (ревизия 794) и могу запустить немодифицированный пример (без DefineFunction) без проблем. DefineFunction поддерживается Августом?

2 ответа

Решение

jcrudy, вы правы: это была ошибка. (API был изменен, и DefineFunction не была обновлена.) Теперь он исправлен в общедоступном репозитории SVN: с Augustus >= r795 вы можете запустить свой пример, как первоначально предполагалось.

Кстати, ваш PMML приходит из внешнего файла, но вы загружаете его в строку, а затем в PMML DOM. Вы можете пропустить промежуточный шаг, просто пройдя loadXML имя файла:

model = modelLoader.loadXml(add_two_numbers_file)

(Это может быть актуально для очень больших файлов PMML; также обратите внимание, что они могут быть GZipped.)

Я смог решить эту проблему, сделав два изменения. Посмотрев на августовский источник и определив, что _setupCalculate нигде не определен, я залатал его обезьяной. Мой скрипт теперь выглядит так:

# Monkey-patch augustus
import augustus.pmml.DefineFunction
def _setupCalculate(self, dataTable, functionTable, performanceTable):
    return (dataTable, functionTable, performanceTable)
augustus.pmml.DefineFunction.DefineFunction._setupCalculate = _setupCalculate

# Now the actual script
from augustus.strict import modelLoader

# Load model
add_two_numbers_file = 'addTwoNumbers.pmml'
with open(add_two_numbers_file, 'r') as model_file:
    model_str = model_file.read()
    model = modelLoader.loadXml(model_str)

# Run model
print model.calc({'x':[1,2,3],'y':[4,5,6]}).look()

Я сделал наивное предположение, что _setupCalculate не нужно делать ничего важного. Теперь я получаю другую и более непостижимую ошибку:

ValueError: assignment destination is read-only

на линии

mask[mask2] = defs.MISSING

в FieldType.py. После нескольких попыток отладчика я увидел, что эта строка была выполнена только во время приведения типов, и заметил, что в PMML я использовал типы с плавающей и двойной типами. Удалив ненужные атрибуты dataType, я смог заставить работать следующее:

<PMML version="4.1" xmlns="http://www.dmg.org/PMML-4_1">
    <Header/>
    <DataDictionary>
        <DataField name="x" dataType="double" optype="continuous"/>
        <DataField name="y" dataType="double" optype="continuous"/>
    </DataDictionary>
    <TransformationDictionary>
        <DefineFunction optype="continuous" name="add">
            <ParameterField optype="continuous" name="first"></ParameterField>
            <ParameterField optype="continuous" name="second"></ParameterField>
            <Apply function="+" invalidValueTreatment="returnInvalid">
                <FieldRef field="first"></FieldRef>
                <FieldRef field="second"></FieldRef>
            </Apply>
        </DefineFunction>
        <DerivedField name="z" dataType="double" optype="continuous">
            <Apply function="add">
                <FieldRef field="x"/>
                <FieldRef field="y"/>
            </Apply>
        </DerivedField>
    </TransformationDictionary>
</PMML>

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

Другие вопросы по тегам