-
Notifications
You must be signed in to change notification settings - Fork 0
/
DINEOF.py
100 lines (87 loc) · 3.13 KB
/
DINEOF.py
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
'''
Author: your name
Date: 2021-07-21 09:31:50
LastEditTime: 2021-07-26 10:49:08
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: /DINEOF_GPU/DINEOF.py
'''
import torch
import numpy as np
from torch import unsqueeze
import xarray as xr
import scipy
def load_data():
nc = xr.open_dataset('/data/Chenjq/Southsea_OCCCI/OCCCI/CCI_ALL-v5.0-DAILY.nc')
data = np.transpose(nc.chlor_a.data,(1,2,0))
num_lat = data.shape[0]
num_lon = data.shape[1]
num_time = data.shape[2]
# 1 参与运算 0 不参与运算
mask = np.ones((num_lat,num_lon))
for la in range(num_lat):
for lo in range(num_lon):
if np.sum(np.isnan(data[la,lo,:]))>int(0.9*num_time):
mask[la,lo] = 0
return data,mask
def dineof_gpu(data,mask,Max_EOF=3,rms_delta = 0.001):
'''
input: data (lat,lon,time)
mask (lat,lon)
Max_EOF 最大的EOF模态
rms_delta 最小的误差阈值
'''
x = data[mask==1] # 剔除掉陆地
# 得到确实数据的索引
index = np.arange(len(x.reshape(-1)))
nan_idx = np.where(np.isnan(x.reshape(-1)))
# 交叉验证索引
val_idx_random = np.random.choice(index,int(0.1*len(index)))
# val_idx = np.concatenate([val_idx_random,nan_idx[0]])
val_idx = val_idx_random
# 将缺失值替换为 0
x[np.isnan(x)]=0
# 初始化一些参属
eof_n = 0
RMS = []
rms_prev = np.inf
perform = []
rms_now = 0
while((rms_prev - rms_now > rms_delta)&(eof_n<=Max_EOF)):
while(rms_prev-rms_now>rms_delta):
rms_prev = rms_now
xx = torch.from_numpy(x).cuda(1)
U,S,V = torch.svd(xx)
Reci = torch.mm(torch.mul(unsqueeze(U[:,eof_n],dim=1),S[eof_n]),unsqueeze(V[:,eof_n],dim=1).T)
Reci = Reci.cpu().numpy()
# 需要释放GPU
torch.cuda.empty_cache()
rms_now = np.sqrt(np.nanmean(np.power(Reci.reshape(-1)[val_idx]-x.reshape(-1)[val_idx],2)))
RMS.append(rms_now)
perform.append((eof_n,rms_now))
print((eof_n,rms_now))
if(rms_now==min(RMS)):
data[mask==1] = Reci
print("do it again")
perform_best = (eof_n,rms_now)
rms_prev = rms_now
xx = torch.from_numpy(x).cuda(1)
U,S,V = torch.svd(xx)
Reci = torch.mm(torch.mul(unsqueeze(U[:,eof_n],dim=1),S[eof_n]),unsqueeze(V[:,eof_n],dim=1).T)
Reci = Reci.cpu().numpy()
# 需要释放GPU
torch.cuda.empty_cache()
rms_now = np.sqrt(np.nanmean(np.power(Reci.reshape(-1)[val_idx]-x.reshape(-1)[val_idx],2)))
RMS.append(rms_now)
perform.append((eof_n,rms_now))
print((eof_n,rms_now))
if(rms_now==min(RMS)):
data[mask==1] = Reci
print("do it again")
perform_best = (eof_n,rms_now)
eof_n+=1
return data,perform,perform_best
if __name__=='__main__':
data,mask = load_data()
data,perform,perform_best= dineof_gpu(data,mask,Max_EOF=8,rms_delta = 0.00001)
np.save('filled.npy',data,)