0%

人工智能海底地形反演(3)-张量构建和归一化

上两节分别介绍了单波束数据质控和卫星测高的重力数据处理,我们发现经过质控的单波束作为训练数据,可以明显提高水深反演的精度,重力异常信号中的短波分量和地形非常相关,加入短波重力有可能大幅提高水深反演精度。

今天介绍AI反演水深最后的前奏:张量构建和归一化处理。

张量的构建

人工智能的数据表示方式是存储在Numpy里的多维数组,数据类型是ndarray,在AI领域它还有一个更具B格的名字:张量(tensor)。一般来说,当前所有机器学习系统都使用张量作为基本数据结构,张量在AI领域是非常重要的概念,以至于Google的TensorFlow都直接以它来命名。

下表是不同维度(TensorFlow中也成为秩、阶数、度数或者是n维)的张量含义:

维度(秩) 数学实体
0 标量(只有大小)
1 向量 (有大小和方向)
2 矩阵 (由数构成的表)
3 3 维张量 (由数构成的方体)
n n 维张量 (你可以自行想象一下)

在水深反演中,我们首先也构建这样的多维张量。因为DNN和CNN的张量略有不同,这里分开介绍它们的构建方式。

DNN

假设人工智能训练数据的输入包括lat,lon,ga,vgg,evd,nvd,sg,输出只有一个od:

  • lat:latitude
  • lon:longitude
  • ga:gravity anomaly
  • vgg:vertical gravity gradient
  • evd:east-west vertical deflection
  • nvd:north-south vertical deflection
  • sg:short wavelength gravity anomaly
  • od:ocean depth

因为在DNN中,没有要求输入必须是图像,所以它接受的输入张量可以是二维矩阵。假设有10000个水深训练点,那么输入张量大小为(10000,7),输出张量为(10000,1)。注意位置信息并不单独占据两个维度,而是作为输入保存在了张量内部。

在python中使用numpy的基本函数可完成张量构建:

1
2
input =  np.concatenate((lon,lat,ga,vgg,evd,nvd,sg), axis=1)
output = np.reshape(free_short[:,2],(len(free_short[:, 2]),1))

CNN

CNN的操作对象必须是图像,因此张量必须是4维度的。CNN的张量构建稍微复杂一些,消耗的时间也长一点。整体思路是:根据经纬度确定index,然后通过index确定矩形范围,再提取重力异常等数据,增加数组维度的深度。

Index确定

使用get_indexer函数得到船测水深点的经纬度在重力网格数组中的存储位置:

1
2
con_lat_index=free_15s.indexes["lat"].get_indexer(control.values[:,1],method="nearest")
con_lon_index=free_15s.indexes["lon"].get_indexer(control.values[:,0],method="nearest")

比如我们想得到index=126处的5×5图像:

1
free_15s.isel(lat=slice(126-2,126+3,1),lon=slice(1056-2,1056+3,1))

根据这个逻辑写循环增加数据参数,假设CNN输入是5×5大小的图像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
temp2 = []
for i in range(len(control["lat"])):
temp = free_15s.isel(lat=slice(con_lat_index[i]-2,con_lat_index[i]+3,1),lon=slice(con_lon_index[i]-2,con_lon_index[i]+3,1))
temp_vgg = vgg_15s.isel(lat=slice(con_lat_index[i]-2,con_lat_index[i]+3,1),lon=slice(con_lon_index[i]-2,con_lon_index[i]+3,1))
temp_e = east_15s.isel(lat=slice(con_lat_index[i]-2,con_lat_index[i]+3,1),lon=slice(con_lon_index[i]-2,con_lon_index[i]+3,1))
temp_n = north_15s.isel(lat=slice(con_lat_index[i]-2,con_lat_index[i]+3,1),lon=slice(con_lon_index[i]-2,con_lon_index[i]+3,1))
temp_shortg = shortg_15s.isel(lat=slice(con_lat_index[i]-2,con_lat_index[i]+3,1),lon=slice(con_lon_index[i]-2,con_lon_index[i]+3,1))
lat1 = free_15s.lat[con_lat_index[i]-2:con_lat_index[i]+3]
lon1 = free_15s.lon[con_lon_index[i]-2:con_lon_index[i]+3]
LON,LAT = np.meshgrid(lon1,lat1)
temp1 = np.concatenate([np.reshape(LON,(5,5,1)),np.reshape(LAT,(5,5,1)),np.reshape(temp.values,(5,5,1)),np.reshape(temp_vgg.values,(5,5,1)),np.reshape(temp_e.values,(5,5,1)),np.reshape(temp_n.values,(5,5,1)),np.reshape(temp_shortg.values,(5,5,1))],axis=2)
temp2.append(temp1)
temp2 = np.array(temp2)
temp2.shape

最终得到的张量空间是(10000, 5, 5, 7)

使用index来确定位置,可以加速张量构建。

归一化

归一化是将一个变量的取值缩放到[0~1]之间,也称数据标准化(Normalization)。数据标准化处理是AI的一项基础工作,不同评价指标往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要对数据进行归一化处理,解决数据指标之间的可比性问题。

优点:提高梯度下降求解最优解的速度;归一化有可能提高精度

在DNN中,我们使用了MinMaxScalertransform函数完成归一化:

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
# normalization
y_train2 = np.reshape(y_train1[:, 2], (len(y_train1[:, 2]), 1)) # depth

scalerlon = MinMaxScaler().fit(x_lon)
scalerlat = MinMaxScaler().fit(x_lat)
scalershort = MinMaxScaler().fit(control_short)
scalerga = MinMaxScaler().fit(control_ga)
scalervgg = MinMaxScaler().fit(control_vgg)
scalerevd = MinMaxScaler().fit(control_evd)
scalernvd = MinMaxScaler().fit(control_nvd)
scalersed = MinMaxScaler().fit(control_sed)
scalerage = MinMaxScaler().fit(control_age)
scalermoho = MinMaxScaler().fit(control_moho)
scalermag = MinMaxScaler().fit(control_mag)
scalerytrain = MinMaxScaler().fit(y_train2)

lat_train = scalerlat.transform(x_lat)
lon_train = scalerlon.transform(x_lon)
short_train = scalershort.transform(control_short)
ga_train = scalerga.transform(control_ga)
vgg_train = scalervgg.transform(control_vgg)
evd_train = scalerevd.transform(control_evd)
nvd_train = scalernvd.transform(control_nvd)
sed_train = scalersed.transform(control_sed)
age_train = scalerage.transform(control_age)
moho_train = scalermoho.transform(control_moho)
mag_train = scalermag.transform(control_mag)
y_trian = scalerytrain.transform(y_train2)

在CNN中,我们使用一样的方法完成归一化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
m,n,k,p = np.shape(temp2)
scalerlon = MinMaxScaler().fit(np.reshape(temp2[:,:,:,4],(m*n*k,1)))
scalerlat = MinMaxScaler().fit(np.reshape(temp2[:,:,:,5],(m*n*k,1)))
scalerfree = MinMaxScaler().fit(np.reshape(temp2[:,:,:,0],(m*n*k,1)))
scalervgg = MinMaxScaler().fit(np.reshape(temp2[:,:,:,1],(m*n*k,1)))
scalernvd = MinMaxScaler().fit(np.reshape(temp2[:,:,:,2],(m*n*k,1)))
scalerevd = MinMaxScaler().fit(np.reshape(temp2[:,:,:,3],(m*n*k,1)))
# scalermae = MinMaxScaler().fit(np.reshape(temp2[:,:,:,6],(m*n*k,1)))
scalerdepth = MinMaxScaler().fit(np.reshape(control.values[:,2],(-1,1)))
lon_train = scalerlon.transform(np.reshape(temp2[:,:,:,4],(m*n*k,1)))
lat_train = scalerlat.transform(np.reshape(temp2[:,:,:,5],(m*n*k,1)))
free_train = scalerfree.transform(np.reshape(temp2[:,:,:,0],(m*n*k,1)))
vgg_train = scalervgg.transform(np.reshape(temp2[:,:,:,1],(m*n*k,1)))
nvd_train = scalernvd.transform(np.reshape(temp2[:,:,:,2],(m*n*k,1)))
evd_train = scalerevd.transform(np.reshape(temp2[:,:,:,3],(m*n*k,1)))
# mae_train = scalerevd.transform(np.reshape(temp2[:,:,:,6],(m*n*k,1)))
x_train = np.reshape(np.concatenate([free_train,vgg_train,nvd_train,evd_train,lon_train,lat_train],axis=1),(m,n,k,p))
y_train = scalerdepth.transform(np.reshape(control.values[:,2],(-1,1)))

注意对实测水深label也必须做归一化处理。

小结

  • 张量是各种维度的向量和矩阵的统称。CNN的张量维度大,比较消耗算力,DNN张量是二维矩阵,计算简单。
  • 归一化是为了解决不同量纲的数据差异问题,提高AI训练质量。

下节预告

完成全部的人工智能的重力水深反演,并展现出高精度的AI水深反演结果。

  • DNN和CNN网络设计
  • 水深预测和评估

俺最近更新很慢,希望早点上手的伙伴可查看完整代码:https://github.com/GenericAltimetryTools/AIBathy

人工智能水深反演比赛的企业总冠名权征集

为提高奖金数额,促进参赛积极性,在保留原奖金的情况下,组委现向全社会征集比赛总冠名权,请有意向的海洋遥感、海洋测绘、人工智能等领域的企业私信联系。