Browse Source

update basic_model.py and related part in other files

pull/3/head
Gao Enhao 3 years ago
parent
commit
c681e3cb0a
5 changed files with 84 additions and 104 deletions
  1. +1
    -2
      abducer/abducer_base.py
  2. +2
    -2
      example.py
  3. +4
    -6
      framework.py
  4. +60
    -75
      models/basic_model.py
  5. +17
    -19
      utils/plog.py

+ 1
- 2
abducer/abducer_base.py View File

@@ -11,8 +11,7 @@
#================================================================#

import abc
from kb import add_KB, hwf_KB
# from abducer.kb import add_KB, hwf_KB
from abducer.kb import add_KB, hwf_KB
import numpy as np

from itertools import product, combinations


+ 2
- 2
example.py View File

@@ -43,11 +43,11 @@ def run_test():
optimizer = torch.optim.Adam(cls.parameters(), lr=0.001, betas=(0.9, 0.99))
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
base_model = BasicModel(cls, criterion, optimizer, device, recorder=recorder)
base_model = BasicModel(cls, criterion, optimizer, device, save_interval=1, save_dir=recorder.save_dir, num_epochs=1, recorder=recorder)
model = WABLBasicModel(base_model, kb.pseudo_label_list)

res = framework.train(model, abducer, train_X, train_Z, train_Y, sample_num = 10000, verbose = 1)
print(res)
recorder.print("abl_acc is ", res)
recorder.dump()
return True


+ 4
- 6
framework.py View File

@@ -123,7 +123,7 @@ def is_all_sublabel_exist(labels, std_label_list):
def pretrain(model, X, Z):
pass

def train(model, abducer, X, Z, Y, epochs = 10, sample_num = -1, verbose = -1):
def train(model, abducer, X, Z, Y, epochs = 5, sample_num = -1, verbose = -1):
# Set default parameters
if sample_num == -1:
sample_num = len(X)
@@ -138,10 +138,7 @@ def train(model, abducer, X, Z, Y, epochs = 10, sample_num = -1, verbose = -1):

predict_func = clocker(model.predict)
train_func = clocker(model.train)

abduce_func = clocker(abducer.batch_abduce)

epochs = 50
# Abductive learning train process
for epoch_idx in range(epochs):
@@ -153,12 +150,13 @@ def train(model, abducer, X, Z, Y, epochs = 10, sample_num = -1, verbose = -1):
if(char_acc_flag):
ori_char_acc = get_char_acc(Z, preds_res['cls'])
abd_char_acc = get_char_acc(abduced_Z, preds_res['cls'])
print('epoch_idx:', epoch_idx, ' abl_acc:', abl_acc, ' ori_char_acc:', ori_char_acc, ' abd_char_acc:', abd_char_acc)
INFO('epoch_idx:', epoch_idx, ' abl_acc:', abl_acc, ' ori_char_acc:', ori_char_acc, ' abd_char_acc:', abd_char_acc)
else:
print('epoch_idx:', epoch_idx, ' abl_acc:', abl_acc)
INFO('epoch_idx:', epoch_idx, ' abl_acc:', abl_acc)
finetune_X, finetune_Z = filter_data(X, abduced_Z)
if len(finetune_X) > 0:
# model.valid(finetune_X, finetune_Z)
train_func(finetune_X, finetune_Z)
else:
INFO("lack of data, all abduced failed", len(finetune_X))


+ 60
- 75
models/basic_model.py View File

@@ -55,7 +55,7 @@ class BasicModel():
optimizer,
device,
batch_size = 1,
num_epochs = 10,
num_epochs = 1,
stop_loss = 0.01,
num_workers = 0,
save_interval = None,
@@ -89,15 +89,15 @@ class BasicModel():
recorder = self.recorder
recorder.print("model fitting")

min_loss = 999999999
min_loss = 1e10
for epoch in range(n_epoch):
loss_value = self.train_epoch(data_loader)
recorder.print(f"{epoch}/{n_epoch} model training loss is {loss_value}")
if loss_value < min_loss:
if min_loss < 0 or loss_value < min_loss:
min_loss = loss_value
if epoch > 0 and self.save_interval is not None and epoch % self.save_interval == 0:
if self.save_interval is not None and (epoch + 1) % self.save_interval == 0:
assert self.save_dir is not None
self.save(self.save_dir)
self.save(epoch + 1, self.save_dir)
if stop_loss is not None and loss_value < stop_loss:
break
recorder.print("Model fitted, minimal loss is ", min_loss)
@@ -107,14 +107,7 @@ class BasicModel():
X = None,
y = None):
if data_loader is None:
collate_fn = self.collate_fn
transform = self.transform

