-
Notifications
You must be signed in to change notification settings - Fork 1
Austin doolittle #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
glcanvas
wants to merge
50
commits into
master
Choose a base branch
from
AustinDoolittle
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
50 commits
Select commit
Hold shift + click to select a range
3c90a0a
austin
glcanvas 102a0fc
austin gain
glcanvas accb0cd
austin gain
glcanvas 4489830
austin gain gpu support
glcanvas aa6fdf5
add classifier
glcanvas 01dc560
add classifier
glcanvas 3e4c032
classifier
glcanvas 1e656f8
classifier & gain
glcanvas 4f70f52
project structure improve
glcanvas 778eedf
project structure improve
glcanvas 4db5259
project structure improve
glcanvas b29d0a1
project structure improve
glcanvas 4adfba7
project structure improve
glcanvas ba71a86
add log file select
glcanvas b9915f0
gain rewrite
glcanvas 0be27ad
gain fix accuracy formula
glcanvas 0dea3aa
gain fix accuracy formula
glcanvas 88326e2
gain fix accuracy formula
glcanvas 96f4788
rewrite gain split
glcanvas b5785fb
merge with remove server
glcanvas e7fd9f3
ability to launch local and remote
glcanvas 88ae67b
gain.sh
glcanvas 7258d1b
executable
glcanvas e53fb3d
Merge branch 'AustinDoolittle' of https://github.com/glcanvas/ml-dipl…
glcanvas 1866490
gain.sh
glcanvas 6443fcf
visualize plots
glcanvas 5c311d8
Using gradient as in original paper
tanyapole 2c51380
Merge pull request #4 from glcanvas/fix-to-as-in-paper
glcanvas 270dc37
gain.sh
glcanvas baf2e44
reduce cells, shuffle data
glcanvas f367ca9
not to github
glcanvas c5efcc8
add a lot of metrics, rewrite output
glcanvas d9f9eee
rename logs
glcanvas ec1ee50
not to github
glcanvas 6cdc00a
fix gain metrics
glcanvas eae704d
improve plot visualize
glcanvas 9ab3f5f
improve plot visualize
glcanvas 30f817f
review accuracy
glcanvas a0a687f
not to github
glcanvas cdea02d
not to github
glcanvas 7484621
fix plot visualize, visualize all plots
glcanvas aff6e55
gain grad after feature name
glcanvas 635f814
gain grad after feature name visualize
glcanvas 8838859
not to github
glcanvas 9e90997
Merge branch 'AustinDoolittle' of https://github.com/glcanvas/ml-dipl…
glcanvas d2d3f57
measure fix 2git add -Agit add -A
glcanvas 9ddc6df
classifier fix
glcanvas 85fa22c
fix cl
glcanvas 4d60585
remove images
glcanvas 9264bb6
Merge remote-tracking branch 'origin/AustinDoolittle' into AustinDool…
glcanvas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,9 @@ | ||
| # ml-diplom | ||
| AustinDoolittle implementation | ||
|
|
||
| wia anaconda pip | ||
| opencv-python | ||
| imgaug | ||
|
|
||
|
|
||
| --------- | ||
| fastai |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why to compute the gradient during model evaluation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
described, resolved
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like this is redudant because in lines bellow: