├── CNN ├── Image │ └── 1.py ├── main.py ├── res50.py └── trajectory_mapping.py ├── CNNTCN ├── Geolife │ └── geolife ├── geolife_test.py ├── model.py ├── tcn.py ├── utilsC.py └── utilsT.py ├── Geolife └── 1.py └── README.md /CNN/Image/1.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /CNN/main.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn, optim 3 | import torchvision.transforms as transforms 4 | import torchvision 5 | from torch.utils.data import DataLoader 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | from torch.autograd import Variable 9 | import torch.optim as optim 10 | #import matplotlib.pyplot as plt 11 | import numpy as np 12 | import sys, os 13 | sys.path.append('/...') 14 | from CNN.res50 import ResNet50 15 | import matplotlib.pyplot as plt 16 | from math import sin,cos,tan,pi,radians,asin,sqrt,degrees,atan2 17 | import datetime 18 | import time 19 | import os 20 | import codecs 21 | from sklearn import preprocessing 22 | from PIL import Image 23 | 24 | classes = ('0','1', '2', '3', '4', '5', '6') 25 | deltalon = 0.3 26 | deltalat = 0.3 27 | #grid image consisted of h*l (h*w in the paper),grid cell is consisted of a*a 28 | h = 50 29 | l = 50 30 | a = 1 31 | device = torch.device('cuda') 32 | 33 | def loaddata(path,batchsz): 34 | trainset = torchvision.datasets.ImageFolder(path, 35 | transform=transforms.Compose([ 36 | transforms.Resize((32, 32)), 37 | 38 | transforms.CenterCrop(32), 39 | transforms.ToTensor()]) 40 | ) 41 | trainloader = torch.utils.data.DataLoader(trainset, batch_size=batchsz, 42 | shuffle=True, num_workers=2) 43 | return trainloader 44 | 45 | def main(): 46 | batchsz = 64 47 | 48 | path1 = "/.../CNN/Image/Geolife/train" # direction of train set of Image 49 | Image_train = loaddata(path1, batchsz) 50 | 51 | x, label = iter(Image_train).next() 52 | print('x:', x.shape, 'label:', label.shape) 53 | 54 | model = ResNet50().to(device) 55 | 56 | criteon = nn.CrossEntropyLoss().to(device) 57 | optimizer = optim.Adam(model.parameters(), lr=1e-3) 58 | 59 | for epoch in range(80): 60 | model.train() 61 | for batchidx, (x, label) in enumerate(Image_train): 62 | x, label = x.to(device), label.to(device) 63 | 64 | logits = model(x) 65 | loss = criteon(logits, label) 66 | 67 | # backprop 68 | optimizer.zero_grad() 69 | loss.backward() 70 | optimizer.step() 71 | 72 | print(epoch, 'loss:', loss.item()) 73 | model.eval() 74 | 75 | 76 | print('Finished Training') 77 | # save the parameters of trained network 78 | torch.save(model, 'model.pkl') 79 | torch.save(model.state_dict(), 'model_params.pkl') 80 | 81 | def test(): 82 | batchsz = 64 83 | 84 | path2 = "/.../CNN/Image/Geolife/test" 85 | Image_test = loaddata(path2,batchsz) 86 | 87 | start_time = time.time() 88 | 89 | model = torch.load('model.pkl') 90 | model = model.to(device) 91 | 92 | with torch.no_grad(): 93 | total_num = 0 94 | total_correct = 0 95 | 96 | for x, label in Image_test: 97 | x, label = x.to(device), label.to(device) 98 | 99 | logits = model(x) 100 | 101 | pred = logits.argmax(dim=1) 102 | correct = torch.eq(pred,label).float().sum().item() 103 | total_correct += correct 104 | total_num += x.size(0) 105 | 106 | acc = total_correct/total_num 107 | print('test acc:{}/{}'.format(total_correct,total_num),acc) 108 | 109 | end_time = time.time() 110 | print("test time:{:.2f}".format(end_time-start_time)) 111 | 112 | if __name__ == '__main__': 113 | #main() 114 | test() 115 | -------------------------------------------------------------------------------- /CNN/res50.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.nn import functional as F 4 | 5 | class ResNet50BasicBlock(nn.Module): 6 | def __init__(self, in_channel, outs, kernerl_size, stride, padding): 7 | super(ResNet50BasicBlock, self).__init__() 8 | self.conv1 = nn.Conv2d(in_channel, outs[0], kernel_size=kernerl_size[0], stride=stride[0], padding=padding[0]) 9 | self.bn1 = nn.BatchNorm2d(outs[0]) 10 | self.conv2 = nn.Conv2d(outs[0], outs[1], kernel_size=kernerl_size[1], stride=stride[0], padding=padding[1]) 11 | self.bn2 = nn.BatchNorm2d(outs[1]) 12 | self.conv3 = nn.Conv2d(outs[1], outs[2], kernel_size=kernerl_size[2], stride=stride[0], padding=padding[2]) 13 | self.bn3 = nn.BatchNorm2d(outs[2]) 14 | 15 | def forward(self, x): 16 | out = self.conv1(x) 17 | out = F.relu(self.bn1(out)) 18 | 19 | out = self.conv2(out) 20 | out = F.relu(self.bn2(out)) 21 | 22 | out = self.conv3(out) 23 | out = self.bn3(out) 24 | 25 | return F.relu(out + x) 26 | 27 | 28 | class ResNet50DownBlock(nn.Module): 29 | def __init__(self, in_channel, outs, kernel_size, stride, padding): 30 | super(ResNet50DownBlock, self).__init__() 31 | # out1, out2, out3 = outs 32 | # print(outs) 33 | self.conv1 = nn.Conv2d(in_channel, outs[0], kernel_size=kernel_size[0], stride=stride[0], padding=padding[0]) 34 | self.bn1 = nn.BatchNorm2d(outs[0]) 35 | self.conv2 = nn.Conv2d(outs[0], outs[1], kernel_size=kernel_size[1], stride=stride[1], padding=padding[1]) 36 | self.bn2 = nn.BatchNorm2d(outs[1]) 37 | self.conv3 = nn.Conv2d(outs[1], outs[2], kernel_size=kernel_size[2], stride=stride[2], padding=padding[2]) 38 | self.bn3 = nn.BatchNorm2d(outs[2]) 39 | 40 | self.extra = nn.Sequential( 41 | nn.Conv2d(in_channel, outs[2], kernel_size=1, stride=stride[3], padding=0), 42 | nn.BatchNorm2d(outs[2]) 43 | ) 44 | 45 | def forward(self, x): 46 | x_shortcut = self.extra(x) 47 | out = self.conv1(x) 48 | out = self.bn1(out) 49 | out = F.relu(out) 50 | 51 | out = self.conv2(out) 52 | out = self.bn2(out) 53 | out = F.relu(out) 54 | 55 | out = self.conv3(out) 56 | out = self.bn3(out) 57 | return F.relu(x_shortcut + out) 58 | 59 | 60 | class ResNet50(nn.Module): 61 | def __init__(self): 62 | super(ResNet50, self).__init__() 63 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3) 64 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) 65 | 66 | self.layer1 = nn.Sequential( 67 | ResNet50DownBlock(64, outs=[64, 64, 256], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]), 68 | ResNet50BasicBlock(256, outs=[64, 64, 256], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]), 69 | ResNet50BasicBlock(256, outs=[64, 64, 256], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]), 70 | ) 71 | 72 | self.layer2 = nn.Sequential( 73 | ResNet50DownBlock(256, outs=[128, 128, 512], kernel_size=[1, 3, 1], stride=[1, 2, 1, 2], padding=[0, 1, 0]), 74 | ResNet50BasicBlock(512, outs=[128, 128, 512], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]), 75 | ResNet50BasicBlock(512, outs=[128, 128, 512], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]), 76 | ResNet50DownBlock(512, outs=[128, 128, 512], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]) 77 | ) 78 | 79 | self.layer3 = nn.Sequential( 80 | ResNet50DownBlock(512, outs=[256, 256, 1024], kernel_size=[1, 3, 1], stride=[1, 2, 1, 2], padding=[0, 1, 0]), 81 | ResNet50BasicBlock(1024, outs=[256, 256, 1024], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], 82 | padding=[0, 1, 0]), 83 | ResNet50BasicBlock(1024, outs=[256, 256, 1024], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], 84 | padding=[0, 1, 0]), 85 | ResNet50DownBlock(1024, outs=[256, 256, 1024], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1], 86 | padding=[0, 1, 0]), 87 | ResNet50DownBlock(1024, outs=[256, 256, 1024], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1], 88 | padding=[0, 1, 0]), 89 | ResNet50DownBlock(1024, outs=[256, 256, 1024], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1], 90 | padding=[0, 1, 0]) 91 | ) 92 | 93 | self.layer4 = nn.Sequential( 94 | ResNet50DownBlock(1024, outs=[512, 512, 2048], kernel_size=[1, 3, 1], stride=[1, 2, 1, 2], 95 | padding=[0, 1, 0]), 96 | ResNet50DownBlock(2048, outs=[512, 512, 2048], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1], 97 | padding=[0, 1, 0]), 98 | ResNet50DownBlock(2048, outs=[512, 512, 2048], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1], 99 | padding=[0, 1, 0]) 100 | ) 101 | 102 | self.avgpool = nn.AdaptiveAvgPool2d(output_size=(1, 1)) 103 | 104 | self.fc = nn.Linear(2048, 10) 105 | 106 | def forward(self, x): 107 | out = self.conv1(x) 108 | out = self.maxpool(out) 109 | out = self.layer1(out) 110 | out = self.layer2(out) 111 | out = self.layer3(out) 112 | out = self.layer4(out) 113 | out = self.avgpool(out) 114 | out = out.reshape(x.shape[0], -1) 115 | out = self.fc(out) 116 | return out 117 | 118 | if __name__ == '__main__': 119 | x = torch.randn(2, 3, 224, 224) 120 | net = ResNet50() 121 | out = net(x) 122 | print('out.shape: ', out.shape) 123 | print(out) -------------------------------------------------------------------------------- /CNN/trajectory_mapping.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | from math import sin,cos,tan,pi,radians,asin,sqrt,degrees,atan2 4 | import datetime 5 | import time 6 | import os 7 | import codecs 8 | from sklearn import preprocessing 9 | deltalon = 0.3 10 | deltalat = 0.3 #0.3 11 | #grid image consisted of h*l(w), grid cell consisted of a*a 12 | h = 50 13 | l = 50 14 | a = 1 15 | 16 | #Distance Computation 17 | def geodistance(lng1,lat1,lng2,lat2): 18 | lng1, lat1, lng2, lat2 = map(radians, [float(lng1), float(lat1), float(lng2), float(lat2)]) # 经纬度转换成弧度 19 | dlon=lng2-lng1 20 | dlat=lat2-lat1 21 | a=sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 22 | distance=2*asin(sqrt(a))*6371*1000 23 | distance=round(distance/1000,3) 24 | return distance 25 | 26 | #Azimuth Computation 27 | def getDegree(latA, lonA, latB, lonB): 28 | radLatA = radians(latA) 29 | radLonA = radians(lonA) 30 | radLatB = radians(latB) 31 | radLonB = radians(lonB) 32 | dLon = radLonB - radLonA 33 | y = sin(dLon) * cos(radLatB) 34 | x = cos(radLatA) * sin(radLatB) - sin(radLatA) * cos(radLatB) * cos(dLon) 35 | brng = degrees(atan2(y, x)) 36 | brng = (brng + 360) % 360 37 | return brng 38 | 39 | #Centroid Computation 40 | def Centroid_calculate(T): 41 | n = len(T) 42 | cenlat = 0 43 | cenlon = 0 44 | for i in range(n): 45 | cenlat = cenlat + T[i][0]/n 46 | cenlon = cenlon + T[i][1]/n 47 | return cenlat, cenlon 48 | 49 | #Trajectory Mapping 50 | def trajectory_mapping(T): 51 | cenlat, cenlon = Centroid_calculate(T) 52 | minlon = 200 53 | minlat = 200 54 | for i in range(len(T)): 55 | if T[i][0]=h or axisx<0 or axisy>=l or axisy<0: continue 75 | lastid = k 76 | if Im[axisx][axisy][0]==0: #start point 77 | Im[axisx][axisy][0] = Im[axisx][axisy][0] + 1 78 | Im[axisx][axisy][1] = k 79 | Im[axisx][axisy][2] = k 80 | Im[axisx][axisy][3] = 0 81 | else: 82 | Im[axisx][axisy][0] = Im[axisx][axisy][0] + 1 83 | Im[axisx][axisy][3] = Im[axisx][axisy][3] + geodistance(T[k][1], T[k][0], T[lastid][1], T[lastid][0]) 84 | Im[axisx][axisy][2] = k #end point 85 | 86 | #pixels 87 | total = [] 88 | for i in range(h): 89 | for j in range(l): 90 | dist = Im[i][j][3] 91 | t1 = 0 92 | t2 = 0 93 | t1 = datetime.datetime.strptime(T[Im[i][j][1]][2], '%Y-%m-%d %H:%M:%S') #起点 94 | t2 = datetime.datetime.strptime(T[Im[i][j][2]][2], '%Y-%m-%d %H:%M:%S') #终点 95 | staytime = (t2 - t1).seconds 96 | direction = getDegree(T[Im[i][j][1]][0], T[Im[i][j][1]][1], T[Im[i][j][2]][0], T[Im[i][j][2]][1]) 97 | 98 | if staytime == 0: 99 | total.append([0,0,0]) 100 | continue 101 | ttt = [] 102 | ttt.append(direction) 103 | ttt.append(dist/(staytime)) 104 | ttt.append(staytime) 105 | total.append(ttt) 106 | #normalization 107 | min_max_scaler = preprocessing.MinMaxScaler() 108 | X_minMax = min_max_scaler.fit_transform(total) 109 | 110 | k = 0 111 | Image = [] 112 | for i in range(h): 113 | test1 = [] 114 | for j in range(l): 115 | t = [] 116 | t.append(X_minMax[k][0]) 117 | t.append(X_minMax[k][1]) 118 | t.append(X_minMax[k][2]) 119 | test1.append(t) 120 | k = k + 1 121 | Image.append(test1) 122 | 123 | return Image 124 | 125 | #Remove the white boader of images 126 | def corp_margin(img): 127 | img2=img.sum(axis=2) 128 | (row,col)=img2.shape 129 | row_top=0 130 | raw_down=0 131 | col_top=0 132 | col_down=0 133 | for r in range(0,row): 134 | if img2.sum(axis=1)[r]<700*col: 135 | row_top=r 136 | break 137 | for r in range(row-1,0,-1): 138 | if img2.sum(axis=1)[r]<700*col: 139 | raw_down=r 140 | break 141 | for c in range(0,col): 142 | if img2.sum(axis=0)[c]<700*row: 143 | col_top=c 144 | break 145 | for c in range(col-1,0,-1): 146 | if img2.sum(axis=0)[c]<700*row: 147 | col_down=c 148 | break 149 | new_img=img[row_top:raw_down+1,col_top:col_down+1,0:3] 150 | return new_img 151 | 152 | #get mapped trajectory 153 | def Paint(Image, path): 154 | savepath = "/.../test.jpg" 155 | plt.axis('off') 156 | plt.imshow(Image, interpolation='nearest') 157 | plt.savefig(savepath) 158 | im = plt.imread(savepath) 159 | img_re = corp_margin(im) 160 | plt.imsave(path, img_re) 161 | 162 | # path1: direction of trajectories 163 | # path2: direction to save mapped trajectories 164 | def func(path1, path2): 165 | k = 0 166 | list1 = os.listdir(path1) 167 | for i in list1: 168 | p1 = os.path.join(path1,i) 169 | list2 = os.listdir(p1) 170 | for j in list2: 171 | print(os.path.join(p1, j)) 172 | f = open(os.path.join(p1, j), "r") 173 | line = f.readline() 174 | ls = [] 175 | while line: 176 | b = line.split(',') 177 | b[0] = float(b[0]) 178 | b[1] = float(b[1]) 179 | b[2] = b[2].strip('\n') 180 | ls.append(b) 181 | line = f.readline() 182 | f.close() 183 | Image = Image_calculate(ls) 184 | Paint(Image, path2+"\\"+str(i)+"\\IMAGE"+str(j)+".jpg") 185 | k = k + 1 186 | 187 | func("/.../Geolife/data1/train", "/.../CNN/Image/train") 188 | func("/.../Geolife/data1/test", "/.../CNN/Image/test") -------------------------------------------------------------------------------- /CNNTCN/Geolife/geolife: -------------------------------------------------------------------------------- 1 | https://www.microsoft.com/en-us/surface?icid=mscom_marcom_dlc 2 | -------------------------------------------------------------------------------- /CNNTCN/geolife_test.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.autograd import Variable 3 | import torch.nn.functional as F 4 | import sys, os 5 | sys.path.append("/.../") 6 | from CNNTCN.Geolife.utilsT import data_generatorDis 7 | from CNNTCN.Geolife.utilsC import data_generator 8 | from CNNTCN.Geolife.model import TCN 9 | from CNN.trajectory_mapping import geodistance, getDegree, Centroid_calculate, trajectory_mapping, Image_calculate, corp_margin 10 | import numpy as np 11 | import argparse 12 | from torch import nn, optim 13 | import torchvision.transforms as transforms 14 | import torchvision 15 | from torch.utils.data import DataLoader 16 | from torch.autograd import Variable 17 | from CNN.res50 import ResNet50 18 | import matplotlib.pyplot as plt 19 | from math import sin,cos,tan,pi,radians,asin,sqrt,degrees,atan2 20 | import datetime 21 | import time 22 | import os 23 | import codecs 24 | from sklearn import preprocessing 25 | from PIL import Image as Im 26 | import multiprocessing 27 | import socket 28 | import json 29 | 30 | start_time = time.time() 31 | 32 | classes = ('0','1', '2', '3', '4', '5', '6') 33 | deltalon = 0.3 34 | deltalat = 0.3 #0.3 35 | h = 50 36 | l = 50 37 | a = 1 38 | device = torch.device('cuda') 39 | import pandas as pd 40 | from statsmodels.tsa.seasonal import seasonal_decompose 41 | 42 | def loaddata(path,batchsz): 43 | trainset = torchvision.datasets.ImageFolder(path, 44 | transform=transforms.Compose([ 45 | transforms.Resize((32, 32)), 46 | 47 | transforms.CenterCrop(32), 48 | transforms.ToTensor()]) 49 | ) 50 | 51 | trainloader = torch.utils.data.DataLoader(trainset, batch_size=batchsz, 52 | shuffle=True, num_workers=2) 53 | return trainloader 54 | 55 | #predict the class of image 56 | def predict(img): 57 | net=torch.load('cnnmodel.pkl') 58 | net=net.to(device) 59 | torch.no_grad() 60 | 61 | transform = transforms.Compose([ 62 | transforms.Resize(256,interpolation=2), 63 | transforms.ToTensor() 64 | ]) 65 | img=transform(img).unsqueeze(0) 66 | img_ = img.to(device) 67 | outputs = net(img_) 68 | _, predicted = torch.max(outputs, 1) 69 | return outputs 70 | 71 | def cnnTest(list1): 72 | savepath = "/.../CNN/test.jpg" 73 | Image = Image_calculate(list1) 74 | plt.axis('off') #去掉坐标轴 75 | plt.imshow(Image, interpolation='nearest') 76 | plt.savefig(savepath) 77 | img = plt.imread(savepath) 78 | new_img = corp_margin(img) 79 | plt.imsave(savepath,new_img) 80 | plt.imshow(new_img) 81 | new_img = Im.open(savepath) 82 | return predict(new_img) 83 | 84 | parser = argparse.ArgumentParser(description='Sequence Modeling - (Permuted) Sequential TCN') 85 | parser.add_argument('--batch_size', type=int, default=64, metavar='N', 86 | help='batch size (default: 64)') 87 | parser.add_argument('--cuda', action='store_false', 88 | help='use CUDA (default: True)') 89 | parser.add_argument('--dropout', type=float, default=0.05, 90 | help='dropout applied to layers (default: 0.05)') 91 | parser.add_argument('--clip', type=float, default=-1, 92 | help='gradient clip, -1 means no clip (default: -1)') 93 | parser.add_argument('--epochs', type=int, default=20, 94 | help='upper epoch limit (default: 20)') 95 | parser.add_argument('--ksize', type=int, default=7, 96 | help='kernel size (default: 7)') 97 | parser.add_argument('--levels', type=int, default=8, 98 | help='# of levels (default: 8)') 99 | parser.add_argument('--log-interval', type=int, default=1, metavar='N', 100 | help='report interval (default: 100') 101 | parser.add_argument('--lr', type=float, default=2e-3, 102 | help='initial learning rate (default: 2e-3)') 103 | parser.add_argument('--optim', type=str, default='Adam', 104 | help='optimizer to use (default: Adam)') 105 | parser.add_argument('--nhid', type=int, default=25, 106 | help='number of hidden units per layer (default: 25)') 107 | parser.add_argument('--seed', type=int, default=1111, 108 | help='random seed (default: 1111)') 109 | parser.add_argument('--permute', action='store_true', 110 | help='use permuted TCN (default: false)') 111 | args = parser.parse_args() 112 | 113 | torch.manual_seed(args.seed) 114 | if torch.cuda.is_available(): 115 | print("WARNING: You have a CUDA device, so you should probably run with --cuda") 116 | 117 | batch_size = args.batch_size 118 | n_classes = 7 119 | input_channels = 3 120 | seq_length = int(300*3 / input_channels) 121 | epochs = args.epochs 122 | steps = 0 123 | 124 | print(args) 125 | train_loaderC, test_loader = data_generator(batch_size) #get test set of CNN 126 | train_loader, test_loader1, test_loader2, test_loader3 = data_generatorDis(batch_size) #get train set and test set of TCN 127 | 128 | permute = torch.Tensor(np.random.permutation(1024).astype(np.float64)).long() 129 | channel_sizes = [args.nhid] * args.levels 130 | kernel_size = args.ksize 131 | model = TCN(input_channels, n_classes, channel_sizes, kernel_size=kernel_size, dropout=args.dropout) 132 | 133 | if args.cuda: 134 | model.cuda() 135 | permute = permute.cuda() 136 | 137 | lr = args.lr #learning rate 138 | optimizer = getattr(optim, args.optim)(model.parameters(), lr=lr) #返回对象属性值 139 | 140 | #TCN training 141 | def train(ep): 142 | global steps 143 | train_loss = 0 144 | model.train() 145 | 146 | with torch.no_grad(): 147 | for batch_idx, (data, target) in enumerate(train_loader): 148 | 149 | if args.cuda: data, target = data.cuda(), target.cuda() 150 | data = data.view(-1, input_channels, seq_length) 151 | if args.permute: 152 | data = data[:, :, permute] 153 | data, target = Variable(data), Variable(target) 154 | print("data:",data.size()) 155 | print("target:",target.size()) 156 | optimizer.zero_grad() 157 | output = model(data) 158 | loss = F.nll_loss(output, target) 159 | loss = loss.requires_grad_() 160 | loss.backward() 161 | if args.clip > 0: 162 | torch.nn.utils.clip_grad_norm_(model.parameters(), args.clip) 163 | optimizer.step() 164 | train_loss += loss 165 | steps += seq_length 166 | 167 | print("output size:",output.shape) 168 | 169 | if batch_idx > 0 and batch_idx % args.log_interval == 0: 170 | print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}\tSteps: {}'.format( 171 | ep, batch_idx * batch_size, len(train_loader.dataset), 172 | 100. * batch_idx / len(train_loader), train_loss.item()/args.log_interval, steps)) 173 | train_loss = 0 174 | l = len(train_loader.dataset) 175 | print("l:",l) 176 | 177 | print("finish training") 178 | torch.save(model,'Urbanmodel.pkl') 179 | torch.save(model.state_dict(),'Urbanmodel_params.pkl') 180 | 181 | from sklearn.metrics import classification_report,f1_score 182 | from sklearn.feature_selection import VarianceThreshold 183 | import pandas as pd 184 | 185 | #TCN testing (serial) 186 | def test(): 187 | net1 = torch.load('Urbanmodel20.pkl') 188 | net1 = net1.to(device) 189 | net2 = torch.load('Suburbmodel20.pkl') 190 | net2 = net2.to(device) 191 | net3 = torch.load('Urban2model20.pkl') 192 | net3 = net3.to(device) 193 | 194 | test_loss = 0 195 | correct = 0 196 | TP = 0 197 | 198 | labe = [] 199 | da = [] 200 | 201 | with torch.no_grad(): 202 | for data, target in test_loader1: 203 | if args.cuda: 204 | data, target = data.cuda(), target.cuda() 205 | data = data.view(-1, input_channels, seq_length) 206 | if args.permute: 207 | data = data[:, :, permute] 208 | with torch.no_grad(): 209 | data, target = Variable(data), Variable(target) 210 | output = net1(data) 211 | test_loss += F.nll_loss(output, target, size_average=False).item() 212 | pred = output.data.max(1, keepdim=True)[1] 213 | correct += pred.eq(target.data.view_as(pred)).cpu().sum() 214 | p = pred.eq(target.data.view_as(pred)) 215 | TP += ((p==True)&(target.data==1)).cpu().sum() 216 | 217 | for data, target in test_loader2: 218 | if args.cuda: 219 | data, target = data.cuda(), target.cuda() 220 | data = data.view(-1, input_channels, seq_length) 221 | if args.permute: 222 | data = data[:, :, permute] 223 | with torch.no_grad(): 224 | data, target = Variable(data), Variable(target) 225 | output = net2(data) 226 | test_loss += F.nll_loss(output, target, size_average=False).item() 227 | pred = output.data.max(1, keepdim=True)[1] 228 | correct += pred.eq(target.data.view_as(pred)).cpu().sum() 229 | p = pred.eq(target.data.view_as(pred)) 230 | TP += ((p==True)&(target.data==1)).cpu().sum() 231 | 232 | for data, target in test_loader3: 233 | if args.cuda: 234 | data, target = data.cuda(), target.cuda() 235 | data = data.view(-1, input_channels, seq_length) 236 | if args.permute: 237 | data = data[:, :, permute] 238 | with torch.no_grad(): 239 | data, target = Variable(data), Variable(target) 240 | output = net2(data) 241 | test_loss += F.nll_loss(output, target, size_average=False).item() 242 | pred = output.data.max(1, keepdim=True)[1] 243 | correct += pred.eq(target.data.view_as(pred)).cpu().sum() 244 | p = pred.eq(target.data.view_as(pred)) 245 | TP += ((p==True)&(target.data==1)).cpu().sum() 246 | 247 | l = len(test_loader1.dataset)+len(test_loader2.dataset)+len(test_loader3.dataset) 248 | test_loss /= l 249 | print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%), F1:({:.2f})\n'.format(test_loss, correct, l, 100.* correct / l, 2/(2+(l-correct)/FP))) 250 | return test_loss 251 | 252 | # TCN testing (parallel) 253 | def test1(test_loader, net): 254 | test_loss = 0 255 | correct = 0 256 | with torch.no_grad(): 257 | for data,target in test_loader: 258 | if args.cuda: 259 | data, target = data.cuda(), target.cuda() 260 | data = data.view(-1,input_channels,seq_length) 261 | if args.permute: 262 | data = data[:,:,permute] 263 | data, target = Variable(data,volatile=True), Variable(target) 264 | output = net(data) 265 | test_loss += F.nll_loss(output,target,size_average=False).item() 266 | pred = output.data.max(1,keepdim=True)[1] 267 | correct += pred.eq(target.data.view_as(pred)).cpu().sum() 268 | p = pred.eq(target.data.view_as(pred)) 269 | TP += ((p==True)&(target.data==1)).cpu().sum() 270 | print('\nTest set: Average loss:{:.4f}, Accuracy:{}/{}({:.2f}%), F1:{:.2f}\n'.format(test_loss/len(test_loader.dataset),correct,len(test_loader.dataset),100.*correct/len(test_loader.dataset), 2/(2+(len(test_loader.dataset)-correct)/FP))) 271 | return test_loss, correct, TP 272 | 273 | #parallel 274 | def func(net,test_loader): 275 | ip_port = ("127.0.0.1", 9001) 276 | sk = socket.socket() 277 | sk.connect(ip_port) 278 | loss, correct, TP = test1(test_loader,net) 279 | t = [] 280 | t.append(loss) 281 | t.append(int(correct)) 282 | t.append(int(TP)) 283 | t = json.dumps(t) 284 | sk.send(bytes(t.encode('utf-8'))) 285 | sk.close() 286 | 287 | if __name__ == "__main__": 288 | start_time = time.time() 289 | ''' 290 | for epoch in range(1, epochs+1): 291 | train(epoch) 292 | ''' 293 | mid_time = time.time() 294 | #print("training time:{:.2f}".format(mid_time-start_time)) 295 | 296 | 297 | cnnTest(text_loader) 298 | ctx = multiprocessing.get_context("spawn") 299 | loss = 0 300 | correct = 0 301 | TP = 0 302 | ip_port = ("127.0.0.1", 9001) 303 | sk = socket.socket() 304 | sk.bind(ip_port) 305 | sk.listen(3) 306 | p1 = ctx.Process(target=func,args=(net1,test_loader1)) 307 | p1.start() 308 | p2 = ctx.Process(target=func,args=(net2,test_loader2)) 309 | p2.start() 310 | p3 = ctx.Process(target=func,args=(net3,test_loader3)) 311 | p3.start() 312 | for i in range(3): 313 | conn, addr = sk.accept() 314 | data = conn.recv(1024) 315 | data = json.loads(data) 316 | print(data) 317 | loss += data[0] 318 | correct += data[1] 319 | conn.close() 320 | p1.join() 321 | p2.join() 322 | p3.join() 323 | sk.close() 324 | print('\nTest set:Total Average loss:{:.4f},Total Accuracy:{}/{}({:0.2f}%)\n'.format(loss/lens,correct,lens,100*correct/lens)) 325 | end_time = time.time() 326 | print("testing time:%d" %(end_time-mid_time)) 327 | 328 | -------------------------------------------------------------------------------- /CNNTCN/model.py: -------------------------------------------------------------------------------- 1 | from torch import nn 2 | import sys, os 3 | sys.path.append(os.pardir) 4 | from TCN.tcn import TemporalConvNet 5 | 6 | 7 | class TCN(nn.Module): 8 | def __init__(self, input_size, output_size, num_channels, kernel_size, dropout): 9 | super(TCN, self).__init__() 10 | self.tcn = TemporalConvNet(input_size, num_channels, kernel_size=kernel_size, dropout=dropout) 11 | self.linear = nn.Linear(num_channels[-1], output_size) 12 | self.init_weights() 13 | 14 | def init_weights(self): 15 | self.linear.weight.data.normal_(0, 0.01) 16 | 17 | def forward(self, x): 18 | y1 = self.tcn(x) 19 | return self.linear(y1.transpose(1, 2)) 20 | -------------------------------------------------------------------------------- /CNNTCN/tcn.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.nn.utils import weight_norm 4 | 5 | 6 | class Chomp1d(nn.Module): 7 | def __init__(self, chomp_size): 8 | super(Chomp1d, self).__init__() 9 | self.chomp_size = chomp_size 10 | 11 | def forward(self, x): 12 | return x[:, :, :-self.chomp_size].contiguous() 13 | 14 | #Temporal Module 15 | class TemporalBlock(nn.Module): 16 | def __init__(self, n_inputs, n_outputs, kernel_size, stride, dilation, padding, dropout=0.2): 17 | super(TemporalBlock, self).__init__() 18 | self.conv1 = weight_norm(nn.Conv1d(n_inputs, n_outputs, kernel_size, 19 | stride=stride, padding=padding, dilation=dilation)) 20 | self.chomp1 = Chomp1d(padding) 21 | self.relu1 = nn.ReLU() 22 | self.dropout1 = nn.Dropout(dropout) 23 | 24 | self.conv2 = weight_norm(nn.Conv1d(n_outputs, n_outputs, kernel_size, 25 | stride=stride, padding=padding, dilation=dilation)) 26 | self.chomp2 = Chomp1d(padding) 27 | self.relu2 = nn.ReLU() 28 | self.dropout2 = nn.Dropout(dropout) 29 | 30 | self.net = nn.Sequential(self.conv1, self.chomp1, self.relu1, self.dropout1, 31 | self.conv2, self.chomp2, self.relu2, self.dropout2) 32 | self.downsample = nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else None 33 | self.relu = nn.ReLU() 34 | self.init_weights() 35 | 36 | def init_weights(self): 37 | self.conv1.weight.data.normal_(0, 0.01) 38 | self.conv2.weight.data.normal_(0, 0.01) 39 | if self.downsample is not None: 40 | self.downsample.weight.data.normal_(0, 0.01) 41 | 42 | def forward(self, x): 43 | out = self.net(x) 44 | res = x if self.downsample is None else self.downsample(x) 45 | 46 | return self.relu(out + res) 47 | 48 | #Temporal Convolution 49 | # # hidden layers: 8 #hidden units of each layer: 25 50 | class TemporalConvNet(nn.Module): 51 | ''' 52 | :param num_inputs: int 53 | :param num_channels: list 54 | :param kernel_size: int 55 | :param dropout: float, drop_out 56 | ''' 57 | def __init__(self, num_inputs, num_channels, kernel_size=2, dropout=0.2): 58 | super(TemporalConvNet, self).__init__() 59 | layers = [] 60 | num_levels = len(num_channels) 61 | for i in range(num_levels): 62 | dilation_size = 2 ** i #dilation coefficient 63 | in_channels = num_inputs if i == 0 else num_channels[i-1] 64 | out_channels = num_channels[i] 65 | layers += [TemporalBlock(in_channels, out_channels, kernel_size, stride=1, dilation=dilation_size, 66 | padding=(kernel_size-1) * dilation_size, dropout=dropout)] 67 | self.network = nn.Sequential(*layers) 68 | 69 | def forward(self, x): 70 | return self.network(x) 71 | -------------------------------------------------------------------------------- /CNNTCN/utilsC.py: -------------------------------------------------------------------------------- 1 | import os 2 | import codecs 3 | import numpy as np 4 | import torch 5 | import datetime 6 | import time 7 | 8 | #get train set and test set 9 | def data_generator(batch_size): 10 | path_train = "/.../CNNTCN/Geolife/data2/train" 11 | path_test = "/.../CNNTCN/Geolife/data2/test" 12 | 13 | list1 = os.listdir(path_train) 14 | list2 = os.listdir(path_test) 15 | X_train = [] 16 | Y_train = [] #labels 17 | X_test = [] 18 | Y_test = [] #labels 19 | timefirst = datetime.datetime.strptime('2000-01-01 00:00:00', '%Y-%m-%d %H:%M:%S') 20 | #train set 21 | for i in list1: 22 | if int(i)<7: 23 | path1 = os.path.join(path_train,i) 24 | list11 = os.listdir(path1) 25 | for j in list11: 26 | path11 = os.path.join(path1,j) 27 | f = open(path11, "r") 28 | line = f.readline() 29 | t = [] 30 | while line: 31 | a = line.strip('\n').split(',') 32 | a[0] = float(a[0]) 33 | a[1] = float(a[1]) 34 | a[2] = (datetime.datetime.strptime(a[2], '%Y-%m-%d %H:%M:%S') - timefirst).seconds 35 | t.append(a) 36 | line = f.readline() 37 | f.close() 38 | 39 | if len(t) <= 300:continue 40 | else: 41 | test = [] 42 | for k in range(0,300): 43 | test.append(t[k]) 44 | X_train.append(test) 45 | 46 | y = [0,0,0,0,0,0,0] 47 | y[int(i)] = 1 48 | Y_train.append(y) 49 | else:continue 50 | X_train = torch.tensor(X_train, dtype=torch.float32) 51 | Y_train = torch.tensor(Y_train, dtype=torch.long) 52 | 53 | datasets = torch.utils.data.TensorDataset(X_train,Y_train) 54 | train_loader = torch.utils.data.DataLoader(datasets, batch_size=batch_size) 55 | 56 | #test set 57 | for i in list1: 58 | path1 = os.path.join(path_test,i) 59 | list11 = os.listdir(path1) 60 | for j in list11: 61 | path11 = os.path.join(path1,j) 62 | f = open(path11, "r") 63 | line = f.readline() 64 | t = [] 65 | while line: 66 | a = line.strip('\n').split(',') 67 | a[0] = float(a[0]) 68 | a[1] = float(a[1]) 69 | a[2] = (datetime.datetime.strptime(a[2], '%Y-%m-%d %H:%M:%S') - timefirst).seconds 70 | t.append(a) 71 | line = f.readline() 72 | f.close() 73 | 74 | if len(t) <= 300: 75 | continue 76 | else: 77 | test = [] 78 | for k in range(0,300): 79 | test.append(t[k]) 80 | X_test.append(test) 81 | 82 | y = [0,0,0,0,0,0,0] 83 | y[int(i)] = 1 84 | Y_test.append(y) 85 | else:continue 86 | 87 | X_test = torch.tensor(X_test, dtype=torch.float32) 88 | Y_test = torch.tensor(Y_test, dtype=torch.long) 89 | 90 | datasets = torch.utils.data.TensorDataset(X_test,Y_test) 91 | test_loader = torch.utils.data.DataLoader(datasets, batch_size=batch_size) 92 | 93 | return train_loader, test_loader 94 | -------------------------------------------------------------------------------- /CNNTCN/utilsT.py: -------------------------------------------------------------------------------- 1 | import os 2 | import codecs 3 | import numpy as np 4 | import torch 5 | import datetime 6 | import time 7 | 8 | import csv 9 | from shapely.geometry import Point 10 | from shapely.geometry.polygon import Polygon 11 | import shutil 12 | import os 13 | 14 | #boader information of partitions 15 | def load_fence(filepath): 16 | buffer = [] 17 | with open(filepath, 'rt', encoding='utf-8-sig') as vsvfile: 18 | reader = csv.reader(vsvfile) 19 | for row in reader: 20 | buffer = buffer + (list(map(float,row))) 21 | buffer = np.array(buffer).reshape(len(buffer) // 2 , 2) 22 | return buffer 23 | 24 | fencedc = load_fence("/.../CNNTCN/Geolife/bjDistrict/dongcheng.txt") 25 | fencexc = load_fence("/.../CNNTCN/Geolife/bjDistrict/xicheng.txt") 26 | fencecy = load_fence("/.../CNNTCN/Geolife/bjDistrict/chaoyang.txt") 27 | fenceft = load_fence("/.../CNNTCN/Geolife/bjDistrict/fengtai.txt") 28 | fencesjs = load_fence("/.../CNNTCN/Geolife/bjDistrict/shijingshan.txt") 29 | fencehd = load_fence("/.../CNNTCN/Geolife/bjDistrict/haidian.txt") 30 | fencemtg = load_fence("/.../CNNTCN/Geolife/bjDistrict/mentougou.txt") 31 | fencefs = load_fence("/.../CNNTCN/Geolife/bjDistrict/fangshan.txt") 32 | fencetz = load_fence("/.../CNNTCN/Geolife/bjDistrict/tongzhou.txt") 33 | fencesy = load_fence("/.../CNNTCN/Geolife/bjDistrict/shunyi.txt") 34 | fencecp = load_fence("/.../CNNTCN/Geolife/bjDistrict/changping.txt") 35 | fencedx = load_fence("/.../CNNTCN/Geolife/bjDistrict/daxing.txt") 36 | fencehr = load_fence("/.../CNNTCN/Geolife/bjDistrict/huairou.txt") 37 | fencepg = load_fence("/.../CNNTCN/Geolife/bjDistrict/pinggu.txt") 38 | fencemy = load_fence("/.../CNNTCN/Geolife/bjDistrict/miyun.txt") 39 | fenceyq = load_fence("/.../CNNTCN/Geolife/bjDistrict/yanqing.txt") 40 | 41 | def IsIn(point, fence): 42 | if Polygon(fence).contains(point) == True: 43 | return 1 44 | else: 45 | return 0 46 | 47 | #Partition 48 | def func(T): 49 | num = {'dc':0, 'xc':0,'cy':0,'ft':0, 50 | 'sjs':0,'hd':0,'mtg':0,'fs':0, 51 | 'tz':0,'sy':0,'cp':0,'dx':0, 52 | 'hr':0,'pg':0,'my':0,'yq':0,} 53 | for i in T: 54 | point = Point(float(i[1]),float(i[0])) 55 | num['dc'] += IsIn(point, fencedc) 56 | num['xc'] += IsIn(point, fencexc) 57 | num['cy'] += IsIn(point, fencecy) 58 | num['ft'] += IsIn(point, fenceft) 59 | num['sjs'] += IsIn(point, fencesjs) 60 | num['hd'] += IsIn(point, fencehd) 61 | num['mtg'] += IsIn(point, fencemtg) 62 | num['fs'] += IsIn(point, fencefs) 63 | num['tz'] += IsIn(point, fencetz) 64 | num['sy'] += IsIn(point, fencesy) 65 | num['cp'] += IsIn(point, fencecp) 66 | num['dx'] += IsIn(point, fencedx) 67 | num['hr'] += IsIn(point, fencehr) 68 | num['pg'] += IsIn(point, fencepg) 69 | num['my'] += IsIn(point, fencemy) 70 | num['yq'] += IsIn(point, fenceyq) 71 | 72 | maxv = max(num.values()) 73 | if maxv == 0: 74 | return 0 75 | for key,value in num.items(): 76 | if(value == maxv): 77 | if key=='dc' or key=='xc': 78 | return 3 79 | else: 80 | if key=='hd' or key=='cy' or key=='sjs' or key=='ft': 81 | return 1 82 | else: 83 | return 2 84 | 85 | #get train set and test set 86 | def data_generatorDis(batch_size): 87 | path_train = "/.../TCN/Geolife/data3/11/train" #11: City Center, 22: Suburb, 33: Urban area 88 | path_test = "/.../TCN/Geolife/data2/test" 89 | list1 = os.listdir(path_train) 90 | list2 = os.listdir(path_test) 91 | X_train = [] 92 | Y_train = [] #labels 93 | X_test1 = [] 94 | Y_test1 = [] #labels 95 | X_test2 = [] 96 | Y_test2 = [] #labels 97 | X_test3 = [] 98 | Y_test3 = [] #labels 99 | timefirst = datetime.datetime.strptime('2000-01-01 00:00:00', '%Y-%m-%d %H:%M:%S') 100 | #train set 101 | for i in list1: 102 | if int(i)<7: 103 | path1 = os.path.join(path_train,i) 104 | list11 = os.listdir(path1) 105 | for j in list11: 106 | path11 = os.path.join(path1,j) 107 | f = open(path11, "r") 108 | line = f.readline() 109 | t = [] 110 | while line: 111 | a = line.strip('\n').split(',') 112 | a[0] = float(a[0]) 113 | a[1] = float(a[1]) 114 | a[2] = (datetime.datetime.strptime(a[2], '%Y-%m-%d %H:%M:%S') - timefirst).seconds 115 | t.append(a) 116 | line = f.readline() 117 | f.close() 118 | if len(t) < 300: #trajectory length 119 | continue 120 | else: 121 | test = [] 122 | for k in range(0,300): 123 | test.append(t[k]) 124 | X_train.append(test) 125 | 126 | y=[0,0,0,0,0,0,0] 127 | y[int(i)]=1 128 | Y_train.append(y) 129 | else:continue 130 | 131 | X_train = torch.tensor(X_train, dtype=torch.float32) 132 | Y_train = torch.tensor(Y_train, dtype=torch.long) 133 | 134 | datasets = torch.utils.data.TensorDataset(X_train,Y_train) 135 | train_loader = torch.utils.data.DataLoader(datasets, batch_size=batch_size) 136 | 137 | #test set 138 | for i in list2: 139 | path1 = os.path.join(path_test,i) 140 | list11 = os.listdir(path1) 141 | for j in list11: 142 | path11 = os.path.join(path1,j) 143 | f = open(path11, "r") 144 | line = f.readline() 145 | t = [] 146 | while line: 147 | a = line.strip('\n').split(',') 148 | a[0] = float(a[0]) 149 | a[1] = float(a[1]) 150 | a[2] = (datetime.datetime.strptime(a[2], '%Y-%m-%d %H:%M:%S') - timefirst).seconds 151 | t.append(a) 152 | line = f.readline() 153 | f.close() 154 | if len(t) <= 300: 155 | continue 156 | else: 157 | test = [] 158 | for k in range(0,300): 159 | test.append(t[k]) 160 | m = func(test) 161 | if m==0: continue 162 | else: 163 | y=[0,0,0,0,0,0,0] 164 | y[int(i)]=1 165 | if m==1: 166 | X_test1.append(test) 167 | Y_test1.append(y) 168 | if m==2: 169 | X_test2.append(test) 170 | Y_test2.append(y) 171 | if m==3: 172 | X_test3.append(test) 173 | Y_test3.append(y) 174 | else:continue 175 | 176 | X_test1 = torch.tensor(X_test1, dtype=torch.float32) 177 | Y_test1 = torch.tensor(Y_test1, dtype=torch.long) 178 | datasets1 = torch.utils.data.TensorDataset(X_test1,Y_test1) 179 | test_loader1 = torch.utils.data.DataLoader(datasets1, batch_size=batch_size) 180 | 181 | X_test2 = torch.tensor(X_test2, dtype=torch.float32) 182 | Y_test2 = torch.tensor(Y_test2, dtype=torch.long) 183 | datasets2 = torch.utils.data.TensorDataset(X_test2,Y_test2) 184 | test_loader2 = torch.utils.data.DataLoader(datasets2, batch_size=batch_size) 185 | 186 | X_test3 = torch.tensor(X_test3, dtype=torch.float32) 187 | Y_test3 = torch.tensor(Y_test3, dtype=torch.long) 188 | datasets3 = torch.utils.data.TensorDataset(X_test3,Y_test3) 189 | test_loader3 = torch.utils.data.DataLoader(datasets3, batch_size=batch_size) 190 | 191 | return train_loader, test_loader1, test_loader2, test_loader3 192 | 193 | #train set and test sets of 3 partitions 194 | t1,t2,t3,t4 = data_generatorDis(64) 195 | -------------------------------------------------------------------------------- /Geolife/1.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | This folder (i.e., ./CNN, /CNNTCN) holds the source code of our methods. 3 | 4 | ## Environment Preparation 5 | - Pytorch 1.9.0 6 | - Python version: 3.9 7 | - GPU Server: GeForce RTX 3090, 2.40GHz GPU, and 24-GB RAM 8 | - Please refer to the source code to install all required packages of libs. 9 | 10 | ## Dataset Description 11 | - "./Geolife, ./CNN/Image, ./CNNTCN/Geolife" contains original trajectory data (data1), mapped trajectory data, trajectory data with seasonal data (data2) or partitioning(data1), and boundary information of 3 partitions (bjDistrict). 12 | - Note, Geolife dataset is consisted of seven kinds of mode datasets. 13 | - The format of the datasets are respectively: 14 | Trajectory data: moving object's sampling points consisted of lattitude, longitude, timestamp. 15 | Mapped trajectory data: grid images (50*50) of trajectory data. 16 | Boundary information: points on the boundaries consisted of lattitude and longetude. 17 | 18 | ## Running 19 | - Remove redundant information (e.g. altitude) of sampling points in GeolifeDataset 1.3; 20 | - Generate seven mode datasets and compose them as a new Geolife './Geolife'; 21 | - Get mapped trajectory by './CNN/trajectory_mapping.py'; 22 | - Train the CNN model by './CNN/main.py' and save the parameters ('./CNN/res50.py' explains how Resnet50 works) 23 | - Load the train set and test set from seven mode datasets and Geolife; 24 | - Run './CNNTCN/geolife_test.py' without cnnTest(), test(), test1() to train TCN model ('./CNNTCN/tcn.py' and './CNNTCN/model.py' explain how TCN works); 25 | - Run './CNNTCN/geolife_test.py' without train(epoch) to test CNN-TCN model and evaluate our methods; 26 | --------------------------------------------------------------------------------