前言

之前不是有说过,神经网络可以学会非线性关系,例如圆之类的,今天我们就来尝试一下,目标就是拟合出下面的圆,完整代码见 https://github.com/zong4/AILearning。

无监督学习

大家先自己过一下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 生成圆上的数据点
num_points = 1000
theta = np.linspace(0, 2 * np.pi, num_points)
radius1 = 1
radius2 = 2
x1 = radius1 * np.cos(theta)
y1 = radius1 * np.sin(theta)
x2 = radius2 * np.cos(theta)
y2 = radius2 * np.sin(theta)

data = np.column_stack((np.concatenate((x1, x2)), np.concatenate((y1, y2))))

# 划分训练集和测试集
train_size = int(0.8 * num_points)
train_data = data[:train_size]
test_data = data[train_size:]

# 构建模型
model = keras.Sequential([
layers.Dense(64, activation='relu', input_shape=(2,)),
layers.Dropout(0.5),
layers.Dense(64, activation='relu'),
layers.Dropout(0.5),
layers.Dense(2)
])

model.compile(optimizer=keras.optimizers.Adam(0.001), loss='mse')

test_data_x = radius1 * np.cos(theta) * 0.5
test_data_y = radius1 * np.sin(theta) * 0.5
test_data = np.column_stack((test_data_x, test_data_y))

# 训练模型
history = model.fit(train_data, train_data, epochs=100, verbose=1)

# 进行预测
predictions = model.predict(test_data)

细心的朋友应该发现了,这里的最后一层网络居然是2个神经元,而且模型训练时居然没有输入训练集标签,也就是要预测的数据。

这也是无监督学习最大的特点,就是输入数据同时作为输入和目标(标签),模型的任务是学习数据之间的关系,所以最后一层网络中的两个神经元就分别代表x和y。

自编码器原理

自编码器是一种无监督学习模型,其目标是将输入数据重构为输出数据。

它由两部分组成:编码器(Encoder)和解码器(Decoder),编码器将输入数据压缩成低维表示,解码器则将这个低维表示重构为与输入数据相似的输出。

有点类似于对抗式生成网络(GAN),但GAN的目标是生成与真实数据相似的数据,而自编码器的目标是重构输入数据。

监督学习

同样的问题,我们也可以用监督学习来做,只需把最后一层网络改成1个神经元,也就是y,然后训练时同时输入标签数据就行了,大家就自行尝试吧。

结果

以下分别是无监督学习学习一个圆和学习两个圆的结果。

以及同样的条件下监督学习学习的结果。

loss 我忘记了,大家就自己品吧。

  1. 看上去无监督学习随着数据的增加效果变好了,说明是真的有在学习关系(函数表达式)。
  2. 而监督学习却随着数据的增加效果反而变差了,说明它没法理解这种嵌套圆的数据,也可以说是模型限制,但是要搭出一个能学习这种数据的模型也是挺麻烦的。