train_dataset = XYDataset(X, y, transform=transform)
sampler = None
data_loader = torch.utils.data.DataLoader(train_dataset, batch_size=self.batch_size, \
shuffle=True, sampler=sampler, num_workers=int(self.num_workers), \
collate_fn=collate_fn)
data_loader = self._data_loader(X, y)
return self._fit(data_loader, self.num_epochs, self.stop_loss)

def train_epoch(self, data_loader):
@@ -136,6 +129,7 @@ class BasicModel():
optimizer.step()

total_loss += loss.item() * data.size(0)
total_num += data.size(0)

return total_loss / total_num

@@ -149,107 +143,98 @@ class BasicModel():
results = []
for data, _ in data_loader:
data = data.to(device)
pred_Y = model(data)
results.append(pred_Y)
out = model(data)
results.append(out)
return torch.cat(results, axis=0)

def predict(self, data_loader = None, X = None, print_prefix = ""):
if data_loader is None:
collate_fn = self.collate_fn
transform = self.transform

Y = [0] * len(X)
val_dataset = XYDataset(X, Y, transform=transform)
sampler = None
data_loader = torch.utils.data.DataLoader(val_dataset, batch_size=self.batch_size, \
shuffle=False, sampler=sampler, num_workers=int(self.num_workers), \
collate_fn=collate_fn)

recorder = self.recorder
recorder.print('Start Predict ', print_prefix)
Y = self._predict(data_loader).argmax(axis=1)
return [int(y) for y in Y]
recorder.print('Start Predict Class ', print_prefix)

def predict_proba(self, data_loader = None, X = None, print_prefix = ""):
if data_loader is None:
collate_fn = self.collate_fn
transform = self.transform

Y = [0] * len(X)
val_dataset = XYDataset(X, Y, transform=transform)
sampler = None
data_loader = torch.utils.data.DataLoader(val_dataset, batch_size=self.batch_size, \
shuffle=False, sampler=sampler, num_workers=int(self.num_workers), \
collate_fn=collate_fn)
data_loader = self._data_loader(X)
return self._predict(data_loader).argmax(axis=1).cpu().numpy()

def predict_proba(self, data_loader = None, X = None, print_prefix = ""):
recorder = self.recorder
recorder.print('Start Predict ', print_prefix)
return torch.softmax(self._predict(data_loader), axis=1).cpu().numpy()
recorder.print('Start Predict Probability ', print_prefix)

def _val(self, data_loader, print_prefix):
if data_loader is None:
data_loader = self._data_loader(X)
return self._predict(data_loader).softmax(axis=1).cpu().numpy()

def _val(self, data_loader):
model = self.model
criterion = self.criterion
recorder = self.recorder
device = self.device
recorder.print('Start val ', print_prefix)
model.eval()
n_correct = 0
pred_num = 0
loss_value = 0

total_correct_num, total_num, total_loss = 0, 0, 0.0

with torch.no_grad():
for _, data in enumerate(data_loader):
X = data[0].to(device)
Y = data[1].to(device)
for data, target in data_loader:
data, target = data.to(device), target.to(device)

pred_Y = model(X)
out = model(data)

correct_num = sum(Y == pred_Y.argmax(axis=1))
loss = criterion(pred_Y, Y)
loss_value += loss.item()
correct_num = sum(target == out.argmax(axis=1)).item()
loss = criterion(out, target)
total_loss += loss.item() * data.size(0)

n_correct += correct_num
pred_num += len(X)
total_correct_num += correct_num
total_num += data.size(0)
mean_loss = total_loss / total_num
accuracy = total_correct_num / total_num

accuracy = float(n_correct) / float(pred_num)
recorder.print('[%s] Val loss: %f, accuray: %f' % (print_prefix, loss_value, accuracy))
return accuracy
return mean_loss, accuracy

def val(self, data_loader = None, X = None, y = None, print_prefix = ""):
if data_loader is None:
collate_fn = self.collate_fn
transform = self.transform
recorder = self.recorder
recorder.print('Start val ', print_prefix)

