深度学习和 Eclipse 集合

作者: Paul King
发布时间: 2022-10-11 10:41AM


在之前的博客中,我们已经介绍了 Eclipse 集合深度学习。最近,Eclipse 集合的一些高度推荐的 kata 进行了改进,包括“宠物”和“水果”表情符号,以增加一些乐趣。还有什么比学习 Eclipse 集合更好的呢?当然还有深度学习和 Eclipse 集合!

设置我们的模型和数据

首先,我们创建一个 PetType 枚举,其中表情符号作为 toString

enum PetType {
    CAT("🐱"),
    DOG("🐶"),
    HAMSTER("🐹"),
    TURTLE("🐢"),
    BIRD("🐦"),
    SNAKE("🐍")

    private final String emoji

    PetType(String emoji) { this.emoji = emoji }

    @Override
    String toString() { emoji }
}

然后是一个 Pet 记录(其中 type 作为 toString

record Pet(PetType type, String name, int age) {
    String toString() { type.toString() }
}

类似地,我们将创建一个 Person 记录。我们还将填充一个 people 列表,如 kata 中所做的那样。完整详情见 repo

让我们使用 GQuery 表达式来探索预填充的列表

println GQ {
    from p in people
    select p.fullName, p.pets
}

结果是

+---------------+----------+
| fullName      | pets     |
+---------------+----------+
| Mary Smith    | [🐱]     |
| Bob Smith     | [🐱, 🐶] |
| Ted Smith     | [🐶]     |
| Jake Snake    | [🐍]     |
| Barry Bird    | [🐦]     |
| Terry Turtle  | [🐢]     |
| Harry Hamster | [🐹, 🐹] |
| John Doe      | []       |
+---------------+----------+

现在让我们复制原始 kata 的 exercise3 中 getCountsByPetType 测试中的断言,该断言检查宠物数量

var counts = people.countByEach(person -> person.petTypes).collect(Object::toString)
var expected = Bags.mutable.withOccurrences("🐱", 2, "🐶", 2, "🐹", 2).with("🐍").with("🐢").with("🐦")
assert counts == expected

正如我们预期的那样,它通过了。

应用深度学习

现在,为了增加一些乐趣,我们将使用一个训练过的神经网络来检测猫和狗的图像,并将其应用于我们的表情符号。我们将遵循 此处 描述的过程。它使用 Eclipse DeepLearning4j 来训练模型,然后使用模型。用于训练模型的图像是真实的猫和狗图像,而不是表情符号,所以我们不期望我们的模型非常准确。

第一次尝试是将表情符号写入 Swing JLabel 组件,然后使用缓冲图像保存。这导致图像质量很差

PetAsFonts

因此,图像推理效果也很差。某些平台上的最新 JDK 版本可能效果更好,但我们放弃了这种方法。

相反,我们使用了 Noto 彩色表情符号 字体中的表情符号图像文件,并将它们保存在 resources 文件夹中的宠物类型下。这些图像看起来要好得多

Noto Color Emoji

以下是使用这些保存的图像来检测动物类型的代码(请注意,由于我们有两个 PetType 类,因此使用了类型别名;我们将其中一个重命名为 PT

import ramo.klevis.ml.vg16.PetType as PT
import ramo.klevis.ml.vg16.VG16ForCat

var vg16ForCat = new VG16ForCat().tap{ loadModel() }
var results = []
people.each{ p ->
    results << p.pets.collect { pet ->
        var file = new File("resources/${pet.type.name()}.png")
        PT petType = vg16ForCat.detectCat(file, 0.675d)
        var desc = switch(petType) {
            case PT.CAT -> 'is a cat'
            case PT.DOG -> 'is a dog'
            default -> 'is unknown'
        }
        "$pet.name $desc"
    }
}
println results.flatten().join('\n')

请注意,该模型超出了普通 GitHub 存储库允许的最大大小,因此您应该按照原始存储库 说明 创建该模型,然后将生成的 model.zip 存储在 resources 文件夹中。

当我们运行脚本时,我们得到以下输出

[main] INFO org.nd4j.linalg.factory.Nd4jBackend - Loaded [CpuBackend] backend
...
[main] INFO org.nd4j.linalg.api.ops.executioner.DefaultOpExecutioner - Blas vendor: [OPENBLAS]
...
==========================================================================================
VertexName (VertexType)                 nIn,nOut       TotalParams    ParamsShape                    Vertex Inputs
==========================================================================================
input_1 (InputVertex)                   -,-            -              -                              -
block1_conv1 (Frozen ConvolutionLayer)  3,64           1792           b:{1,64}, W:{64,3,3,3}         [input_1]
block1_conv2 (Frozen ConvolutionLayer)  64,64          36928          b:{1,64}, W:{64,64,3,3}        [block1_conv1]
block1_pool (Frozen SubsamplingLayer)   -,-            0              -                              [block1_conv2]
block2_conv1 (Frozen ConvolutionLayer)  64,128         73856          b:{1,128}, W:{128,64,3,3}      [block1_pool]
block2_conv2 (Frozen ConvolutionLayer)  128,128        147584         b:{1,128}, W:{128,128,3,3}     [block2_conv1]
block2_pool (Frozen SubsamplingLayer)   -,-            0              -                              [block2_conv2]
block3_conv1 (Frozen ConvolutionLayer)  128,256        295168         b:{1,256}, W:{256,128,3,3}     [block2_pool]
block3_conv2 (Frozen ConvolutionLayer)  256,256        590080         b:{1,256}, W:{256,256,3,3}     [block3_conv1]
block3_conv3 (Frozen ConvolutionLayer)  256,256        590080         b:{1,256}, W:{256,256,3,3}     [block3_conv2]
block3_pool (Frozen SubsamplingLayer)   -,-            0              -                              [block3_conv3]
block4_conv1 (Frozen ConvolutionLayer)  256,512        1180160        b:{1,512}, W:{512,256,3,3}     [block3_pool]
block4_conv2 (Frozen ConvolutionLayer)  512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block4_conv1]
block4_conv3 (Frozen ConvolutionLayer)  512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block4_conv2]
block4_pool (Frozen SubsamplingLayer)   -,-            0              -                              [block4_conv3]
block5_conv1 (Frozen ConvolutionLayer)  512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block4_pool]
block5_conv2 (Frozen ConvolutionLayer)  512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block5_conv1]
block5_conv3 (Frozen ConvolutionLayer)  512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block5_conv2]
block5_pool (Frozen SubsamplingLayer)   -,-            0              -                              [block5_conv3]
flatten (PreprocessorVertex)            -,-            -              -                              [block5_pool]
fc1 (Frozen DenseLayer)                 25088,4096     102764544      b:{1,4096}, W:{25088,4096}     [flatten]
fc2 (Frozen DenseLayer)                 4096,4096      16781312       b:{1,4096}, W:{4096,4096}      [fc1]
predictions (OutputLayer)               4096,2         8194           b:{1,2}, W:{4096,2}            [fc2]
------------------------------------------------------------------------------------------
            Total Parameters:  134268738
        Trainable Parameters:  8194
           Frozen Parameters:  134260544
==========================================================================================
...
Tabby is a cat
Dolly is a cat
Spot is a dog
Spike is a dog
Serpy is a cat
Tweety is unknown
Speedy is a dog
Fuzzy is unknown
Wuzzy is unknown

正如我们所看到的,它正确地预测了猫(虎斑猫和多莉)和狗(斑点和尖刺),但错误地认为蛇(塞尔皮)是猫,乌龟(斯皮迪)是狗。考虑到表情符号图像与训练图像相比缺乏细节,这种缺乏准确性并不出乎意料。如果我们想要更好的结果,我们当然可以使用更好的图像或以不同的方式训练我们的模型,但有趣的是,即使使用表情符号,我们的模型也能取得不错的效果!