diff --git a/README.md b/README.md index 614ca01..873dd76 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ -# ml-diplom \ No newline at end of file +AustinDoolittle implementation + +wia anaconda pip +opencv-python +imgaug + + +--------- +fastai \ No newline at end of file diff --git a/__pycache__/cbam_model.cpython-36.pyc b/__pycache__/cbam_model.cpython-36.pyc new file mode 100644 index 0000000..972513b Binary files /dev/null and b/__pycache__/cbam_model.cpython-36.pyc differ diff --git a/__pycache__/classifier.cpython-36.pyc b/__pycache__/classifier.cpython-36.pyc new file mode 100644 index 0000000..9519c98 Binary files /dev/null and b/__pycache__/classifier.cpython-36.pyc differ diff --git a/__pycache__/gain.cpython-36.pyc b/__pycache__/gain.cpython-36.pyc new file mode 100644 index 0000000..cb0485e Binary files /dev/null and b/__pycache__/gain.cpython-36.pyc differ diff --git a/__pycache__/image_loader.cpython-36.pyc b/__pycache__/image_loader.cpython-36.pyc new file mode 100644 index 0000000..9257a56 Binary files /dev/null and b/__pycache__/image_loader.cpython-36.pyc differ diff --git a/__pycache__/main_cbam.cpython-36.pyc b/__pycache__/main_cbam.cpython-36.pyc new file mode 100644 index 0000000..20ba512 Binary files /dev/null and b/__pycache__/main_cbam.cpython-36.pyc differ diff --git a/__pycache__/property.cpython-36.pyc b/__pycache__/property.cpython-36.pyc new file mode 100644 index 0000000..a134852 Binary files /dev/null and b/__pycache__/property.cpython-36.pyc differ diff --git a/__pycache__/sam_model.cpython-36.pyc b/__pycache__/sam_model.cpython-36.pyc new file mode 100644 index 0000000..10e1d1d Binary files /dev/null and b/__pycache__/sam_model.cpython-36.pyc differ diff --git a/__pycache__/sam_train.cpython-36.pyc b/__pycache__/sam_train.cpython-36.pyc new file mode 100644 index 0000000..57b90d3 Binary files /dev/null and b/__pycache__/sam_train.cpython-36.pyc differ diff --git a/__pycache__/utils.cpython-36.pyc b/__pycache__/utils.cpython-36.pyc new file mode 100644 index 0000000..64e9c5b Binary files /dev/null and b/__pycache__/utils.cpython-36.pyc differ diff --git a/classifier.py b/classifier.py new file mode 100644 index 0000000..53b8da8 --- /dev/null +++ b/classifier.py @@ -0,0 +1,232 @@ +""" +classify dataset +""" + +import torch +import torchvision.models as m +import property as P +import torch.nn as nn +import copy +from datetime import datetime +import os +import utils + +probability_threshold = 0.5 + + +def scalar(tensor): + return tensor.data.cpu().item() + + +def send_to_gpu(*args) -> tuple: + result = [] + for i in args: + result.append(i.cuda()) + return (*result,) + + +def send_to_cpu(*args) -> tuple: + result = [] + for i in args: + result.append(i.cpu()) + return (*result,) + + +class Classifier: + + def __init__(self, description: str, classes: int, gpu=False, loss_classifier=None): + self.gpu = gpu + self.description = description + # здесь * 2 так как каждой метке соответсвует бинарное значение -- да, нет в самом деле я сделал так для + # классификации так как сделать по другому не знаю + self.classes = classes + self.model = m.vgg16(pretrained=True) + num_features = self.model.classifier[6].in_features + self.model.classifier[6] = nn.Linear(num_features, self.classes) + + self.best_weights = copy.deepcopy(self.model.state_dict()) + self.best_test_weights = copy.deepcopy(self.model.state_dict()) + + if loss_classifier is None: + self.loss_classifier = torch.nn.BCELoss() + + if self.gpu: + self.model = self.model.cuda() + self.tensor_source = torch.cuda + else: + self.tensor_source = torch + + self.train_model_answers = [[] for _ in range(self.classes)] + self.train_trust_answers = [[] for _ in range(self.classes)] + self.train_probabilities = [[] for _ in range(self.classes)] + + self.test_model_answers = [[] for _ in range(self.classes)] + self.test_trust_answers = [[] for _ in range(self.classes)] + self.test_probabilities = [[] for _ in range(self.classes)] + + def train(self, epochs: int, test_each_epochs: int, save_test_roc_each_epochs: int, save_train_roc_each_epochs: int, + train_data_set, test_data_set, + learning_rate=1e-6): + + optimizer = torch.optim.Adam(self.model.parameters(), lr=learning_rate) + self.model.train() + best_loss = None + best_test_loss = None + + for epoch in range(1, epochs + 1): + total_loss_cl = 0 + total_cl_acc = 0 + set_size = 0 + for images, _, labels in train_data_set: + set_size += 1 # images.size(0) + if self.gpu: + images, labels = send_to_gpu(images, labels) + # images, labels = wrap_to_variable(images, labels) + class_label = labels + train_batch_size = labels.shape[0] + self.model.zero_grad() + output_cl = self.model(images) + + sigmoid = nn.Sigmoid() # used for calculate accuracy + output_cl = sigmoid(output_cl) + loss_cl = self.loss_classifier(output_cl, class_label) + + loss_cl.backward() + optimizer.step() + + total_loss_cl, total_cl_acc, output_cl, output_probability = self.__calculate_accuracy(output_cl, + class_label, + train_batch_size, + loss_cl, + total_loss_cl, + total_cl_acc) + + labels = labels.cpu() + output_cl = output_cl.cpu() + output_probability = output_probability.cpu() + for i in range(output_cl.shape[1]): + self.train_trust_answers[i].extend(labels[:, i].tolist()) + self.train_model_answers[i].extend(output_cl[:, i].tolist()) + self.train_probabilities[i].extend(output_probability[:, i].tolist()) + + torch.cuda.empty_cache() + + if best_loss is None or total_loss_cl < best_loss: + best_loss = total_loss_cl + self.best_weights = copy.deepcopy(self.model.state_dict()) + + f_1_score_text, recall_score_text, precision_score_text = utils.calculate_metric(self.classes, + self.train_trust_answers, + self.train_model_answers) + text = "TRAIN={} Loss_CL={:.10f} Accuracy_CL_Percent={:.5f} {} {} {} ".format(epoch, + total_loss_cl / set_size, + total_cl_acc / set_size, + f_1_score_text, + recall_score_text, + precision_score_text) + if epoch % save_train_roc_each_epochs == 0: + auc_roc = "auc_roc=" + for idx, i in enumerate(self.train_trust_answers): + auc_roc += "trust_{}={}".format(idx, ",".join(list(map(lambda x: "{}".format(x), i)))) + for idx, i in enumerate(self.train_probabilities): + auc_roc += "prob_{}={}".format(idx, ",".join(list(map(lambda x: "{:.5f}".format(x), i)))) + text += auc_roc + + print(text) + P.write_to_log(text) + if epoch % test_each_epochs == 0: + test_loss, _ = self.test(test_data_set, epoch, save_test_roc_each_epochs) + if best_test_loss is None or test_loss < best_test_loss: + best_test_loss = test_loss + self.best_test_weights = copy.deepcopy(self.model.state_dict()) + + self.train_model_answers = [[] for _ in range(self.classes)] + self.train_trust_answers = [[] for _ in range(self.classes)] + self.test_model_answers = [[] for _ in range(self.classes)] + self.test_trust_answers = [[] for _ in range(self.classes)] + self.train_probabilities = [[] for _ in range(self.classes)] + self.test_probabilities = [[] for _ in range(self.classes)] + + self.save_model(self.best_test_weights, "classifier_test_weights") + self.save_model(self.best_weights, "classifier_train_weights") + + def test(self, test_data_set, epoch: int, save_test_roc_each_epoch: int): + test_total_loss_cl = 0 + test_total_cl_acc = 0 + test_size = 0 + for images, _, labels in test_data_set: + test_size += 1 # images.size(0) + if self.gpu: + images, labels = send_to_gpu(images, labels) + class_label = labels + batch_size = labels.shape[0] + output_cl = self.model(images) + + grad_target = output_cl * class_label + grad_target.backward(gradient=class_label * output_cl, retain_graph=True) + + sigmoid = nn.Sigmoid() # used for calculate accuracy + output_cl = sigmoid(output_cl) + loss_cl = self.loss_classifier(output_cl, class_label) + + test_total_loss_cl, test_total_cl_acc, output_cl, output_probability = self.__calculate_accuracy(output_cl, + class_label, + batch_size, + loss_cl, + test_total_loss_cl, + test_total_cl_acc) + labels = labels.cpu() + output_cl = output_cl.cpu() + output_probability = output_probability.cpu() + for i in range(output_cl.shape[1]): + self.test_trust_answers[i].extend(labels[:, i].tolist()) + self.test_model_answers[i].extend(output_cl[:, i].tolist()) + self.test_probabilities[i].extend(output_probability[:, i].tolist()) + + # test_size = len(test_data_set) + test_total_loss_cl /= test_size + test_total_cl_acc /= test_size + + f_1_score_text, recall_score_text, precision_score_text = utils.calculate_metric(self.classes, + self.test_trust_answers, + self.test_model_answers) + text = "TEST Loss_CL={:.10f} Accuracy_CL_Percent={:.5f} {} {} {} ".format(test_total_loss_cl, + test_total_cl_acc, + f_1_score_text, + recall_score_text, + precision_score_text) + if epoch % save_test_roc_each_epoch == 0: + auc_roc = "auc_roc=" + for idx, i in enumerate(self.test_trust_answers): + auc_roc += "trust_{}={}".format(idx, ",".join(list(map(lambda x: "{}".format(x), i)))) + for idx, i in enumerate(self.test_probabilities): + auc_roc += "prob_{}={}".format(idx, ",".join(list(map(lambda x: "{:.5f}".format(x), i)))) + text += auc_roc + + print(text) + P.write_to_log(text) + + return test_total_loss_cl, test_total_cl_acc + + def save_model(self, weights, name="classifier-model"): + try: + name = name + self.description + datetime.today().strftime('%Y-%m-%d-_-%H_%M_%S') + ".torch" + saved_dir = os.path.join(P.base_data_dir, 'classifier_weights') + os.makedirs(saved_dir, exist_ok=True) + saved_file = os.path.join(saved_dir, name) + torch.save(weights, saved_file) + print("Save model: {}".format(name)) + P.write_to_log("Save model: {}".format(name)) + except Exception as e: + print("Can't save model: {}".format(name), e) + P.write_to_log("Can't save model: {}".format(name), e) + + def __calculate_accuracy(self, output_cl, class_label, batch_size, loss_cl, total_loss_cl, total_cl_acc): + output_probability = output_cl.clone() + output_cl[output_cl >= probability_threshold] = 1 + output_cl[output_cl < probability_threshold] = 0 + cl_acc = torch.eq(output_cl, class_label).sum() + + total_loss_cl += scalar(loss_cl.sum()) / batch_size + total_cl_acc += scalar(cl_acc.sum()) / (batch_size * self.classes) + return total_loss_cl, total_cl_acc, output_cl, output_probability diff --git a/classifier.sh b/classifier.sh new file mode 100755 index 0000000..32992db --- /dev/null +++ b/classifier.sh @@ -0,0 +1,18 @@ +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 2000 --test_left 2001 --test_right 2592 --description new_measures + +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 500 --test_left 501 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 500 --test_left 501 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 500 --test_left 501 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 500 --test_left 501 --test_right 2592 --description new_measures + +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 1000 --test_left 1001 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 1000 --test_left 1001 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 1000 --test_left 1001 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 1000 --test_left 1001 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 1000 --test_left 1001 --test_right 2592 --description new_measures + +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 100 --test_left 101 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 100 --test_left 101 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 100 --test_left 101 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 100 --test_left 101 --test_right 2592 --description new_measures +~/nduginec_evn3/bin/python ~/ml-diplom/main_classifier.py --train_left 0 --train_right 100 --test_left 101 --test_right 2592 --description new_measures diff --git a/gain.py b/gain.py new file mode 100644 index 0000000..57485e0 --- /dev/null +++ b/gain.py @@ -0,0 +1,481 @@ +import torch +import torch.nn.functional as F +import torchvision.models as m +import torch.nn as nn +import copy +import property as P +from datetime import datetime +import os +import utils + +EPS = 1e-10 +probability_threshold = 0.5 + + +def scalar(tensor): + return tensor.data.cpu().item() + + +def reduce_boundaries(boundaries: int, batch_size=10, huge: int = -10000): + # assume BSx1x224x224 + zeros = torch.zeros((batch_size, 1, 224, 224)) + zeros[:, :, 0:boundaries, :] = huge + zeros[:, :, 224 - boundaries:224, :] = huge + zeros[:, :, :, 0:boundaries] = huge + zeros[:, :, :, 224 - boundaries:224] = huge + return zeros + + +class AttentionGAIN: + # 28 + def __init__(self, description: str, classes: int, gradient_layer_name="features.27", + from_gradient_layer=False, + weights=None, + gpu=False, + device=0, + loss_classifier=None, + usage_am_loss=False, + alpha=1, + omega=10, + sigma=0.5): + # validation + if not gradient_layer_name: + raise ValueError('Missing required argument gradient_layer_name') + if gpu and device is None: + raise ValueError('Missing required argument device, but gpu enable') + + # set gpu options + self.gpu = gpu + self.device = device + self.description = description + self.usage_am_loss = usage_am_loss + + self.classes = classes + + # define model + self.model = m.vgg16(pretrained=True) + num_features = self.model.classifier[6].in_features + self.model.classifier[6] = nn.Linear(num_features, self.classes) + + self.best_weights = None + self.best_test_weights = None + + # define loss classifier for classifier path + # create loss function + if loss_classifier is None: + self.loss_cl = torch.nn.BCELoss() + self.gain_loss_cl = torch.nn.BCEWithLogitsLoss() + + if weights: + self.model.load_state_dict(weights) + + self.minus_mask = reduce_boundaries(8) + if self.gpu: + self.model = self.model.cuda(self.device) + self.tensor_source = torch.cuda + self.minus_mask = self.minus_mask.cuda(self.device) + else: + self.tensor_source = torch + + # wire up our hooks for heatmap creation + self.from_gradient_layer = from_gradient_layer + self.gradient_layer_name = gradient_layer_name + + self.registered_for_update_weights = self.register_weights_gradient() + + self._register_hooks(self.gradient_layer_name) + + # misc parameters + self.omega = omega + self.sigma = sigma + self.alpha = alpha + + self.train_model_answers = [[] for _ in range(self.classes)] + self.train_trust_answers = [[] for _ in range(self.classes)] + self.train_probabilities = [[] for _ in range(self.classes)] + + self.test_model_answers = [[] for _ in range(self.classes)] + self.test_trust_answers = [[] for _ in range(self.classes)] + self.test_probabilities = [[] for _ in range(self.classes)] + + def _register_hooks(self, layer_name): + # this wires up a hook that stores both the activation and gradient of the conv layer we are interested in + def forward_hook(module, input_, output_): + self._last_activation = output_ + + def backward_hook(module, grad_in, grad_out): + self._last_grad = grad_out[0] + + # locate the layer that we are concerned about + gradient_layer_found = False + for idx, m in self.model.named_modules(): + if idx == layer_name: + m.register_forward_hook(forward_hook) + m.register_backward_hook(backward_hook) + gradient_layer_found = True + break + + # for our own sanity, confirm its existence + if not gradient_layer_found: + raise AttributeError('Gradient layer %s not found in the internal model' % layer_name) + + def forward(self, data, label, segments, train_batch_size: int, ill_index: int): + data, label, segments = self._convert_data_and_label(data, label, segments) + return self._forward(data, label, segments, train_batch_size, ill_index) + + def train(self, rds, epochs, test_each_epochs: int, save_test_roc_each_epochs: int, save_train_roc_each_epochs: int, + pre_train_epoch: int = 25, learning_rate=1e-6): + + self.best_weights = copy.deepcopy(self.model.state_dict()) + best_loss = None + best_test_loss = None + + opt = torch.optim.Adam(self.registered_for_update_weights, lr=learning_rate) + for epoch in range(1, epochs, 1): + + loss_cl_sum_segm = 0 + loss_am_sum_segm = 0 + acc_cl_sum_segm = 0 + loss_sum_segm = 0 + loss_e_sum_segm = 0 + + loss_cl_sum_no_segm = 0 + acc_cl_sum_no_segm = 0 + + with_segments_elements = 0 + without_segments_elements = 0 + + for images, segments, labels in rds['train_segment']: + # тренирую здесь с использованием сегментов + with_segments_elements += 1 # images.shape[0] + loss_sum_segm, loss_cl_sum_segm, loss_am_sum_segm, acc_cl_sum_segm, loss_e_sum_segm = self.__train_gain_branch( + epoch, + pre_train_epoch, + images, + segments, + labels, + opt, + loss_sum_segm, + loss_cl_sum_segm, + loss_am_sum_segm, + acc_cl_sum_segm, + loss_e_sum_segm) + + for images, segments, labels in rds['train_classifier']: + without_segments_elements += 1 # images.shape[0] + loss_cl_sum_no_segm, acc_cl_sum_no_segm = self.__train_classifier_branch(images, labels, opt, + loss_cl_sum_no_segm, + acc_cl_sum_no_segm) + + last_acc_total_segm = acc_cl_sum_segm / self.classes + last_acc_total_segm /= with_segments_elements + + last_acc_total = (last_acc_total_segm + acc_cl_sum_no_segm / without_segments_elements) / 2 + + loss_cl_sum_total_segm = loss_cl_sum_segm / self.classes + loss_cl_sum_total_segm /= with_segments_elements + + loss_cl_sum_total = (loss_cl_sum_total_segm + loss_cl_sum_no_segm /without_segments_elements) / 2 + + f_1_score_text, recall_score_text, precision_score_text = utils.calculate_metric(self.classes, + self.train_trust_answers, + self.train_model_answers) + prefix = "PRETRAIN" if epoch < pre_train_epoch else "TRAIN" + text = "{}={} Loss_CL={:.5f} Loss_AM={:.5f} Loss_E={:.5f} Loss_Total={:.5f} Accuracy_CL={:.5f} " \ + "{} {} {} ".format( + prefix, + epoch, + loss_cl_sum_total, + loss_am_sum_segm / (with_segments_elements * self.classes + EPS), + loss_e_sum_segm / (with_segments_elements * self.classes + EPS), + loss_sum_segm / (with_segments_elements * self.classes + EPS), + last_acc_total, + f_1_score_text, + recall_score_text, + precision_score_text) + + if epoch % save_train_roc_each_epochs == 0: + auc_roc = "auc_roc=" + for idx, i in enumerate(self.train_trust_answers): + auc_roc += "trust_{}={}".format(idx, ",".join(list(map(lambda x: "{}".format(x), i)))) + for idx, i in enumerate(self.train_probabilities): + auc_roc += "prob_{}={}".format(idx, ",".join(list(map(lambda x: "{:.5f}".format(x), i)))) + text += auc_roc + print(text) + P.write_to_log(text) + + if epoch % test_each_epochs == 0: + test_loss, _ = self.test(rds['test'], epoch, save_test_roc_each_epochs) + if best_test_loss is None or test_loss < best_test_loss: + best_test_loss = test_loss + self.best_test_weights = copy.deepcopy(self.model.state_dict()) + + if best_loss is None or loss_sum_segm < best_loss: + best_loss = loss_sum_segm + self.best_weights = copy.deepcopy(self.model.state_dict()) + + self.train_model_answers = [[] for _ in range(self.classes)] + self.train_trust_answers = [[] for _ in range(self.classes)] + self.train_probabilities = [[] for _ in range(self.classes)] + + self.test_model_answers = [[] for _ in range(self.classes)] + self.test_trust_answers = [[] for _ in range(self.classes)] + self.test_probabilities = [[] for _ in range(self.classes)] + + self.save_model(self.best_test_weights, "gain_test_weights") + self.save_model(self.best_weights, "gain_train_weights") + + def __train_gain_branch(self, current_epoch: int, pre_train_epoch: int, images, segments, labels, + optimizer, loss_sum, loss_cl_sum, am_sum, acc_cl_sum, e_sum): + + train_batch_size = images.shape[0] + self.minus_mask = reduce_boundaries(8, train_batch_size) + if self.gpu: + images = images.cuda(self.device) # bs x 3 x 224 x 224 + segments = segments.cuda(self.device) # bs x 1 x 224 x 224 + labels = labels.cuda(self.device) # bs x 5 + self.minus_mask = self.minus_mask.cuda(self.device) + + for ill_index in range(0, self.classes): + total_loss, loss_cl, loss_am, loss_e, output_cl, output_probability, acc_cl, _, _, _ = \ + self.forward(images, + labels, + segments[:, ill_index], + train_batch_size, + ill_index) + + self.save_train_data(labels, output_cl, output_probability) + + loss_sum += scalar(total_loss) + loss_cl_sum += scalar(loss_cl) + am_sum += scalar(loss_am) + acc_cl_sum += scalar(acc_cl) + e_sum += scalar(loss_e) + + if current_epoch <= pre_train_epoch: + loss_cl.backward() + else: + total_loss.backward() + optimizer.step() + torch.cuda.empty_cache() + return loss_sum, loss_cl_sum, am_sum, acc_cl_sum, e_sum + + def __train_classifier_branch(self, images, labels, optimizer, loss_cl_sum, acc_cl_sum): + if self.gpu: + images = images.cuda(self.device) # bs x 3 x 224 x 224 + labels = labels.cuda(self.device) # bs x 10 + output_cl_model = self.model(images) + + sigmoid = nn.Sigmoid() # used for calculate accuracy + output_cl = sigmoid(output_cl_model) + loss_cl = self.loss_cl(output_cl, labels) + + loss_cl.backward() + optimizer.step() + self.model.zero_grad() + + batch_size = images.shape[0] + + output_probability, output_cl, cl_acc = self.calculate_accuracy(labels, output_cl, batch_size) + + self.save_train_data(labels, output_cl, output_probability) + + # accumulate information + acc_cl_sum += scalar(cl_acc.sum()) + loss_cl_sum += scalar(loss_cl.sum()) + + return loss_cl_sum, acc_cl_sum + + # тестирование взять с классификатора(взял) + def test(self, test_data_set, epoch: int, save_test_roc_each_epoch: int): + test_total_loss_cl = 0 + test_total_cl_acc = 0 + test_size = 0 + for images, _, labels in test_data_set: + test_size += 1 # images.size(0) + batch_size = images.shape[0] + if self.gpu: + # images, labels = send_to_gpu(images, labels) + images = images.cuda(self.device) + labels = labels.cuda(self.device) + + output_cl_model = self.model(images) + + sigmoid = nn.Sigmoid() # used for calculate accuracy + output_cl = sigmoid(output_cl_model) + loss_cl = self.loss_cl(output_cl, labels) + + output_probability, output_cl, cl_acc = self.calculate_accuracy(labels, output_cl, batch_size) + + self.save_test_data(labels, output_cl, output_probability) + + test_total_loss_cl += scalar(loss_cl.sum()) # / batch_size + test_total_cl_acc += scalar(cl_acc) + + f_1_score_text, recall_score_text, precision_score_text = utils.calculate_metric(self.classes, + self.test_trust_answers, + self.test_model_answers) + test_total_loss_cl = (test_total_loss_cl / test_size) + test_total_cl_acc = (test_total_cl_acc / test_size) + text = 'TEST Loss_CL={:.5f} Accuracy_CL={:.5f} {} {} {} '.format(test_total_loss_cl, + test_total_cl_acc, + f_1_score_text, + recall_score_text, + precision_score_text) + if epoch % save_test_roc_each_epoch == 0: + auc_roc = "auc_roc=" + for idx, i in enumerate(self.test_trust_answers): + auc_roc += "trust_{}={}".format(idx, ",".join(list(map(lambda x: "{}".format(x), i)))) + for idx, i in enumerate(self.test_probabilities): + auc_roc += "prob_{}={}".format(idx, ",".join(list(map(lambda x: "{:.5f}".format(x), i)))) + text += auc_roc + + P.write_to_log(text) + print(text) + + return test_total_loss_cl, test_total_cl_acc + + def _attention_map_forward(self, data, label, ill_index: int): + + output_cl_model = self.model(data) + # тут раньше была сумма, но не думаю что она нужна в данном случае + grad_target = output_cl_model * label + ones = torch.ones(label.shape[0]) + if self.gpu: + ones = ones.cuda(self.device) + + sigmoid = nn.Sigmoid() # used for calculate accuracy + output_cl = sigmoid(output_cl_model) + loss_cl = self.gain_loss_cl(output_cl_model, label) + + grad_target[:, ill_index].backward(gradient=ones, retain_graph=True) + self.model.zero_grad() + + # Eq 1 + # grad = self._last_grad + # w_c = F.avg_pool2d(grad, (grad.shape[-2], grad.shape[-1]), 1) + # w_c_new_shape = (1, w_c.shape[0] * w_c.shape[1], w_c.shape[2], w_c.shape[3]) + # w_c = w_c.view(w_c_new_shape).unsqueeze(0) + + # Eq 2 + # TODO this support batching !!! + # weights = self._last_activation + # weights_new_shape = (1, weights.shape[0] * weights.shape[1], weights.shape[2], weights.shape[3]) + # weights = weights.view(weights_new_shape).unsqueeze(0) + + last_grad_GAP = F.adaptive_avg_pool2d(self._last_grad, 1) # weights + # self._last_activation = F.adaptive_avg_pool2d(self._last_activation, 1) # fl + A_c = torch.mul(self._last_activation, last_grad_GAP).sum(dim=1, keepdim=True) + A_c = F.relu(A_c) + A_c = F.upsample_bilinear(A_c, size=data.size()[2:]) + # gcam = F.relu(F.conv2d(weights, w_c)) + # A_c = F.upsample(gcam, size=data.size()[2:], mode='bilinear') + + return output_cl, loss_cl, A_c + + def _mask_image(self, gcam, image): + gcam_min = gcam.min() + gcam_max = gcam.max() + scaled_gcam = (gcam - gcam_min) / (gcam_max - gcam_min + EPS) + mask = F.sigmoid(self.omega * (scaled_gcam - self.sigma)) + masked_image = image - (image * mask) + return masked_image, mask + + def _forward(self, data, label, segment, train_batch_size: int, ill_index: int): + # TODO normalize elsewhere, this feels wrong (вроде здесь ок) + output_cl, loss_cl, gcam = self._attention_map_forward(data, label, ill_index) + + # Eq 4 + # TODO this support batching + I_star, mask = self._mask_image(gcam, data) + + if self.gpu: + loss_am = torch.tensor([0.0]).cuda(self.device) + else: + loss_am = torch.tensor([0.0]) + + if self.usage_am_loss: + output_am = self.model(I_star) + # Eq 5 + loss_am = F.sigmoid(output_am) * label + loss_am = loss_am.sum() / label.sum().type(self.tensor_source.FloatTensor) + + updated_segment_mask = segment * self.omega + self.minus_mask + loss_e = ((mask - updated_segment_mask) @ (mask - updated_segment_mask)).sum() + + # Eq 6 + total_loss = loss_cl + loss_e * 100 + self.alpha * loss_am + + output_probability, output_cl, cl_acc = self.calculate_accuracy(label, output_cl, train_batch_size) + + return total_loss, loss_cl, loss_am, loss_e, output_cl, output_probability, cl_acc, gcam, I_star, mask + + def _convert_data_and_label(self, data, label, segments): + # converts our data and label over to optional gpu + if self.gpu: + data = data.cuda(self.device) + label = label.cuda(self.device) + segments = segments.cuda(self.device) + + return data, label, segments + + def save_model(self, weights, name="gain-model"): + try: + name = name + self.description + "_date-" + datetime.today().strftime('%Y-%m-%d-_-%H_%M_%S') + ".torch" + saved_dir = os.path.join(P.base_data_dir, 'gain_weights') + os.makedirs(saved_dir, exist_ok=True) + saved_file = os.path.join(saved_dir, name) + torch.save(weights, saved_file) + print("Save model: {}".format(name)) + P.write_to_log("Save model: {}".format(name)) + except Exception as e: + print("Can't save model: {}".format(name), e) + P.write_to_log("Can't save model: {}".format(name), e) + + def save_train_data(self, labels, output_cl, output_probability): + output_cl = output_cl.cpu() + output_probability = output_probability.cpu() + labels = labels.cpu() + for i in range(output_cl.shape[1]): + self.train_trust_answers[i].extend(labels[:, i].tolist()) + self.train_model_answers[i].extend(output_cl[:, i].tolist()) + self.train_probabilities[i].extend(output_probability[:, i].tolist()) + + def save_test_data(self, labels, output_cl, output_probability): + output_cl = output_cl.cpu() + output_probability = output_probability.cpu() + labels = labels.cpu() + for i in range(output_cl.shape[1]): + self.test_trust_answers[i].extend(labels[:, i].tolist()) + self.test_model_answers[i].extend(output_cl[:, i].tolist()) + self.test_probabilities[i].extend(output_probability[:, i].tolist()) + + def calculate_accuracy(self, labels, output_cl, batch_size): + output_probability = output_cl.clone() + output_cl[output_cl >= probability_threshold] = 1 + output_cl[output_cl < probability_threshold] = 0 + cl_acc = torch.eq(output_cl, labels).sum().float() + cl_acc /= (batch_size * self.classes + EPS) + return output_probability, output_cl, cl_acc + + def register_weights_gradient(self): + for param in self.model.parameters(): + param.requires_grad = True + + # update all weights + if not self.from_gradient_layer: + print("all layers updates weights") + P.write_to_log("all layers updates weights") + return self.model.parameters() + + # register weights after marked layer + flag = False + result = [] + for registered_param, (name, param) in zip(self.model.parameters(), self.model.named_modules()): + if name == self.gradient_layer_name: + flag = True + if flag: + result.append(registered_param) + print("register layer: ", name) + P.write_to_log("register layer: ", name) + return result diff --git a/gain.sh b/gain.sh new file mode 100755 index 0000000..dd3d238 --- /dev/null +++ b/gain.sh @@ -0,0 +1,56 @@ +# source ~/nduginec_evn3/bin/activate + +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 1000 --train_right 2000 --test_left 2001 --test_right 2592 --gpu 1 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 1000 --train_right 2000 --test_left 2001 --test_right 2592 --gpu 1 --am_loss=True +# +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 501 --test_left 501 --test_right 2592 --gpu 1 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 501 --test_left 501 --test_right 2592 --gpu 1 --am_loss=True +# +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 250 --train_right 500 --test_left 501 --test_right 2592 --gpu 1 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 250 --train_right 500 --test_left 501 --test_right 2592 --gpu 1 --am_loss=True +# +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --am_loss=True +# +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 99 --train_right 100 --test_left 101 --test_right 2592 --gpu 1 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 99 --train_right 100 --test_left 101 --test_right 2592 --gpu 1 --am_loss=True + + +source ~/nduginec_evn3/bin/activate + +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.28 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.28 --am_loss=True + +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.27 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.27 --am_loss=True + +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.26 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.26 --am_loss=True + +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.25 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.25 --am_loss=True + +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.24 +# ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.24 --am_loss=True + + +~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.23 + +~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.23 --am_loss=True + +~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.22 + +~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.22 --am_loss=True + +~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.21 + +~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.21 --am_loss=True + +~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.20 + +~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.20 --am_loss=True + + +~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.19 ~/nduginec_evn3/bin/python ~/ml-diplom/main_gain.py --description measures --pre_train 25 --train_left 0 --segments 500 --train_right 1000 --test_left 1001 --test_right 2592 --gpu 1 --from_gradient_layer True --gradient_layer_name features.19 --am_loss=True + + diff --git a/heh2 b/heh2 deleted file mode 100644 index e69de29..0000000 diff --git a/image_loader.py b/image_loader.py new file mode 100644 index 0000000..643f43a --- /dev/null +++ b/image_loader.py @@ -0,0 +1,224 @@ +import os +import torch +import torch.utils.data.dataset +from torchvision import transforms +from PIL import Image +import property as P +import random + +composite = transforms.Compose([ + transforms.Scale((P.image_size, P.image_size)), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), + transforms.ToTensor(), +]) + +normalization = transforms.Compose([ + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) +]) + + +class DatasetLoader: + """ + Load ISIC files as images and cache them, or load from cache files + """ + + @staticmethod + def initial(): + return DatasetLoader(P.data_inputs_path, P.data_labels_path, P.cache_data_inputs_path, P.cache_data_labels_path) + + def __init__(self, input_path: str = None, target_path: str = None, cache_input_path: str = None, + cache_target_path: str = None, image_suffixes: list = ['.jpg', '.png', P.cached_extension]): + self.input_path = input_path + self.target_path = target_path + self.image_suffixes = image_suffixes + + # create cached path if not exists + if cache_input_path is None: + cache_input_path = os.path.join(input_path, "cached") + os.makedirs(cache_input_path, exist_ok=True) + print("created cache input dir: {}".format(cache_input_path)) + P.write_to_log("created cache input dir: {}".format(cache_input_path)) + if cache_target_path is None: + cache_target_path = os.path.join(target_path, "cached") + os.makedirs(cache_target_path, exist_ok=True) + print("created cache target dir: {}".format(cache_target_path)) + P.write_to_log("created cache target dir: {}".format(cache_target_path)) + self.cache_input_path = cache_input_path + self.cache_target_path = cache_target_path + + self.data = None + + def __get_input_image_list(self, input_path) -> list: + inputs = self.__get_id_value(input_path) + inputs.sort(key=lambda x: int(x[0])) + return inputs + + def __get_target_image_list(self, target_path) -> list: + targets = self.__get_id_value(target_path) + targets = list(map(lambda x: (x[0].split(P.attribute)[0], x[0].split(P.attribute)[1], x[1]), targets)) + reduced = dict() + for identifier, label, path in targets: + if identifier in reduced: + reduced[identifier][label] = path + else: + reduced[identifier] = {label: path} + reduced[identifier]['id'] = identifier + targets = [reduced[i] for i in reduced] + targets.sort(key=lambda x: int(x['id'])) + return targets + + def __merge_data(self, input_path, target_path) -> list: + inputs = self.__get_input_image_list(input_path) + targets = self.__get_target_image_list(target_path) + + def composite_zips(x): + inp = x[0] + tar = x[1] + tar[P.input_attribute] = inp[1] + return tar + + return list(map(composite_zips, zip(inputs, targets))) + + def __get_id_value(self, absolute_path: str) -> list: + arrays = [] + for _, _, f in os.walk(absolute_path): + for file in f: + for suffix in self.image_suffixes: + if file.endswith(suffix) and file.startswith(P.prefix): + identifier = file.split(suffix)[0].split(P.prefix)[1] + arrays.append((identifier, os.path.join(absolute_path, file))) + return arrays + + def save_images_to_tensors(self): + data = self.__merge_data(self.input_path, self.target_path) + data_len = len(data) + for idx, dct in enumerate(data): + for item in P.labels_attributes: + self.__save_torch(dct, item, self.cache_target_path) + self.__save_torch(dct, P.input_attribute, self.cache_input_path) + print("=" * 10) + print("save: {} of {} elements".format(idx, data_len)) + P.write_to_log("=" * 10) + P.write_to_log("save: {} of {} elements".format(idx, data_len)) + print("all saved successfully") + P.write_to_log("all saved successfully") + + def load_tensors(self, lower_bound=None, upper_bound=None, load_first_segments: int = 10 ** 20): + if self.data is None: + self.data = self.__merge_data(self.cache_input_path, self.cache_target_path) + random.shuffle(self.data) + data_len = len(self.data) + lower_bound = 0 if lower_bound is None else lower_bound + upper_bound = data_len if upper_bound is None else upper_bound + result = [] + + loads = 0 + for idx, dct in enumerate(self.data): + if lower_bound <= idx < upper_bound: + torch_dict = dict() + torch_dict['id'] = dct['id'] + # здесь как обсуждалось + # я помечу только первые N сегментов как существующие, остальные при загрузке + # я заменю НА ПУСТЫЕ МАТРИЦЫ + torch_dict['is_segments'] = False + if loads < load_first_segments: + torch_dict['is_segments'] = True + loads += 1 + for item in P.labels_attributes: + torch_dict[item] = torch.load(dct[item]) + torch_dict[P.input_attribute] = normalization(torch.load(dct[P.input_attribute])) + # normalization(torch.load(dct[P.input_attribute])) + result.append(torch_dict) + # print("left:{}, current:{}, right:{} processed".format(lower_bound, idx, upper_bound)) + # P.write_to_log("left:{}, current:{}, right:{} processed".format(lower_bound, idx, upper_bound)) + return result + + @staticmethod + def __save_torch(dct, item, path): + composited_image = composite(Image.open(dct[item])) + name = os.path.basename(dct[item])[:-4] + P.cached_extension + torch.save(composited_image, os.path.join(path, name)) + + +class ImageDataset(torch.utils.data.Dataset): + """ + data_set is result of execution DatasetLoader.load_tensors() + + возвращается кортеж: + (исходная картинка| 5 сегмент. масок| 10 элментов для заболевани) + + i -- если 1 то нет заболевания + i + 1 -- если 1 то есть заболевание + """ + + def __init__(self, data_set): + self.data_set = self.__prepare_data(data_set) + + def __len__(self): + return len(self.data_set) + + def __getitem__(self, item): + return self.data_set[item] + + @staticmethod + def __prepare_data(data: list): + result = [] + for item in range(0, len(data)): + dct = data[item] + input_data = dct[P.input_attribute] + target_data = dict() + for i in P.labels_attributes: + target_data[i] = dct[i] + target_data = ImageDataset.__cache_targets(target_data) + # tensor of input data + # tensor of segments + # tensor of labels answer + segm, labl = ImageDataset.split_targets(target_data) + # ничего не загружаю + if not dct['is_segments']: + segm = -1 # torch.zeros([5, 1, 224, 224]).float() + result.append((input_data, segm, labl)) + return result + + @staticmethod + def __cache_targets(dct: dict): + for i in P.labels_attributes: + ill_tag = i + '_value' + if ill_tag not in dct: + dct[ill_tag] = True if dct[i].sum().item() > 0 else False + return dct + + @staticmethod + def split_targets(dct: dict): + segments = None + # not exist ill, exist ill + labels = [] + # trusted = None + for idx, i in enumerate(P.labels_attributes): + segments = dct[i] if segments is None else torch.cat((segments, dct[i])) + # trusted = dct[i] + ill_tag = i + '_value' + if dct[ill_tag]: + labels.append(1) + else: + labels.append(0) + return segments, torch.tensor(labels).float() + + +def create_torch_tensors(): + loader = DatasetLoader(P.data_inputs_path, P.data_labels_path) + loader.save_images_to_tensors() + + +# from torch.utils.data.dataloader import DataLoader + +if __name__ == "__main__": + create_torch_tensors() + # loader = DatasetLoader.initial() + # train = loader.load_tensors(0, 100) + # test = loader.load_tensors(100, 150) + # train_set = DataLoader(ImageDataset(train), batch_size=10, shuffle=True, num_workers=4) + # for i, j, k, l in train_set: + # print(l.shape) + # loader = DatasetLoader(P.data_inputs_path, P.data_labels_path) + # loader.save_images_to_tensors() diff --git a/main.py b/main.py deleted file mode 100644 index e69de29..0000000 diff --git a/main_classifier.py b/main_classifier.py new file mode 100644 index 0000000..63f55f0 --- /dev/null +++ b/main_classifier.py @@ -0,0 +1,31 @@ +import image_loader as il +from torch.utils.data import DataLoader +import classifier +import property as P +import sys + +if __name__ == "__main__": + parsed = P.parse_input_commands().parse_args(sys.argv[1:]) + + description = parsed.description + train_left = int(parsed.train_left) + train_right = int(parsed.train_right) + test_left = int(parsed.test_left) + test_right = int(parsed.test_right) + P.initialize_log_name("metric_classifier_" + description) + try: + clf = classifier.Classifier(description, 5, gpu=True) + + loader = il.DatasetLoader.initial() + train = loader.load_tensors(train_left, train_right) + test = loader.load_tensors(test_left, test_right) + + train_set = DataLoader(il.ImageDataset(train), batch_size=10, shuffle=True, num_workers=0) + test_set = DataLoader(il.ImageDataset(test), batch_size=10, shuffle=True, num_workers=0) + + clf.train(100, 4, 4, 10, train_set, test_set) + except BaseException as e: + print("EXCEPTION", e) + print(type(e)) + P.write_to_log("EXCEPTION", e, type(e)) + raise e diff --git a/main_gain.py b/main_gain.py new file mode 100644 index 0000000..8131925 --- /dev/null +++ b/main_gain.py @@ -0,0 +1,61 @@ +import image_loader as il +from torch.utils.data import DataLoader +import gain +import property as P +import sys + +if __name__ == "__main__": + parsed = P.parse_input_commands().parse_args(sys.argv[1:]) + gpu = int(parsed.gpu) + parsed_description = parsed.description + train_left = int(parsed.train_left) + train_right = int(parsed.train_right) + test_left = int(parsed.test_left) + test_right = int(parsed.test_right) + train_segments_count = int(parsed.segments) + use_am_loss = parsed.am_loss.lower() == "true" + pre_train = int(parsed.pre_train) + gradient_layer_name = parsed.gradient_layer_name + from_gradient_layer = parsed.from_gradient_layer.lower() == "true" + + description = "{}_train_left-{},train_segments-{},train_right-{},test_left-{},test_right-{},am_loss-{}," \ + "pre_train-{}_gradient_layer_name-{}_from_gradient_layer-{}" \ + .format(parsed_description, + train_left, + train_segments_count, + train_right, + test_left, + test_right, + use_am_loss, + pre_train, + gradient_layer_name, + from_gradient_layer + ) + + P.initialize_log_name("metric_gain_" + description) + + try: + gain = gain.AttentionGAIN(description, 5, gpu=True, device=gpu, gradient_layer_name=gradient_layer_name, + from_gradient_layer=from_gradient_layer, + usage_am_loss=use_am_loss) + + loader = il.DatasetLoader.initial() + train_segments = loader.load_tensors(train_left, train_segments_count, train_segments_count) + train_classifier = loader.load_tensors(train_segments_count, train_right, 0) + test = loader.load_tensors(test_left, test_right) + + train_segments_set = DataLoader(il.ImageDataset(train_segments), batch_size=10, shuffle=True) + train_classifier_set = DataLoader(il.ImageDataset(train_classifier), batch_size=10, shuffle=True) + test_set = DataLoader(il.ImageDataset(test), batch_size=10) + + gain.train({'train_segment': train_segments_set, 'train_classifier': train_classifier_set, 'test': test_set}, + 101, + 4, + 4, + 10, + pre_train) + except BaseException as e: + print("EXCEPTION", e) + print(type(e)) + P.write_to_log("EXCEPTION", e, type(e)) + raise e diff --git a/notebooks/init.ipynb b/notebooks/init.ipynb deleted file mode 100644 index a9b2291..0000000 --- a/notebooks/init.ipynb +++ /dev/null @@ -1,46 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 2 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" - }, - "pycharm": { - "stem_cell": { - "cell_type": "raw", - "source": [], - "metadata": { - "collapsed": false - } - } - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file diff --git a/output_plot.py b/output_plot.py new file mode 100644 index 0000000..d3ece3c --- /dev/null +++ b/output_plot.py @@ -0,0 +1,440 @@ +"""draw plot of accuracy""" +import matplotlib.pyplot as plt +import os +import re +from sklearn.metrics import roc_curve, auc, precision_recall_curve, average_precision_score + +plot_images_path = "/home/nikita/PycharmProjects/ml-diplom/stat_plot_layers_grad" +logs_path = "/home/nikita/PycharmProjects/ml-data/logs" + + +def gain_train_parse(train_line): + values = train_line.split() + loss_cl = float(values[4][:-1]) + loss_am = float(values[6][:-1]) + loss_e = float(values[9][:-1]) + loss_total = float(values[12][:-1]) + accuracy = float(values[14][:-1]) + return loss_cl, loss_am, loss_e, loss_total, accuracy + + +def gain_test_parse(test_line): + values = test_line.split() + loss_cl = float(values[2][:-1]) + accuracy = float(values[4][:-1]) + return loss_cl, accuracy + + +def classifier_train_parse(train_line): + values = train_line.split() + loss_cl = float(values[7][:-1]) + accuracy = float(values[9][:-1]) + return loss_cl, accuracy + + +def classifier_test_parse(test_line): + values = test_line.split() + loss_cl = float(values[2][:-1]) + accuracy = float(values[4][:-1]) + return loss_cl, accuracy + + +def __load_statistics(dct: dict) -> tuple: + f_measures = [] + recall = [] + precision = [] + for i in range(0, 5): + key = 'f_1_{}'.format(i) + f_measures.append((key, float(dct[key]))) + f_measures.append(('f_1_global', float(dct['f_1_global']))) + + for i in range(0, 5): + key = 'recall_{}'.format(i) + recall.append((key, float(dct[key]))) + recall.append(('recall_global', float(dct['recall_global']))) + + for i in range(0, 5): + key = 'precision_{}'.format(i) + precision.append((key, float(dct[key]))) + precision.append(('precision_global', float(dct['precision_global']))) + return f_measures, recall, precision + + +def __parse_auc(auc_value: str) -> tuple: + splited = re.split(r'trust_[0-5]{1}=|prob_[0-5]{1}=', auc_value) + splited = list(filter(lambda x: len(x) > 0, splited)) + trust = [] + prob = [] + for i in range(0, 5): + trust.append(('trust_{}'.format(i), list(map(lambda x: int(float(x)), splited[i].split(","))))) + for i in range(0, 5): + prob.append(('prob_{}'.format(i), list(map(float, splited[5 + i].split(","))))) + return trust, prob + + +def __to_dict(input: str) -> dict: + dct = dict() + for key_value in input.split(): + idx = key_value.find("=") + if idx == -1: + continue + key = key_value[:idx] + value = key_value[idx + 1:] + dct[key] = value + return dct + + +def gain_parse_test_and_classifier_all(input: str): + dct = __to_dict(input) + loss_cl = float(dct['Loss_CL']) + + k = str(dct['precision_global']) + idx_auc = k.find("auc_roc") + if idx_auc != -1: + dct['precision_global'] = k[:idx_auc] + dct['auc_roc'] = k[k.find("=trust_0") + 1:] + accuracy_cl = float(dct['Accuracy_CL_Percent']) if 'Accuracy_CL_Percent' in dct else float(dct['Accuracy_CL']) + f_measures, recall, precision = __load_statistics(dct) + if not 'auc_roc' in dct: + return loss_cl, accuracy_cl, f_measures, recall, precision + else: + trust, prob = __parse_auc(dct['auc_roc']) + return loss_cl, accuracy_cl, f_measures, recall, precision, trust, prob + + +def gain_parse_train(input: str): + dct = __to_dict(input) + Loss_CL = float(dct['Loss_CL']) + Loss_AM = float(dct['Loss_AM']) + Loss_E = float(dct['Loss_E']) + Loss_Total = float(dct['Loss_Total']) + Accuracy_CL = dct['Accuracy_CL'] + if Accuracy_CL[0] == "=": + Accuracy_CL = float(Accuracy_CL[1:]) + else: + Accuracy_CL = float(Accuracy_CL) + f_measures, recall, precision = __load_statistics(dct) + if not 'auc_roc' in dct: + return Loss_CL, Loss_AM, Loss_E, Loss_Total, Accuracy_CL, f_measures, recall, precision + else: + trust, prob = __parse_auc(dct['auc_roc']) + return Loss_CL, Loss_AM, Loss_E, Loss_Total, Accuracy_CL, f_measures, recall, precision, trust, prob + + +def __load_file(file_path: str, train_parse, test_parse): + train = [] + test = [] + train_index = 1 + test_index = 4 + train_indexes = [] + test_indexes = [] + with open(file_path) as f: + for l in f.readlines(): + if "TRAIN" in l: + train.append(train_parse(l)) + train_indexes.append(train_index) + train_index += 1 + elif "TEST" in l: + test.append(test_parse(l)) + test_indexes.append(test_index) + test_index += 4 + file_name = os.path.basename(f.name) + if len(train) == 0 or len(test) == 0: + raise ValueError("Empty data") + return train, test, train_indexes, test_indexes, file_name + + +def draw_metrics_classification_plot(file_path: str): + train, test, train_indexes, test_indexes, file_name = __load_file(file_path, gain_parse_test_and_classifier_all, + gain_parse_test_and_classifier_all) + train_auc = 0 + test_auc = 0 + for i in train: + if len(i) > 5: + train_auc += 1 + for i in test: + if len(i) > 5: + test_auc += 1 + + fig, axes = plt.subplots(6 + max(train_auc, test_auc) * 2, 2, figsize=(15, 50)) + fig.tight_layout() + plt.subplots_adjust(bottom=0.5, top=2) + + def __set_train_axes(axes_index: int, label_text: str, item_index: int): + axes[axes_index][0].set_title(label_text) + axes[axes_index][0].plot(train_indexes, list(map(lambda x: x[item_index], train))) + + def __set_test_axes(axes_index: int, label_text: str, item_index: int): + axes[axes_index][0].set_title(label_text) + axes[axes_index][0].plot(test_indexes, list(map(lambda x: x[item_index], test))) + + def __set_train_measures(axes_index: int, label_text: str, item_index: int): + axes[axes_index][1].set_title(label_text) + for i in range(0, 6): + legend = train[0][item_index][i][0] + axes[axes_index][1].plot(train_indexes, list(map(lambda x: x[item_index][i][1], train)), label=legend) + axes[axes_index][1].legend(loc='upper left') + + def __set_test_measures(axes_index: int, label_text: str, item_index: int): + axes[axes_index][1].set_title(label_text) + for i in range(0, 6): + legend = test[0][item_index][i][0] + axes[axes_index][1].plot(test_indexes, list(map(lambda x: x[item_index][i][1], test)), label=legend) + axes[axes_index][1].legend(loc='upper left') + + __set_train_axes(0, "train classification loss", 0) + __set_train_axes(1, "train accuracy", 1) + __set_train_measures(0, "f_1_train", 2) + __set_train_measures(1, "recall_train", 3) + __set_train_measures(2, "precision_train", 4) + + __set_test_axes(2, "test classification loss", 0) + __set_test_axes(3, "test accuracy", 1) + __set_test_measures(3, "f_1_test", 2) + __set_test_measures(4, "recall_test", 3) + __set_test_measures(5, "precision_test", 4) + + train_idx = 0 + for idx, values in enumerate(train): + if len(values) <= 5: + continue + axes[6 + train_idx * 2][0].set_title("auc plot for train={}".format(idx + 1)) + axes[6 + train_idx * 2 + 1][0].set_title("auc plot for train={}".format(idx + 1)) + for i in range(0, 5): + trust_name, trust_value = values[5][i] + prob_name, prob_value = values[6][i] + a, b, _ = roc_curve(trust_value, prob_value) + c = auc(a, b) + axes[6 + train_idx * 2][0].plot(a, b, lw=2, label='ROC curve {} (area = {:.2f})'.format(prob_name[4:], c)) + a1, b1, _ = precision_recall_curve(trust_value, prob_value) + c1 = average_precision_score(trust_value, prob_value) + axes[6 + train_idx * 2 + 1][0].plot(a1, b1, lw=2, + label='PR curve {} (area = {:.2f})'.format(prob_name[4:], c1)) + axes[6 + train_idx * 2][0].legend(loc='upper left') + axes[6 + train_idx * 2 + 1][0].legend(loc='upper left') + train_idx += 1 + + test_idx = 0 + for idx, values in enumerate(test): + if len(values) <= 5: + continue + axes[6 + test_idx * 2][1].set_title("auc plot for test={}".format((idx + 1) * 4)) + axes[6 + test_idx * 2 + 1][1].set_title("auc plot for test={}".format((idx + 1) * 4)) + for i in range(0, 5): + trust_name, trust_value = values[5][i] + prob_name, prob_value = values[6][i] + a, b, _ = roc_curve(trust_value, prob_value) + c = auc(a, b) + axes[6 + test_idx * 2][1].plot(a, b, lw=2, label='ROC curve {} (area = {:.2f})'.format(prob_name[4:], c)) + a1, b1, _ = precision_recall_curve(trust_value, prob_value) + c1 = average_precision_score(trust_value, prob_value) + axes[6 + test_idx * 2 + 1][1].plot(a1, b1, lw=2, + label='PR curve {} (area = {:.2f})'.format(prob_name[4:], c1)) + axes[6 + test_idx * 2][1].legend(loc='upper left') + axes[6 + test_idx * 2 + 1][1].legend(loc='upper left') + test_idx += 1 + + for ax in axes[0:5][:].flat: + ax.set(xlabel='epoch', ylabel='value') + + for ax in axes[6:][:].flat: + ax.set(xlabel='False Positive Rate', ylabel='True Positive Rate') + + plt.suptitle(file_name, y=1.99) + plt.savefig(os.path.join(plot_images_path, file_name[:-4]), bbox_inches='tight') + plt.show() + + +def draw_gain_metric_plot(file_path: str): + train, test, train_indexes, test_indexes, file_name = __load_file(file_path, gain_parse_train, + gain_parse_test_and_classifier_all) + + train_auc = 0 + test_auc = 0 + for i in train: + if len(i) > 8: + train_auc += 1 + for i in test: + if len(i) > 5: + test_auc += 1 + + fig, axes = plt.subplots(7 + max(train_auc, test_auc) * 2, 2, figsize=(15, 50)) + fig.tight_layout() + plt.subplots_adjust(bottom=0.5, top=2) + + def __set_train_axes(axes_index: int, label_text: str, item_index: int): + axes[axes_index][0].set_title(label_text) + axes[axes_index][0].plot(train_indexes, list(map(lambda x: x[item_index], train))) + + def __set_test_axes(axes_index: int, label_text: str, item_index: int): + axes[axes_index][0].set_title(label_text) + axes[axes_index][0].plot(test_indexes, list(map(lambda x: x[item_index], test))) + + def __set_train_measures(axes_index: int, label_text: str, item_index: int): + axes[axes_index][1].set_title(label_text) + for i in range(0, 6): + legend = train[0][item_index][i][0] + axes[axes_index][1].plot(train_indexes, list(map(lambda x: x[item_index][i][1], train)), label=legend) + axes[axes_index][1].legend(loc='upper left') + + def __set_test_measures(axes_index: int, label_text: str, item_index: int): + axes[axes_index][1].set_title(label_text) + for i in range(0, 6): + legend = test[0][item_index][i][0] + axes[axes_index][1].plot(test_indexes, list(map(lambda x: x[item_index][i][1], test)), label=legend) + axes[axes_index][1].legend(loc='upper left') + + __set_train_axes(0, "train classification loss", 0) + __set_train_axes(1, "train am loss", 1) + __set_train_axes(2, "train e loss", 2) + __set_train_axes(3, "train total loss", 3) + __set_train_axes(4, "train accuracy", 4) + + __set_train_measures(0, "f_1_train", 5) + __set_train_measures(1, "recall_train", 6) + __set_train_measures(2, "precision_train", 7) + + __set_test_axes(5, "test classification loss", 0) + __set_test_axes(6, "test accuracy", 1) + + __set_test_measures(3, "f_1_test", 2) + __set_test_measures(4, "recall_test", 3) + __set_test_measures(5, "precision_test", 4) + + train_idx = 0 + for idx, values in enumerate(train): + if len(values) <= 8: + continue + axes[7 + train_idx * 2][0].set_title("auc plot for train={}".format(idx + 1)) + axes[7 + train_idx * 2 + 1][0].set_title("auc plot for train={}".format(idx + 1)) + for i in range(0, 5): + trust_name, trust_value = values[8][i] + prob_name, prob_value = values[9][i] + a, b, _ = roc_curve(trust_value, prob_value) + c = auc(a, b) + axes[7 + train_idx * 2][0].plot(a, b, lw=2, label='ROC curve {} (area = {:.2f})'.format(prob_name[4:], c)) + a1, b1, _ = precision_recall_curve(trust_value, prob_value) + c1 = average_precision_score(trust_value, prob_value) + axes[7 + train_idx * 2 + 1][0].plot(a1, b1, lw=2, + label='PR curve {} (area = {:.2f})'.format(prob_name[4:], c1)) + axes[7 + train_idx * 2][0].legend(loc='upper left') + axes[7 + train_idx * 2 + 1][0].legend(loc='upper left') + train_idx += 1 + + test_idx = 0 + for idx, values in enumerate(test): + if len(values) <= 5: + continue + axes[7 + test_idx * 2][1].set_title("auc plot for test={}".format((idx + 1) * 4)) + axes[7 + test_idx * 2 + 1][1].set_title("auc plot for test={}".format((idx + 1) * 4)) + for i in range(0, 5): + trust_name, trust_value = values[5][i] + prob_name, prob_value = values[6][i] + a, b, _ = roc_curve(trust_value, prob_value) + c = auc(a, b) + axes[7 + test_idx * 2][1].plot(a, b, lw=2, label='ROC curve {} (area = {:.2f})'.format(prob_name[4:], c)) + a1, b1, _ = precision_recall_curve(trust_value, prob_value) + c1 = average_precision_score(trust_value, prob_value) + axes[7 + test_idx * 2 + 1][1].plot(a1, b1, lw=2, + label='PR curve {} (area = {:.2f})'.format(prob_name[4:], c1)) + axes[7 + test_idx * 2][1].legend(loc='upper left') + axes[7 + test_idx * 2 + 1][1].legend(loc='upper left') + test_idx += 1 + + for ax in axes[0:7][:].flat: + ax.set(xlabel='epoch', ylabel='value') + + for ax in axes[8:][:].flat: + ax.set(xlabel='False Positive Rate', ylabel='True Positive Rate') + + plt.suptitle(file_name, y=1.99) + plt.savefig(os.path.join(plot_images_path, file_name.replace(".", "_")[:-4]), bbox_inches='tight') + plt.show() + + +def draw_gain_plot(file_path: str): + train, test, train_indexes, test_indexes, file_name = __load_file(file_path, gain_train_parse, gain_test_parse) + fig, axes = plt.subplots(7, figsize=(9, 11)) + fig.tight_layout() + plt.subplots_adjust(bottom=0.5, top=2) + + def __set_train_axes(axes_index: int, label_text: str, item_index: int): + axes[axes_index].set_title(label_text) + axes[axes_index].plot(train_indexes, list(map(lambda x: x[item_index], train))) + + def __set_test_axes(axes_index: int, label_text: str, item_index: int): + axes[axes_index].set_title(label_text) + axes[axes_index].plot(test_indexes, list(map(lambda x: x[item_index], test))) + + __set_train_axes(0, "train classification loss", 0) + __set_train_axes(1, "train am loss", 1) + __set_train_axes(2, "train e loss", 2) + __set_train_axes(3, "train total loss", 3) + __set_train_axes(4, "train accuracy", 4) + + __set_test_axes(5, "test classification loss", 0) + __set_test_axes(6, "test accuracy", 1) + + for ax in axes.flat: + ax.set(xlabel='epoch', ylabel='value') + plt.suptitle(file_name, y=1.99) + plt.savefig(os.path.join(plot_images_path, file_name.replace(".", "_")[:-4]), bbox_inches='tight') + + +def draw_classification_plot(file_path: str): + train, test, train_indexes, test_indexes, file_name = __load_file(file_path, classifier_train_parse, + classifier_test_parse) + fig, axes = plt.subplots(4, figsize=(9, 11)) + fig.tight_layout() + plt.subplots_adjust(bottom=0.5, top=2) + + def __set_train_axes(axes_index: int, label_text: str, item_index: int): + axes[axes_index].set_title(label_text) + axes[axes_index].plot(train_indexes, list(map(lambda x: x[item_index], train))) + + def __set_test_axes(axes_index: int, label_text: str, item_index: int): + axes[axes_index].set_title(label_text) + axes[axes_index].plot(test_indexes, list(map(lambda x: x[item_index], test))) + + __set_train_axes(0, "train classification loss", 0) + __set_train_axes(1, "train accuracy", 1) + + __set_test_axes(2, "test classification loss", 0) + __set_test_axes(3, "test accuracy", 1) + + for ax in axes.flat: + ax.set(xlabel='epoch', ylabel='value') + plt.suptitle(file_name, y=1.99) + plt.savefig(os.path.join(plot_images_path, file_name[:-4]), bbox_inches='tight') + + +import traceback + +def visualize_all(): + for r, d, f in os.walk(logs_path): + for file in f: + try: + if "metric_classifier" in file: + print("begin", file) + draw_metrics_classification_plot(os.path.join(r, file)) + print("end", file) + elif "classifier" in file: + print("begin", file) + draw_classification_plot(os.path.join(r, file)) + print("end", file) + elif "metric_gain" in file: + print("begin", file) + draw_gain_metric_plot(os.path.join(r, file)) + print("end", file) + elif "gain" in file: + print("begin", file) + draw_gain_plot(os.path.join(r, file)) + print("end", file) + except ValueError as e: + print("error file: {}".format(file), e) + traceback.print_exc() + + + +if __name__ == "__main__": + visualize_all() diff --git a/property.py b/property.py new file mode 100644 index 0000000..67f1e61 --- /dev/null +++ b/property.py @@ -0,0 +1,67 @@ +import os +from datetime import datetime +import sys +import argparse + +prefix = 'ISIC_' +attribute = '_attribute_' +image_size = 224 + +input_attribute = 'input' +cached_extension = '.torch' + +base_data_dir = "/home/nikita/PycharmProjects" +if not os.path.exists(base_data_dir): + base_data_dir = "/media/disk1/nduginec" + +data_inputs_path = base_data_dir + "/ISIC2018_Task1-2_Training_Input" +data_labels_path = base_data_dir + "/ISIC2018_Task2_Training_GroundTruth_v3" + +cache_data_inputs_path = base_data_dir + "/ISIC2018_Task1-2_Training_Input/cached" +cache_data_labels_path = base_data_dir + "/ISIC2018_Task2_Training_GroundTruth_v3/cached" + +log_path = base_data_dir + "/logs" + +current_log_name = None + + +def initialize_log_name(value: str): + global current_log_name + current_log_name = "log{}___{}.txt".format(datetime.today().strftime('%Y-%m-%d-_-%H_%M_%S'), value) + + +labels_attributes = [ + 'streaks', + 'negative_network', + 'milia_like_cyst', + 'globules', + 'pigment_network' +] + + +def write_to_log(*args): + try: + os.makedirs(log_path, exist_ok=True) + log = os.path.join(log_path, current_log_name) + with open(log, 'a+') as log_file: + for i in args: + log_file.write(str(i) + "\n") + log_file.flush() + except Exception as e: + print("Exception while write log", e) + + +def parse_input_commands(): + parser = argparse.ArgumentParser(description="Classifier/gain args") + parser.add_argument("--train_left", default=0) + parser.add_argument("--train_right") + parser.add_argument("--test_left") + parser.add_argument("--test_right") + parser.add_argument("--description", default="_DEF_DESCRIPTION_") + parser.add_argument("--am_loss", default="False") + parser.add_argument("--gpu", default=0) + parser.add_argument("--segments", default=10 ** 10) + parser.add_argument("--pre_train", default=15) + parser.add_argument("--gradient_layer_name", default="features.28") + parser.add_argument("--from_gradient_layer", default="False") + return parser diff --git a/requirements.txt b/requirements.txt index e69de29..0e8c91d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -0,0 +1,114 @@ +absl-py==0.8.1 +albumentations==0.4.3 +attrs==19.3.0 +backcall==0.1.0 +bleach==3.1.0 +cachetools==3.1.1 +catalyst==19.11.6 +certifi==2019.9.11 +cffi==1.13.0 +chardet==3.0.4 +crc32c==2.0 +cryptography==2.8 +cycler==0.10.0 +decorator==4.4.0 +defusedxml==0.6.0 +entrypoints==0.3 +future==0.18.2 +gitdb2==2.0.6 +GitPython==3.0.5 +google-auth==1.7.1 +google-auth-oauthlib==0.4.1 +grpcio==1.25.0 +idna==2.8 +imageio==2.6.1 +imgaug==0.2.6 +importlib-metadata==0.23 +ipykernel==5.1.2 +ipython==7.8.0 +ipython-genutils==0.2.0 +ipywidgets==7.5.1 +jedi==0.15.1 +Jinja2==2.10.3 +joblib==0.13.2 +jsonschema==3.1.1 +jupyter==1.0.0 +jupyter-client==5.3.4 +jupyter-console==6.0.0 +jupyter-core==4.6.0 +kiwisolver==1.1.0 +Markdown==3.1.1 +MarkupSafe==1.1.1 +matplotlib==3.1.1 +mistune==0.8.4 +mkl-fft==1.0.14 +mkl-random==1.1.0 +mkl-service==2.3.0 +more-itertools==7.2.0 +nbconvert==5.6.0 +nbformat==4.4.0 +networkx==2.4 +notebook==6.0.1 +numpy==1.17.2 +oauthlib==3.1.0 +olefile==0.46 +opencv-python==4.1.2.30 +opencv-python-headless==4.1.2.30 +packaging==19.2 +pandas==0.25.2 +pandocfilters==1.4.2 +parso==0.5.1 +pexpect==4.7.0 +pickleshare==0.7.5 +Pillow==6.2.0 +pip==19.3.1 +plotly==4.2.1 +prometheus-client==0.7.1 +prompt-toolkit==2.0.10 +protobuf==3.11.1 +ptyprocess==0.6.0 +pyasn1==0.4.8 +pyasn1-modules==0.2.7 +pycparser==2.19 +Pygments==2.4.2 +pygraphviz==1.3 +pyparsing==2.4.2 +pyrsistent==0.15.4 +pyTelegramBotAPI==3.6.6 +python-dateutil==2.8.0 +python-telegram-bot==12.2.0 +pytz==2019.3 +PyWavelets==1.1.1 +PyYAML==5.2 +pyzmq==18.1.0 +qtconsole==4.5.5 +requests==2.22.0 +requests-oauthlib==1.3.0 +retrying==1.3.3 +rsa==4.0 +safitty==1.3 +scikit-image==0.16.2 +scikit-learn==0.21.3 +scipy==1.3.1 +seaborn==0.9.0 +Send2Trash==1.5.0 +setuptools==41.4.0 +Shapely==1.6.4.pos +six==1.12.0 +smmap2==2.0.5 +tensorboard==2.0.2 +tensorboardX==1.9 +terminado==0.8.2 +testpath==0.4.2 +torch==1.2.0 +torchvision==0.4.0a0 +tornado==6.0.3 +tqdm==4.40.0 +traitlets==4.3.3 +urllib3==1.25.7 +wcwidth==0.1.7 +webencodings==0.5.1 +Werkzeug==0.16.0 +wheel==0.33.6 +widgetsnbextension==3.5.1 +zipp==0.6.0 \ No newline at end of file diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..0e819ac --- /dev/null +++ b/utils.py @@ -0,0 +1,42 @@ +import sklearn.metrics as metrics + + +def __to_global(a, b): + aa = [] + bb = [] + for index, i in enumerate(a): + aa.extend(list(map(lambda x: x * (index + 1), i))) + for index, i in enumerate(b): + bb.extend(list(map(lambda x: x * (index + 1), i))) + return aa, bb + + +def calculate_metric(classes, trust_answers, model_answer): + f_1_score_text = "" + for i in range(classes): + f_1_score_text += "f_1_{}={:.5f} ".format(i, + metrics.f1_score(trust_answers[i], + model_answer[i]) + ) + recall_score_text = "" + for i in range(classes): + recall_score_text += "recall_{}={:.5f} ".format(i, + metrics.recall_score(trust_answers[i], + model_answer[i]) + ) + + precision_score_text = "" + for i in range(classes): + precision_score_text += "precision_{}={:.5f} ".format(i, + metrics.precision_score(trust_answers[i], + model_answer[i]) + ) + + trust_answer, model_answer = __to_global(trust_answers, model_answer) + + f_1_score_text += "f_1_global={:.5f}".format(metrics.f1_score(trust_answer, model_answer, average='micro')) + recall_score_text += "recall_global={:.5f}".format( + metrics.recall_score(trust_answer, model_answer, average='micro')) + precision_score_text += "precision_global={:.5f}".format( + metrics.precision_score(trust_answer, model_answer, average='micro')) + return f_1_score_text, recall_score_text, precision_score_text diff --git a/visualize.py b/visualize.py new file mode 100644 index 0000000..ced111c --- /dev/null +++ b/visualize.py @@ -0,0 +1,51 @@ +""" +Copy paste =( +""" + +import torch +from torchvision.utils import make_grid +import numpy as np +import matplotlib.pyplot as plt +import time + + +def to_3_dim_image(img): + layer = img[0].tolist() + t =torch.tensor([layer] * 3) # flush_boundaries(torch.tensor([layer] * 3), 20) + t_min = t.min() + t_max = t.max() + t = (t - t_min) / (t_max - t_min) + return t + + +def flush_boundaries(t: torch.Tensor, boundaries: int): + for chanel in t: + for idx_i in range(0, 224): + for idx_j in range(0, 224): + if idx_i < boundaries or idx_i + boundaries >= 224 or idx_j < boundaries or idx_j + boundaries >= 224: + chanel[idx_i][idx_j] = 0 + return t + + +def create_empty_image(shape=(3, 224, 224)): + return torch.zeros(shape) + + +# 3 3 1 1 +def visualize(image: torch.Tensor, i_start: torch.Tensor, a_c: torch.Tensor, mask: torch.Tensor, segment: torch.Tensor, + epochs_trained): + a_c = to_3_dim_image(a_c) + # a_c[a_c > 0] = 1 + mask = to_3_dim_image(mask) + # mask[mask > 0] = 1 + + images = [image, i_start, to_3_dim_image(a_c), to_3_dim_image(mask), to_3_dim_image(segment)] + images = list(map(lambda x: x.cpu(), images)) + imgs = make_grid(images, padding=50).detach().numpy() + plt.imshow(np.transpose(imgs, (1, 2, 0))) + plt.figure() + plt.show() + + plt.imshow(np.transpose(imgs, (1, 2, 0))) + plt.savefig("images/image-I_star-A_c-mask-segment_epoch-" + str(epochs_trained) + " " + str(time.time_ns())) + plt.figure()