val_dataset = XYDataset(X, y, transform=transform)
sampler = None
data_loader = torch.utils.data.DataLoader(val_dataset, batch_size=self.batch_size, \
shuffle=True, sampler=sampler, num_workers=int(self.num_workers), \
collate_fn=collate_fn)
return self._val(data_loader, print_prefix)
if data_loader is None:
data_loader = self._data_loader(X, y)
mean_loss, accuracy = self._val(data_loader)
recorder.print('[%s] Val loss: %f, accuray: %f' % (print_prefix, mean_loss, accuracy))
return accuracy

def score(self, data_loader = None, X = None, y = None, print_prefix = ""):
return self.val(data_loader, X, y, print_prefix)

def save(self, save_dir):
def _data_loader(self, X, y = None):
collate_fn = self.collate_fn
transform = self.transform

if y is None:
y = [0] * len(X)
dataset = XYDataset(X, y, transform=transform)
sampler = None
data_loader = torch.utils.data.DataLoader(dataset, batch_size=self.batch_size, \
shuffle=False, sampler=sampler, num_workers=int(self.num_workers), \
collate_fn=collate_fn)
return data_loader

def save(self, epoch_id, save_dir):
recorder = self.recorder
if not os.path.exists(save_dir):
os.mkdir(save_dir)
recorder.print("Saving model and opter")
save_path = os.path.join(save_dir, "net.pth")
save_path = os.path.join(save_dir, str(epoch_id) + "_net.pth")
torch.save(self.model.state_dict(), save_path)

save_path = os.path.join(save_dir, "opt.pth")
save_path = os.path.join(save_dir, str(epoch_id) + "_opt.pth")
torch.save(self.optimizer.state_dict(), save_path)

def load(self, load_dir):
def load(self, epoch_id, load_dir):
recorder = self.recorder
recorder.print("Loading model and opter")
load_path = os.path.join(load_dir, "net.pth")
load_path = os.path.join(load_dir, str(epoch_id) + "_net.pth")
self.model.load_state_dict(torch.load(load_path))

load_path = os.path.join(load_dir, "opt.pth")
load_path = os.path.join(load_dir, str(epoch_id) + "_opt.pth")
self.optimizer.load_state_dict(torch.load(load_path))

if __name__ == "__main__":


+ 17
- 19
utils/plog.py View File

@@ -20,12 +20,11 @@ global recorder
recorder = None

class ResultRecorder:
def __init__(self, pk_dir = 'results', pk_filepath = None):
self.result = {}

def __init__(self):
logging.basicConfig(level=logging.DEBUG, filemode='a')

self.set_savefile(pk_dir, pk_filepath)
self.result = {}
self.set_savefile()
logging.info("===========================================================")
logging.info("============= Result Recorder Version: 0.03 ===============")
@@ -33,20 +32,19 @@ class ResultRecorder:

pass

def set_savefile(self, pk_dir = None, pk_filepath = None):
if pk_dir is None:
pk_dir = "results"
if not os.path.exists(pk_dir):
os.makedirs(pk_dir)
def set_savefile(self):
local_time = time.strftime("%Y%m%d_%H_%M_%S", time.localtime())

if pk_filepath is None:
local_time = time.strftime("%Y%m%d_%H_%M_%S", time.localtime())
pk_filepath = os.path.join(pk_dir, local_time + ".pk")
save_dir = os.path.join("results", local_time)
save_file_path = os.path.join(save_dir, "result.pk")
self.save_file = pk_filepath
self.save_dir = save_dir
self.save_file_path = save_file_path

if not os.path.exists(save_dir):
os.makedirs(save_dir)

filename = os.path.join(pk_dir, local_time + ".txt")
filename = os.path.join(save_dir, "log.txt")
file_handler = logging.FileHandler(filename)
file_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
@@ -87,10 +85,10 @@ class ResultRecorder:
#self.print_result(label + ":" + str(data))
self.store_kv(label, data)

def dump(self, save_file = None):
if save_file is None:
save_file = self.save_file
with open(save_file, 'wb') as f:
def dump(self, save_file_path = None):
if save_file_path is None:
save_file_path = self.save_file_path
with open(save_file_path, 'wb') as f:
pk.dump(self.result, f)

def clock(self, func):


Loading…
Cancel
Save