Python 从Tensorflow转换->;CoreML 3.0用于插槽/意图检测

Python 从Tensorflow转换->;CoreML 3.0用于插槽/意图检测,python,swift,tensorflow,chatbot,coreml,Python,Swift,Tensorflow,Chatbot,Coreml,我试图在我的Swift应用程序中使用这个代码库()创建的一些模型 我能够将lstm\u nopooling、lstm\u nopooling 300和lstm转换为CoreML 在model.py中,我使用了以下代码: def save_model(self): joblib.dump(self.summary, 'models/' + self.name + '.txt') self.model.save('models/' + self.name + '.h5') t

我试图在我的Swift应用程序中使用这个代码库()创建的一些模型

我能够将
lstm\u nopooling
lstm\u nopooling 300
lstm
转换为CoreML

model.py
中,我使用了以下代码:

def save_model(self):
    joblib.dump(self.summary, 'models/' + self.name + '.txt')
    self.model.save('models/' + self.name + '.h5')
    try:
        coreml_model = coremltools.converters.keras.convert(self.model, input_names="main_input", output_names=["intent_output","slot_output"])
        coreml_model.save('models/' + self.name + '.mlmodel')
    except:
        pass
    print("Saved model to disk")
我试图将向量转换回意图和槽

我有这个,但是

    func tokenizeSentences(instr: String) -> [Int] {
        let s = instr.lowercased().split(separator: " ")
        var ret = [Int]()
        if let filepath = Bundle.main.path(forResource: "atis.dict.vocab", ofType: "csv") {
            do {
                let contents = try String(contentsOfFile: filepath)
                print(contents)
                var lines = contents.split { $0.isNewline }
                var pos = 0
                for word in s {
                    if let index = lines.firstIndex(of: word) {
                        print(index.description + " " + word)
                        ret.append(index)
                    }
                }
                return ret
            } catch {
                // contents could not be loaded
            }
        } else {
            // example.txt not found!
        }
        return ret
    }
    func predictText(instr:String) {
        let model = lstm_nopooling300()
        guard let mlMultiArray = try? MLMultiArray(shape:[20,1,1],
                                                   dataType:MLMultiArrayDataType.int32) else {
                                                    fatalError("Unexpected runtime error. MLMultiArray")
        }
        let tokens = tokenizeSentences(instr: instr)
        for (index, element) in tokens.enumerated() {
            mlMultiArray[index] = NSNumber(integerLiteral: element)
        }

        guard let m = try? model.prediction(input: lstm_nopooling300Input.init(main_input: mlMultiArray))
            else {
                fatalError("Unexpected runtime error. MLMultiArray")
        }
        let mm = m.intent_output
        let length = mm.count
        let doublePtr =  mm.dataPointer.bindMemory(to: Double.self, capacity: length)
        let doubleBuffer = UnsafeBufferPointer(start: doublePtr, count: length)
        let output = Array(doubleBuffer)
        print("******** intents \(mm.count) ********")
        print(output)
        let mn = m.slot_output
        let length2 = mn.count
        let doublePtr2 =  mm.dataPointer.bindMemory(to: Double.self, capacity: length2)
        let doubleBuffer2 = UnsafeBufferPointer(start: doublePtr2, count: length2)
        let output2 = Array(doubleBuffer2)
        print("******** slots \(mn.count) ********")
        print(output2)
    }
}
当我运行代码时,出于以下目的,我得到了这个被截断的代码:

********意图540*******

