网站首页 > 技术教程 正文
自编码
自编码器是另一种用于以压缩方式再现输入的神经网络。自编码器有一个特殊的特性,即输入神经元的数目与输出神经元的数目相同。
请看上图。Autoencoder的目标是在输出层创建输入的表示,使得输出和输入是相似的。
Autoencoder的实际用途是确定具有最低数据丢失量的输入数据的压缩版本。这与主成分分析非常相似,但是是以黑盒的方式进行的。自编码器的编码器部分在压缩数据的同时,确保重要数据不丢失,但数据的大小减少。
使用Autoencoder进行插值的缺点是压缩数据是一种黑盒表示法—我们不知道压缩版本中数据的结构。
假设有一个有10个参数的数据集,我们在这个数据上训练一个自编码器。编码器并没有为了更好的表示而忽略一些参数,但是它将这些参数融合在一起以创建一个压缩的版本(将参数的数量从10个减少到5个)。
自编码器有两个部分,编码器和解码器。编码器压缩输入数据,解码器则相反地产生数据的未压缩版本,以产生尽可能接近原始输入的重构输入。
插值方法
插值是在两个数据点之间猜测函数值的过程。例如,给定x=[1,3,5,7,9],y=[230.02,321.01,305.00,245.75,345.62],再给定x=4,你想知道y的值是多少。
有大量的插值方法,有些是基于模型的,有些是无模型的,即数据驱动的。实现插值最常用的方法是通过数据拟合。例如,使用线性回归分析将线性模型拟合到给定的数据。
在线性回归中,给定预测变量X和响应变量Y,使用公式Y=β0+β1X拟合数据,其中β0和β1使用最小二乘拟合确定。
顾名思义,线性回归是线性的,也就是说,即使预测变量和响应变量之间的关系可能是非线性的,它也是一条直线或者超平面。
然而,最普遍的插值形式是多项式拟合。给定k个采样点,拟合k-1次多项式是很简单的。给定数据集*{xi, yi}*,多项式拟合是通过确定函数的多项式系数ai来获得的。
通过以下表达式求解矩阵求逆:
一旦我们有了系数ai,我们就可以找到任意x的函数f的值。
有一些多项式拟合的特殊情况,其中用分段三次多项式来拟合数据。其他一些非参数方法包括三次样条、平滑样条、回归样条、核回归和密度估计。
本文的重点不是多项式拟合,而是插值。多项式拟合恰好有助于插值。多项式拟合方法存在一个问题——无论是参数拟合还是非参数拟合,它们的行为方式都与所教的相同。它的意思是,如果数据是干净的,拟合将是干净和平滑的,但如果数据是有噪声的,拟合将是有噪声的。
此问题在传感器数据中更为普遍,例如,从心率传感器捕获的心跳数据、从激光雷达获取的距离数据、从汽车获取的CAN总线速度数据、GPS数据等。
https://medium.com/analytics-vidhya/how-does-a-self-driving-vehicle-see-using-lidar-49f569ededf2
此外,由于噪声的存在,它们更难处理,特别是当你的算法需要对这些数据执行双重或二阶导数时。
一般来说,这些传感器数据是时间序列数据,即它们是随时间收集的,因此响应变量可能是一些物理量,例如速度、物体与安装在自动驾驶汽车顶部的激光雷达的距离、心率,并且预测变量是时间。
在对这些数据进行操作时,可能有几个目标:我想将数据插值到某个时间戳上,在该时间戳上,我的传感器无法记录任何响应,但由于传感器在实时世界中工作,并且由于潜在的物理原因,这些数据保持嘈杂,我还想要一个可靠的插值,不受传感器噪声的影响。
此外,我的要求还可能包括此类时间序列数据的导数。但是导数往往会放大潜在时间序列数据中的噪声。如果有一种方法,我可以得到数据的底层表示,同时抛弃噪声呢?在这种情况下,自编码器可以来实现我的目标。
自编码器作为插补器
为了演示使用Autoencoder的去噪+插值目标,我使用了一个由我的实验室从车辆收集的距离数据的例子,其中因变量是前一辆车在我的车辆前面的距离,自变量是时间。
我在GitHub repo上提供了一小部分数据,作为演示的一部分,你可以自由使用。但是它非常小,除了本文所描述的教程之外,没有其他用途。
https://github.com/rahulbhadani/medium.com/blob/master/data/lead_dist_sample.csv
好了,现在该编码了。
注意:在使用数据之前,我应该指出时间(自变量)和响应变量(因变量)必须重新缩放。在我的例子中,原始时间从1594247088.289515开始(POSIX格式,以秒为单位),到1594247110.290019结束。我使用公式(time - start_time)/(end_time - start_time)规范化了我的时间值。类似地,响应变量使用(message - message_min)/(message_max -message_min)进行规范化。
我的GitHub中提供的示例数据已经标准化了,你可以直接重用它。
训练
import glob
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
df = pd.read_csv("../data/lead_dist_sample.csv")
time = df['Time']
message = df['Message']
import tensorflow as tf
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(units = 1, activation = 'linear', input_shape=[1]))
model.add(tf.keras.layers.Dense(units = 128, activation = 'relu'))
model.add(tf.keras.layers.Dense(units = 64, activation = 'relu'))
model.add(tf.keras.layers.Dense(units = 32, activation = 'relu'))
model.add(tf.keras.layers.Dense(units = 64, activation = 'relu'))
model.add(tf.keras.layers.Dense(units = 128, activation = 'relu'))
model.add(tf.keras.layers.Dense(units = 1, activation = 'linear'))
model.compile(loss='mse', optimizer="adam")
model.summary()
# 训练
model.fit( time, message, epochs=1000, verbose=True)
如你所见,我没有执行任何正则化,因为我要进行过拟合,以便能够充分利用数据的基本特征。现在是时候做出预测了。
你将看到,在进行预测之前,我将时间轴重新缩放回原始值。对于本例,time_original[0] = 1594247088.289515 ,time_original[-1] = 1594247110.290019 , msg_min = 33, msg_max = 112
newtimepoints_scaled = np.linspace(time[0] - (time[1] - time[0]),time[-1], 10000)
y_predicted_scaled = model.predict(newtimepoints_scaled)
newtimepoints = newtimepoints_scaled*(time_original[-1] - time_original[0]) + time_original[0]
y_predicted = y_predicted_scaled*(msg_max - msg_min) + msg_min
注意,我正在用可变的newtimepoints_scaled创建更密集的时间点,它允许我在看不见的时间点上插入数据。最后,曲线如下:
# 显示结果
import matplotlib.pylab as pylab
params = {'legend.fontsize': 'x-large',
'figure.figsize': (15, 5),
'axes.labelsize': 'x-large',
'axes.titlesize':'x-large',
'xtick.labelsize':'x-large',
'ytick.labelsize':'x-large'}
pylab.rcParams.update(params)
plt.scatter(time*(1594247110.290019 - 1594247088.289515) + 1594247088.289515, message*(112 - 33) + 33, label='Original Data')
plt.scatter(newtimepoints, y_predicted, c = 'red', s = 1, label = 'Interpolated Data')
plt.xlabel('Time')
plt.ylabel('Message')
plt.legend()
plt.show()
结尾
虽然我只训练了1000个epoch,但如果你的数据很大的话,你的训练可能不会那么短。这种方法的最大优点是采用导数,从下面的图中可以看出,对原始数据执行的导数很差——甚至可能不能代表真正的导数!
df_interpolation = pd.DataFrame()
df_interpolation['Time'] = newtimepoints
df_interpolation['Message'] = y_predicted
df_interpolation['diff'] = df_interpolation['Message'].diff()/df_interpolation['Time'].diff()
df_original = pd.DataFrame()
df_original['Time'] = time*(1594247110.290019 - 1594247088.289515) + 1594247088.289515
df_original['Message'] = message*(112 - 33) + 33
df_original['diff'] = df_original['Message'].diff()/df_original['Time'].diff()
# 显示结果
import matplotlib.pylab as pylab
params = {'legend.fontsize': 'x-large',
'figure.figsize': (15, 5),
'axes.labelsize': 'x-large',
'axes.titlesize':'x-large',
'xtick.labelsize':'x-large',
'ytick.labelsize':'x-large'}
pylab.rcParams.update(params)
plt.scatter(df_original['Time'], df_original['diff'], label='Derivative on Original Data')
plt.scatter(df_interpolation['Time'], df_interpolation['diff'], s= 10, c = 'red', label='Derivative on Interpolated Data')
plt.xlabel('Time')
plt.ylabel('Message')
plt.legend()
plt.show()
这种方法唯一的缺点是时间复杂。根据数据点的数量,可能需要数小时才能完成训练。但是,如果你可以访问高性能计算集群、amazonec2或类似的应用程序,那么训练自编码器可能不会花费太多时间。
复制本教程的笔记本可以在我的GitHub上找到
https://github.com/rahulbhadani/medium.com/blob/master/01_02_2021/AutoEncoder_Interpolation_TF2.ipynb.
文章的一个较长的版本被张贴在ArXiv.org网站:https://arxiv.org/abs/2101.00853
如果这篇文章对你有帮助,请使用以下引文来引用本作品:
Rahul Bhadani. Autoencoder for interpolation. arXiv preprint arXiv:2101.00853, 2021.
或:
@article{bhadani2021autoencoder,
title={AutoEncoder for Interpolation},
author={Rahul Bhadani},
year={2021},
eprint={2101.00853},
archivePrefix={arXiv},
primaryClass={stat.ML},
journal={arXiv preprint arXiv:2101.00853},
}
猜你喜欢
- 2024-10-16 机器学习中应用的范数 机器学习中常见的超参照数调整
- 2024-10-16 有限元求解:结构应力法如何实现的网格不敏感呢?
- 2024-10-16 论利用粒子群算法求解测距定位方程
- 2024-10-16 推荐系统多样性——DPP篇 推荐系统的模型
- 2024-10-16 线性代数主要可以从几个角度去理解: (1)线性方程...
- 2024-10-16 numpy入门 day05 numpy eig
- 2024-10-16 python多进程矩阵计算的应用示例 python多进程队列
- 2024-10-16 计量课后5.4(大数据202230906137 HSl)
- 2024-10-16 Matlab矩阵的简单操作 matlab如何进行矩阵运算
- 2024-10-16 鸡兔同笼问题多种数学方法解答 百分之九十的人做不出来
你 发表评论:
欢迎- 05-05从virsh当中学习QEMU/KVM启动命令
- 05-05Win10 BCD文件损坏怎么修复?(bcd文件损坏win7)
- 05-05亚马逊春节假期期间的店铺管理设置
- 05-051分钟总结常用k8s常用诊断教程(k8s常见故障)
- 05-05VisiPics重复图片查找软件中文汉化教程
- 05-05微服务的发布实现方式1灰度实现(微服务实现原理)
- 05-05轻松掌握Java多线程 - 第二章:线程的生命周期
- 05-05德拉诺之王邪DK报告:PVE向小测试及分析
- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)