深度学习和 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 组件,然后使用缓冲图像保存。这导致图像质量很差
因此,图像推理效果也很差。某些平台上的最新 JDK 版本可能效果更好,但我们放弃了这种方法。
相反,我们使用了 Noto 彩色表情符号 字体中的表情符号图像文件,并将它们保存在 resources
文件夹中的宠物类型下。这些图像看起来要好得多
以下是使用这些保存的图像来检测动物类型的代码(请注意,由于我们有两个 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
正如我们所看到的,它正确地预测了猫(虎斑猫和多莉)和狗(斑点和尖刺),但错误地认为蛇(塞尔皮)是猫,乌龟(斯皮迪)是狗。考虑到表情符号图像与训练图像相比缺乏细节,这种缺乏准确性并不出乎意料。如果我们想要更好的结果,我们当然可以使用更好的图像或以不同的方式训练我们的模型,但有趣的是,即使使用表情符号,我们的模型也能取得不错的效果!