【问题标题】:Convert from Tensorflow -> CoreML 3.0 for slot/intent detection从 Tensorflow 转换 -> CoreML 3.0 用于槽/意图检测
【发布时间】:2020-03-20 07:29:28
【问题描述】:

我正在尝试在我的 Swift 应用程序中使用此代码库 (Slot-Filling-Understanding-Using-RNNs) 创建的一些模型。

我能够将lstm_nopoolinglstm_nopooling300lstm 转换为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.0044302307069301605,0.00012486864579841495,0.0004683282459154725,0.003053907072171569,3.806956738117151e-05,0.012112349271774292,5.861848694621585e-05,0.0031344725284725428, P>

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

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

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

这里是 coreml 输入/输出

【问题讨论】:

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

标签: python swift tensorflow chatbot coreml


【解决方案1】:

感谢@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 中执行此操作,因此我还必须创建一个 observable,以便我可以使用 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)
}

【讨论】:

    猜你喜欢
    • 2020-05-01
    • 2018-09-12
    • 2020-06-08
    • 1970-01-01
    • 2020-08-25
    • 2019-12-18
    • 2021-07-24
    • 2019-03-23
    • 2020-12-21
    相关资源
    最近更新 更多