ClipDraw: Drawing as a Form of Communicating with AI A

作者:禅与计算机程序设计艺术

1.简介

随着人工智能技术的飞速发展、应用落地及其广泛应用,在智能交互领域取得重大突破,越来越多的人开始重新思考人机交互方式。而语言和画图作为人类和机器沟通的方式,被视作最优秀的通信方式之一。然而,现代人工智能技术面临着巨大的挑战——从文本到图像再到视频,如何让智能体获取到高质量的信息并通过语言或者图片进行有效沟通是一个难题。因此,针对这一问题,本文提出了一种新的交互方式——ClipDraw。 ClipDraw 把绘画当做一种人机对话形式,与智能体进行即时沟通。用户通过触屏设备(例如笔记本电脑、手机或平板电脑)绘制自己的想法,智能体也会用相同的手法作出响应,并将他们的意图和思绪传达给对方,达成共鸣。智能体的语音识别功能可以使得双方语速一致,同时还可以减少语言切换的时间,降低沟通成本。除此之外,为了能够更加准确地表达用户的想法,智能体可以结合计算机视觉技术,识别用户的脸部表情、姿态等信息,进一步丰富对话内容。 基于上述目标,本文设计了 ClipDraw 框架,并开发了 ClipDraw 智能体程序。所开发的智能体程序可用于控制计算机、手机、平板电脑甚至打印机,实现人机对话。能够自动生成具有独特风格和情感的图像,帮助用户快速准确地表达自己的想法。

2.基本概念和术语

2.1 绘图描述符

ClipDraw 框架中的绘图描述符是一个描述客观事物的符号,它由关键词、图形、颜色、线条等构成。描述符可以用来描绘某种对象的形状和特征,使得智能体可以通过符号来理解含义。如:“橙色的圆”、“蓝色的椭圆”、“宽的矩形”等。

2.2 绘图动作

ClipDraw 框架中的绘图动作是指通过具体的绘画行为来触发智能体的响应,它由起始点、终止点、笔触大小、笔触粗细、方向、画笔类型等构成。画笔类型的选择十分重要,不同的画笔会影响画出的图片的清晰度和对话效果。

2.3 模型训练与推理

在 ClipDraw 框架中,用户绘制的符号信息和动作序列作为输入数据,通过模型训练得到一个抽象的图像表示,之后将该图像送入神经网络,生成一系列的声音命令。模拟器根据这些指令,控制输出设备产生对应的图像画面,完成对话。

3.核心算法和具体操作步骤

3.1 模型搭建

3.1.1 数据集准备

为了能够训练出高质量的图片描述符和动作轨迹,我们收集了一系列游戏角色的图片和动作,并按照相同的格式制作成了数据集。

3.1.2 CNN-LSTM 模型结构

为了能够准确捕捉图片的全局上下文信息,我们采用了一个双层的 CNN-LSTM 模型。其中,CNN 是卷积神经网络,用于提取局部特征;LSTM 是长短期记忆网络,用于提取全局特征。最终的输出则是一个张量,代表整个图片的语义。

3.1.3 训练策略

为了使模型在训练过程中能够快速收敛并避免过拟合,我们设置了两个损失函数,分别是图片描述符和动作轨迹的平均二次误差。

3.1.4 模型参数设置

在模型训练前,我们需要设置以下几个超参数:

  • 输入尺寸 - 根据实际的数据集,我们可以调整模型的输入尺寸,将较小的尺寸缩放到合适的范围。
  • 学习率 - 学习率通常是影响模型训练收敛速度的一个重要因素。如果模型的学习率太大,可能会导致模型不稳定或者欠拟合。我们可以先用较大的学习率尝试几轮训练,然后逐步减小学习率来获得更好的结果。
  • 批大小 - 批大小决定了每次梯度更新时的样本数量。一个大的批大小能够更好地利用 GPU 的计算资源,但是过大的批大小又可能导致内存溢出。通常,批大小在 32~512 之间调节。

    3.2 模型推理过程

    模型推理过程可以分为两步:

    3.2.1 描绘和分析

    首先,我们将用户的绘制转换为符号描述符,然后送入模型,得到图片表示。然后,通过图片表示和其他用户输入,系统分析用户的意图,并生成对应指令。

    3.2.2 命令执行

    接下来,指令会被发送给模拟器,模拟器按照指令将输出图像渲染出来,完成对话。

    3.3 模型代码示例

    import tensorflow as tf
    from PIL import Image
    

class ClipsDrawer(object): def init(self, input_size=256, num_classes=7): self.input_size = input_size self.num_classes = num_classes

# build the model architecture
def build_model(self):
    inputs = tf.keras.layers.Input(shape=(None, None, 3))

    x = tf.keras.layers.Conv2D(filters=32, kernel_size=3, padding='same')(inputs)
    x = tf.keras.layers.BatchNormalization()(x)
    x = tf.keras.activations.relu(x)
    x = tf.keras.layers.MaxPooling2D(pool_size=2)(x)

    for i in range(2):
        x = tf.keras.layers.Conv2D(filters=32*(i+2), kernel_size=3, padding='same')(x)
        x = tf.keras.layers.BatchNormalization()(x)
        x = tf.keras.activations.relu(x)
        x = tf.keras.layers.MaxPooling2D(pool_size=2)(x)

    x = tf.keras.layers.Conv2D(filters=128, kernel_size=3, padding='same')(x)
    x = tf.keras.layers.BatchNormalization()(x)
    x = tf.keras.activations.relu(x)
    x = tf.keras.layers.GlobalAveragePooling2D()(x)

    lstm_units = 512
    outputs, state_h, state_c = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(lstm_units, return_sequences=True, return_state=True))(x)

    logits = tf.keras.layers.Dense(units=self.num_classes, activation='softmax')(outputs)
    model = tf.keras.models.Model(inputs=[inputs], outputs=[logits])
    optimizer = tf.keras.optimizers.Adam()
    loss_fn = 'categorical_crossentropy'
    metrics = ['accuracy']

    model.compile(optimizer=optimizer, loss=loss_fn, metrics=metrics)
    return model

# load dataset from files and preprocess images
def preprocess_data(self, image_paths, labels):
    imgs = []
    for path in image_paths:
        img = np.array(Image.open(path).resize((self.input_size, self.input_size))) / 255.
        imgs.append(img)

    imgs = np.stack(imgs, axis=0)
    onehot_labels = to_categorical(labels, num_classes=self.num_classes)
    return (imgs, onehot_labels)

# train the model on preprocessed data
def train(self, image_paths, labels, epochs=10, batch_size=32):
    model = self.build_model()
    data = self.preprocess_data(image_paths, labels)
    model.fit(data[0], data[1], validation_split=0.1, epochs=epochs, batch_size=batch_size)

# generate output command based on user's drawing and previous history
def predict(self, image):
    pass

drawer = ClipsDrawer(input_size=256, num_classes=7) train_images = [...] train_labels = [...] drawer.train(train_images, train_labels)

test_images = [...] for img in test_images: pred_label = drawer.predict(img) ```

猜你喜欢

转载自blog.csdn.net/universsky2015/article/details/133566283