[0.0028914143331348896、0.0057610333897173405、4.1651015635579824e-05、, 0.15935245156288147、5.6665314332349226e-05、5.7797817134996876e-05、0.004430230706901605、0.00012486864579841495、0.0004683282459154725、0.003053907072171569、3.806956738117151e-05、0.012112349271774292、5.861848694621585e-05、0.003134472525428、

我认为,问题在于ID位于pickle文件中,因此可能在atis/atis.train.pkl中

我所做的只是训练模型并将它们转换成CoreML,现在我正在尝试使用它,但不确定下一步该怎么做

我有一个文本字段,输入“伦敦当前天气”,我希望得到类似的内容(这来自运行example.py)
{'intent':'weather_intent','slots':[{'name':'city','value':'London'}]}

下面是coreml输入/输出


多亏了@MatthijsHollemans,我才知道该怎么办

在data_processing.py中,我添加了以下内容:

with open('atis/wordlist.csv', 'w') as f:
    for key in ids2words.keys():
        f.write("%s\n"%(ids2words.keys[key]))
with open('atis/wordlist_slots.csv', 'w') as f:
    for key in ids2slots.keys():
        f.write("%s\n"%(ids2slots[key]))
with open('atis/wordlist_intents.csv', 'w') as f:
    for key in ids2intents.keys():
        f.write("%s\n"%(ids2intents[key]))
这允许我使用wordlist.csv正确标记

然后当我得到响应时,使用
mm.count
是错误的,它应该是
output.count
例如,我可以看到意图

查找具有最大值的元素,然后在wordlist_intents.csv(我将其转换为数组,可能应该是字典)中查找可能的意图

我仍然需要做插槽,但基本想法是一样的

关键是将python中使用的字典输出到csv文件,然后将其导入到项目中

更新

我意识到当mm.count为540时,这是因为它可以在句子中包含20个单词,因此它可以返回那么多。所以在我的例子中,我需要将单词按空格分割,然后循环多次,因为我不会得到比单词更多的插槽

我在SwiftUI中这样做,所以我还必须创建一个可观察对象,以便使用EnvironmentObject传递术语

因此,为了正确地循环内存中的双数组,我包含了实现我期望的最新代码

func predictText(instr:String) {
    let model = lstm_nopooling300()
    guard let mlMultiArray = try? MLMultiArray(shape:[20,1,1],
                                               dataType:MLMultiArrayDataType.int32) else {
                                                fatalError("Unexpected runtime error. MLMultiArray")
    }
    let tokens = tokenizeSentences(instr: instr)
    let sent = instr.split(separator: " ")
    print(instr)
    print(tokens)
    for (index, element) in tokens.enumerated() {
        mlMultiArray[index] = NSNumber(integerLiteral: element)
    }

    guard let m = try? model.prediction(input: lstm_nopooling300Input.init(main_input: mlMultiArray))
        else {
            fatalError("Unexpected runtime error. MLMultiArray")
    }

    let mm = m.intent_output
    let length = mm.count
    let doublePtr =  mm.dataPointer.bindMemory(to: Double.self, capacity: length)
    var intents = [String]()
    for i in 0...sent.count - 1  {
        let doubleBuffer = UnsafeBufferPointer(start: doublePtr + i * 27, count: 27)
        let output = Array(doubleBuffer)
        let intent = convertVectorToIntent(vector: output)
        intents.append(intent)
    }
    print(intents)
    let mn = m.slot_output
    let length2 = mn.count
    let doublePtr2 =  mn.dataPointer.bindMemory(to: Double.self, capacity: length2)
    var slots = [String]()
    for i in 0...sent.count - 1 {
        let doubleBuffer2 = UnsafeBufferPointer(start: doublePtr2 + i * 133, count: 133)
        let output2 = Array(doubleBuffer2)
        var slot = ""
        slot = convertVectorToSlot(vector: output2)
        slots.append(slot)
        slots.append(sent[i].description)
    }
    print(slots)
}

您运行了哪种代码来生成该输出?@smac89-我编写了一个应用程序,我正在尝试使用它,这就是我运行的代码。如果您查看swift代码,“打印(输出)”'是我显示的,但我只想显示返回值的一小部分。我添加了更多代码,因为我忘记了一个函数,并且显示了所有函数可能会有所帮助。模型实际输出什么?原始model.py显示需要argmax来获取索引,然后在表中查找。从您的问题来看,不清楚输出数据看起来像,以及应该如何获取这些argmax。@MatthijsHollemans-谢谢。添加了我键入的内容和我期望得到的内容,或者与之相近的内容。但我问你从模型中实际得到了什么。有多少个输出,它们的数据类型是什么,它们的形状是什么,等等?