From 730a51e734bb7d36ddd443e7084fa40548c39187 Mon Sep 17 00:00:00 2001 From: Qiushi Zhai Date: Sat, 1 Aug 2020 16:45:33 -0400 Subject: [PATCH] merge from Qiushi's fork to yewsg/yews: add polarity and focal_mechanism models (#18) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Replace MIT license by Apache 2.0 Protect trademarks and logos * include license and readme for pip package * add tests for yews.transform.functional * try travis from torchvision * Add travis.ci badge * Fix bug in travis.yml (#1) * Fix bug in travis.yml * add codecov badge * add python 3.7 to travis.ci * Add python 3.7 travis image * add download badge * update logo color * try torchvision’s sphinx setup * Update logo * Add appveyor.yml for Windows CI (#3) Add appveyor.yml for windows CI * add appveyor badge * add bages for anaconda cloud and pypi * move badge below the title * remove line between logo and title * Add more test to transforms (#2) * add more test to transforms * replace torch and numpy in module by direct import * add tests for transform correctness * Add instructin to install pytorch first * Update conda command * Uploading PyTorch builds to lijunzhu channel * not import yews in docs * Create initial docs (#4) * init docs by sphinx. * Update documentation theme to blue * add doc to README * use www subdomain for docs * Squashed commit of the following: commit ce4b4452b0871566870d02b88c7ef2e671f6f9e6 Author: Lijun Zhu Date: Wed Apr 17 13:12:43 2019 -0400 yews.transform under cover with 100% coverage. commit 2cf610831e0daeed0aba8fe22d0a390a8474f126 Author: Lijun Zhu Date: Tue Apr 16 09:01:48 2019 -0400 use www subdomain for docs commit 4c0b0605d91827183c714e1ce4fc6e65c916d280 Author: Lijun Zhu Date: Wed Apr 17 13:15:07 2019 -0400 add is_dataset to check dataset-like objects commit 5a7b0e8f77ddcb9b6485de90e22d1471437e7cca Author: Lijun Zhu Date: Tue Apr 16 21:46:35 2019 -0400 Refactorize yews.datasets * Squashed commit of the following: commit cbb2b6b2f401fa16b88e4067c1cc6888f46114ba Author: Lijun Zhu Date: Wed Apr 17 15:04:07 2019 -0400 rename module to avoid python built-ins commit e9ebf4678173e81b2e4cbc3a062ef80b1779baba Author: Lijun Zhu Date: Wed Apr 17 15:27:41 2019 -0400 yews.files under cover. commit 744daae4d25b27d50ac7571bfea10a119b8df2f9 Author: Lijun Zhu Date: Wed Apr 17 15:04:24 2019 -0400 yews.datasets.dirs under cover commit 1f8be24d7e5f75c93722bbf525cdb0895f8caf09 Author: Lijun Zhu Date: Wed Apr 17 15:04:07 2019 -0400 rename module to avoid python built-ins commit df8c897f081b473c5e8575efac6eaf48fb5d629e Author: Lijun Zhu Date: Wed Apr 17 13:44:15 2019 -0400 add test to yews.datasets commit ce4b4452b0871566870d02b88c7ef2e671f6f9e6 Author: Lijun Zhu Date: Wed Apr 17 13:12:43 2019 -0400 yews.transform under cover with 100% coverage. commit 2cf610831e0daeed0aba8fe22d0a390a8474f126 Author: Lijun Zhu Date: Tue Apr 16 09:01:48 2019 -0400 use www subdomain for docs commit 4c0b0605d91827183c714e1ce4fc6e65c916d280 Author: Lijun Zhu Date: Wed Apr 17 13:15:07 2019 -0400 add is_dataset to check dataset-like objects commit 5a7b0e8f77ddcb9b6485de90e22d1471437e7cca Author: Lijun Zhu Date: Tue Apr 16 21:46:35 2019 -0400 Refactorize yews.datasets * Add transform to convert label to int * Improve conda installation Use both lijunzhu and pytorch channels. * Squashed commit of the following: commit efe8105c558319d8145b0033f9c108466ca9ad97 Author: Lijun Zhu Date: Wed Apr 17 21:57:49 2019 -0400 automate building process commit b9b5ba8f86129ce422d0d521e26064c12bbb88e8 Author: Lijun Zhu Date: Wed Apr 17 21:57:07 2019 -0400 hide usage of scipy until necessary commit 9a7c981781ef4f32b346988e493feaf6be02b9dc Author: Lijun Zhu Date: Wed Apr 17 20:36:35 2019 -0400 comply with PyPI rst requirement. * automate release * improve docs. * move docs to a separate repo. * bump version to 0.0.3 * update logo url * Move metadata from setup.py to setup.cfg * improve automation. * yews get version from pkg installation. * Use scipy as an extra feature Known issue: `scipy` is imported via try-exception which is hard to unittest. However, it has been tested under conda env with/without scipy installed to verify the expected ModuleNotFoundError raised properly. * fix a bug to version in yews.__init__ * Remove not-runnable code from coverage report. * add pre-commit-config * add changelog.rst * change .coveragerc do not ignore __repr__ and NotImplementedError * add staticmethod valid() to check path. * refactorizing BaseDataset Add is_valid() and _handle_invalid() * add smoke test via @pytest.mark.smoke * modify datasets error msgs. * add `yews.datasets.utils` with tests covered 100% * check end of file * remove redundant __about__.py * update changelog * add `datasets.wenchuan` * fix code issues. * add test to datasets.wenchuan pytest.mark tests requiring internet connection. * update wenchuan example according to new api * clean temp files due to broken tests. * try svg for logo image * change back to gif * optimize logo and readme layout for mobile * add memory_limit to control loading of .npy file. * bump version to 0.0.4 * fix a typo. * add scipy to host environment * update docs url * fix doctring typo * sync meta.yaml and setup.cfg for install and test. * avoid downloading large file during test Slow internet connection friendly. Traive-CI will still run the full test. * explicitly add allow_pickle for older numpy. * update CHANGELOG.rst * Update installation notes in README.rst * Implement original cpic model in the paper. * create mariana dataset and tools to support it. * bump version to 0.0.5 * wenchuan dataset released to public * add numpy verion requirement for pathlib usage * fix test_datasets.py bug * add packaged SCSN dataset * avoid large downlad on traivs-ci * add detection example for mariana dataset * attempt to add OK dataset in the same way as Mariana * ignore all model files * Squashed commit of the following: commit 6b2c3cd13e4c6fa15613c16015ae0923ad9b4f21 Author: Lijun Zhu Date: Tue May 7 12:08:45 2019 -0400 fix wrong test name for tar utils commit 19e4a1c5715016e0fca594021bbb0a4ce5ef83b7 Merge: 0270bb9 010a8dd Author: Lijun Zhu Date: Wed May 1 21:39:52 2019 -0400 Merge branch 'master' into improve_scsn_dataset * master: ignore all model files commit 0270bb979ce7b2329d9835417e19fd6c6b9a1e08 Author: Lijun Zhu Date: Wed May 1 21:32:23 2019 -0400 repace tar.bz2 by tar for SCSN dataset * fix function name * fix bias bug * save results after training * save model class name * Allow save and load checkpoint. * ignore tags file from ctags. * add resume function during training * add picking * remove dimension check for numpy waveform * rename deploy to cpic * add hubconf for torch.hub module * migrate to torch.hub load_url * update cpic model * update wenchuan example for new models.cpic module * fix model_device bug * test training results save * fix wenchuan example path bug * fix wenchuan result path name * get filename as staticmethod * add ok_transfer example * fix bug in sac dataset * fix typo in ok transfer * fix typo in ok transfer * add loader to ok dataset * fix glob bug for ok transfer * change path str for obspy read * convert path after creating label * try to fix appveyor * install obspy for appveyor * do not download large file during testing * use tar instead of tar.bz2 for packaged datasets * use model intead of model_gen for trainer * show accuracy at the end of each epoch * add cpic model pretrianed on wenchuan dataset * rename example files * save current and best checkpoint during training * training from initial model * add scipy as a mandatory dependency * new deployment example for Mw 7.5 earthquake in southern pacific * start a doucment for rbp installation steps. * add miniconda and build pytorch from source * update environmental variable * disable qnnpack * fix a bug in applying transform during inference * bump version before release * correct typo * use tensor stack instead array stack * update example for sp deployment example * add raspberry pi files * marian deployment example * update cpic with a simplified model * update rbp example with plots * add batch_size for deployment * update rbp example * update rbp example with simplified model * update rbp example with simplified model * update rbp example * Correct a typo * Making some utils available outside classes * add example for preparing dataset from file names * move old example to experimental * reorganize dataset pacakge * correct typo * skipped broken waveforms. * fix bug * fix test for new dataset package * remove unused varialbe. * prepare waveform by groups * avoid skipping the entire group for one invalid phase. * merge groups of npys into one * add notes for merging large npy arrays. * make some object available on the top level of yews package. * docs fiex * fix bugs in example * training example * increase batch size for faster training and validation * increase memory limit to load the entire dataset in memory * run logner training * Update package structure Move source code under src/ directory and update tests module. * Update conda install pytorch command for testing. * Local test skip downloading large files. * Update mmap store code for npy. * Raise exception when file not exists. Previously, it returns a empty list which defer the raise of exception later when the list is consumed. However, it makes it harder to pin point the problem when debugging the code. Thus, we will raise exception at the moment it finds out the target directory does not exists. * Put a soft link to data inside example directory. * Temporarily disable tqdm in exporting data. Tests passed on local Mac setup but fails in both Linux and Windows remote machines. * Update CHANGELOG * Fix meta.yaml depdendency * Improve anaconda build process. Anaconda build was broken due to local files containing third party projects. Summary of Changes: 1. Build recipe from GitHub master branch instead of local path 2. Move anaconda recipe to a separate folder to avoid including unintended large files in the build 3. Update Makefile to work with the current file structure * Use softlink to data path. * Update URLs to package datasets. * change Wenchuan data url from gt to dropbox * add packaged_datasets SCSN_polarity * add packaged_datasets SCSN_polarity * change MEMORY_LIMIT from 2g to 10g * add import polarity.py * add polarity.py * add import numpy to polarity.py * added comment for pull request test * delete commit examples in polarity.py * add wenchuan cpic example * add scsn polarity training example * delete the note of 2d, will see it in the focal_mechanism.py * primitive LSTM model added in polarity.py * add Taiwan_focal_mechanism dataset * add Taiwan_focal_mechanism dataset * add focal_mechanism model * add focal_mechanism model * rename scsn.training.py to scsn_polarity_cnn.training.py * rename scsn.training.py to scsn_polarity_cnn.training.py * add taiwan_focal_mechanism.training.py to example * change the batch_size and learning rate of this example * add VGG style fm_v2 into models/focal_mechanism.py * modified VGG style fm_v2, use dropout(0.1) after each maxpool * delete unknow label, add vgg style model, remove the last 2 cnn layers * delete unknow label, add vgg style model, remove the last 2 cnn layers * add vgg style model for grad-cam, remove the last 2 cnn layers, stop at 4*4 * add a backup line of using AdamW instead of Adam * working LSTM (bidirectional untested) * finished LSTM for polarity * added example for polarity LSTM * fix the indent * change the wenchuan example file name * fix indent of polarity.py again * add a note: please use only 1 gpu to run LSTM, https://github.com/pytorch/pytorch/issues/21108 * add a note: please use only 1 gpu to run LSTM, https://github.com/pytorch/pytorch/issues/21108 * fix the dsets name in the example * add WeightedRandomSampler to balance the numbers of different labels in each batch * add Taiwan20092010 of cpic into packaged_datasets.py and __init__.py * add Taiwan20092010 of cpic into packaged_datasets.py and __init__.py * add example for cpic: Taiwan20092010 * add vgg style model cpicv3, stop at 4 for grad-cam * add vgg style model cpicv3, stop at 4 for grad-cam * vgg style model FmV2 stop at 8*8 * vgg style model FmV2 stop at 8*8 * update cpic.py and wenchuan_cpic.training.py based on the test of grad-cam with cpic_v3, 2000->1000->7->fc * forget why, so just add a comment #wav = wav.astype(float) into src/yews/transforms/functional.py as a backup * add RemoveMean RemoveTrend Taper BandpassFilter into src/yews/transforms/transforms.py * add polarity_cnn_lstm from Zijian Li * input 600->300 * rm data in example * fix super * update example * update cnn_lstm * add a line for LSTM which can only use one gpu * need to be updated, how to read the pretrained model * Resolve merge conflict * delete train.py.bak * fix bug <<<<<<< ======= >>>>>>> * recover some image and target * nothing important * xxxx to null link * delete the commit of using 1 gpu, in the future, use: device = torch.device(cuda:0 if torch.cuda.is_available() else cpu) model_on_device(model, device) * remove RemoveMean, change Taper and BandpassFilter Co-authored-by: Lijun Zhu Co-authored-by: Lijun Zhu Co-authored-by: Chujie Chen <38991172+ChujieChen@users.noreply.github.com> Co-authored-by: ChujieChen --- examples/data | 1 - examples/scsn_polarity_cnn.training.py | 104 ++++++ examples/scsn_polarity_lstm_training.py | 116 +++++++ examples/taiwan20092010_cpic.training.py | 71 +++++ examples/taiwan_focal_mechanism.training.py | 141 +++++++++ examples/wenchuan_cpic.training.py | 58 ++++ src/yews/datasets/packaged_datasets.py | 1 + src/yews/models/__init__.py | 2 + src/yews/models/cpic.py | 120 +++++-- src/yews/models/focal_mechanism.py | 331 ++++++++++++++++++++ src/yews/models/polarity.py | 220 +++++++++++++ src/yews/train/train.py.bak | 254 --------------- src/yews/transforms/functional.py | 1 - src/yews/transforms/transforms.py | 36 +++ 14 files changed, 1182 insertions(+), 274 deletions(-) delete mode 120000 examples/data create mode 100644 examples/scsn_polarity_cnn.training.py create mode 100644 examples/scsn_polarity_lstm_training.py create mode 100644 examples/taiwan20092010_cpic.training.py create mode 100644 examples/taiwan_focal_mechanism.training.py create mode 100644 examples/wenchuan_cpic.training.py create mode 100644 src/yews/models/focal_mechanism.py create mode 100644 src/yews/models/polarity.py delete mode 100644 src/yews/train/train.py.bak diff --git a/examples/data b/examples/data deleted file mode 120000 index 7cd9125..0000000 --- a/examples/data +++ /dev/null @@ -1 +0,0 @@ -/Volumes/data \ No newline at end of file diff --git a/examples/scsn_polarity_cnn.training.py b/examples/scsn_polarity_cnn.training.py new file mode 100644 index 0000000..22beae6 --- /dev/null +++ b/examples/scsn_polarity_cnn.training.py @@ -0,0 +1,104 @@ +import datetime +import torch +from torch.nn import CrossEntropyLoss +from torch.utils.data import DataLoader +from torch.utils.data import random_split + +import yews.datasets as dsets +import yews.transforms as transforms +from yews.train import Trainer + +from yews.models import polarity_cnn +model=polarity_cnn + + +if __name__ == '__main__': + + print("Now: start : " + str(datetime.datetime.now())) + + # Preprocessing + waveform_transform = transforms.Compose([ + #transforms.ZeroMean(), + #transforms.SoftClip(1e-4), + transforms.ToTensor(), + ]) + + # Prepare dataset + dsets.set_memory_limit(10 * 1024 ** 3) # first number is GB + # dset = dsets.Wenchuan(path='/home/qszhai/temp_project/deep_learning_course_project/cpic', download=False,sample_transform=waveform_transform) + dset = dsets.SCSN(path='/data6/scsn/polarity/train_npy', download=False, sample_transform=waveform_transform) + + # Split datasets into training and validation + train_length = int(len(dset) * 0.8) + val_length = len(dset) - train_length + train_set, val_set = random_split(dset, [train_length, val_length]) + + # Prepare dataloaders + train_loader = DataLoader(train_set, batch_size=5000, shuffle=True, num_workers=4) + val_loader = DataLoader(val_set, batch_size=10000, shuffle=False, num_workers=4) + + # Prepare trainer + trainer = Trainer(model(), CrossEntropyLoss(), lr=0.01) + + # Train model over training dataset + trainer.train(train_loader, val_loader, epochs=100, print_freq=100) + #resume='checkpoint_best.pth.tar') + + # Save training results to disk + trainer.results(path='scsn_polarity_results.pth.tar') + + # Validate saved model + results = torch.load('scsn_polarity_results.pth.tar') + model = model() + model.load_state_dict(results['model']) + trainer = Trainer(model, CrossEntropyLoss(), lr=0.1) + trainer.validate(val_loader, print_freq=100) + + print("Now: end : " + str(datetime.datetime.now())) + + import matplotlib.pyplot as plt + import numpy as np + + myfontsize1=14 + myfontsize2=18 + myfontsize3=24 + + results = torch.load('scsn_polarity_results.pth.tar') + + fig, axes = plt.subplots(2, 1, num=0, figsize=(6, 4), sharex=True) + axes[0].plot(results['val_acc'], label='Validation') + axes[0].plot(results['train_acc'], label='Training') + + #axes[1].set_xlabel("Epochs",fontsize=myfontsize2) + axes[0].set_xscale('log') + axes[0].set_xlim([1, 100]) + axes[0].xaxis.set_tick_params(labelsize=myfontsize1) + + axes[0].set_ylabel("Accuracies (%)",fontsize=myfontsize2) + axes[0].set_ylim([0, 100]) + axes[0].set_yticks(np.arange(0, 101, 10)) + axes[0].yaxis.set_tick_params(labelsize=myfontsize1) + + axes[0].grid(True, 'both') + axes[0].legend(loc=4) + + #axes[1].semilogx(results['val_loss'], label='Validation') + #axes[1].semilogx(results['train_loss'], label='Training') + axes[1].plot(results['val_loss'], label='Validation') + axes[1].plot(results['train_loss'], label='Training') + + axes[1].set_xlabel("Epochs",fontsize=myfontsize2) + axes[1].set_xscale('log') + axes[1].set_xlim([1, 100]) + axes[1].xaxis.set_tick_params(labelsize=myfontsize1) + + axes[1].set_ylabel("Losses",fontsize=myfontsize2) + axes[1].set_ylim([0.0, 1.0]) + axes[1].set_yticks(np.arange(0.0,1.01,0.2)) + axes[1].yaxis.set_tick_params(labelsize=myfontsize1) + + axes[1].grid(True, 'both') + axes[1].legend(loc=1) + + fig.tight_layout() + plt.savefig('Accuracies_train_val.pdf') diff --git a/examples/scsn_polarity_lstm_training.py b/examples/scsn_polarity_lstm_training.py new file mode 100644 index 0000000..d943a10 --- /dev/null +++ b/examples/scsn_polarity_lstm_training.py @@ -0,0 +1,116 @@ +import datetime +import torch +from torch.nn import CrossEntropyLoss +from torch.utils.data import DataLoader +from torch.utils.data import random_split + +import yews.datasets as dsets +import yews.transforms as transforms +from yews.train import Trainer + +#from yews.models import cpic +#from yews.models import cpic_v1 +#from yews.models import cpic_v2 +#cpic = cpic_v1 + +from yews.models import polarity_v1 +from yews.models import polarity_v2 +from yews.models import polarity_lstm +polarity=polarity_lstm + + +if __name__ == '__main__': + + print("Now: start : " + str(datetime.datetime.now())) + + # Preprocessing + waveform_transform = transforms.Compose([ + transforms.ZeroMean(), + #transforms.SoftClip(1e-4), + transforms.ToTensor(), + ]) + + # Prepare dataset + dsets.set_memory_limit(10 * 1024 ** 3) # first number is GB + # dset = dsets.Wenchuan(path='/home/qszhai/temp_project/deep_learning_course_project/cpic', download=False,sample_transform=waveform_transform) + dset = dsets.SCSN_polarity(path='/home/qszhai/temp_project/deep_learning_course_project/first_motion_polarity/scsn_data/train_npy', download=False, sample_transform=waveform_transform) + + # Split datasets into training and validation + train_length = int(len(dset) * 0.8) + val_length = len(dset) - train_length + train_set, val_set = random_split(dset, [train_length, val_length]) + + # Prepare dataloaders + train_loader = DataLoader(train_set, batch_size=5000, shuffle=True, num_workers=4) + val_loader = DataLoader(val_set, batch_size=10000, shuffle=False, num_workers=4) + + # Prepare trainer + # trainer = Trainer(cpic(), CrossEntropyLoss(), lr=0.1) + # note: please use only 1 gpu to run LSTM, https://github.com/pytorch/pytorch/issues/21108 + model_conf = {"hidden_size": 64} + plt = polarity(**model_conf) + trainer = Trainer(plt, CrossEntropyLoss(), lr=0.001) + + # Train model over training dataset + trainer.train(train_loader, val_loader, epochs=50, print_freq=100) + #resume='checkpoint_best.pth.tar') + + # Save training results to disk + trainer.results(path='scsn_polarity_results.pth.tar') + + # Validate saved model + results = torch.load('scsn_polarity_results.pth.tar') + #model = cpic() + model = plt + model.load_state_dict(results['model']) + trainer = Trainer(model, CrossEntropyLoss(), lr=0.001) + trainer.validate(val_loader, print_freq=100) + + print("Now: end : " + str(datetime.datetime.now())) + + import matplotlib.pyplot as plt + import numpy as np + + myfontsize1=14 + myfontsize2=18 + myfontsize3=24 + + results = torch.load('scsn_polarity_results.pth.tar') + + fig, axes = plt.subplots(2, 1, num=0, figsize=(6, 4), sharex=True) + axes[0].plot(results['val_acc'], label='Validation') + axes[0].plot(results['train_acc'], label='Training') + + #axes[1].set_xlabel("Epochs",fontsize=myfontsize2) + axes[0].set_xscale('log') + axes[0].set_xlim([1, 100]) + axes[0].xaxis.set_tick_params(labelsize=myfontsize1) + + axes[0].set_ylabel("Accuracies (%)",fontsize=myfontsize2) + axes[0].set_ylim([0, 100]) + axes[0].set_yticks(np.arange(0, 101, 10)) + axes[0].yaxis.set_tick_params(labelsize=myfontsize1) + + axes[0].grid(True, 'both') + axes[0].legend(loc=4) + + #axes[1].semilogx(results['val_loss'], label='Validation') + #axes[1].semilogx(results['train_loss'], label='Training') + axes[1].plot(results['val_loss'], label='Validation') + axes[1].plot(results['train_loss'], label='Training') + + axes[1].set_xlabel("Epochs",fontsize=myfontsize2) + axes[1].set_xscale('log') + axes[1].set_xlim([1, 100]) + axes[1].xaxis.set_tick_params(labelsize=myfontsize1) + + axes[1].set_ylabel("Losses",fontsize=myfontsize2) + axes[1].set_ylim([0.0, 1.0]) + axes[1].set_yticks(np.arange(0.0,1.01,0.2)) + axes[1].yaxis.set_tick_params(labelsize=myfontsize1) + + axes[1].grid(True, 'both') + axes[1].legend(loc=1) + + fig.tight_layout() + plt.savefig('Accuracies_train_val.pdf') diff --git a/examples/taiwan20092010_cpic.training.py b/examples/taiwan20092010_cpic.training.py new file mode 100644 index 0000000..67f23ee --- /dev/null +++ b/examples/taiwan20092010_cpic.training.py @@ -0,0 +1,71 @@ +import datetime +import torch +from torch.nn import CrossEntropyLoss +from torch.utils.data import DataLoader +from torch.utils.data import random_split + +import yews.datasets as dsets +import yews.transforms as transforms +from yews.train import Trainer + +#from yews.models import cpic +from yews.models import cpic_v1 +from yews.models import cpic_v2 +from yews.models import cpic_v3 +cpic = cpic_v3 + + +if __name__ == '__main__': + + print("Now: start : " + str(datetime.datetime.now())) + + # Preprocessing + waveform_transform = transforms.Compose([ + transforms.ZeroMean(), + #transforms.RemoveTrend(), + #transforms.RemoveMean(), + #transforms.Taper(), + #transforms.BandpassFilter(), + #transforms.SoftClip(2e-3), + #1e-2=1/100 100=1% max + #2e-3=4/2048 hist: max = 2048 + #import numpy as np;import matplotlib.pyplot as plt;samples=np.load("samples.npy",mmap_mode='r'); + #targets=np.load("targets.npy");target.shape + #plt.hist(samples[0:100000,0,:].flatten(), bins=100); plt.ylim([0.1,1.5e8]);plt.show() + transforms.ToTensor(), + ]) + + # Prepare dataset + dsets.set_memory_limit(10 * 1024 ** 3) # first number is GB + dset = dsets.Taiwan20092010(path='/home/qszhai/temp_project/deep_learning_course_project/cpic/Taiwan20092010', download=False, sample_transform=waveform_transform) + + # Split datasets into training and validation + train_length = int(len(dset) * 0.8) + val_length = len(dset) - train_length + train_set, val_set = random_split(dset, [train_length, val_length]) + + # Prepare dataloaders + train_loader = DataLoader(train_set, batch_size=2000, shuffle=True, num_workers=4) + # train_set: bastch_size = targets.shape / 500 + val_loader = DataLoader(val_set, batch_size=4000, shuffle=False, num_workers=4) + # train_set: bastch_size : larger is better if the GPU memory is enough. + # num_workers = number of cpu core, but limited by the disk speed. so 8 is good. + + # Prepare trainer + trainer = Trainer(cpic(), CrossEntropyLoss(), lr=0.1) + + # Train model over training dataset + trainer.train(train_loader, val_loader, epochs=300, print_freq=100) + #resume='checkpoint_best.pth.tar') + + # Save training results to disk + trainer.results(path='Taiwan20092010_results.pth.tar') + + # Validate saved model + results = torch.load('Taiwan20092010_results.pth.tar') + model = cpic() + model.load_state_dict(results['model']) + trainer = Trainer(model, CrossEntropyLoss(), lr=0.1) + trainer.validate(val_loader, print_freq=100) + + print("Now: end : " + str(datetime.datetime.now())) diff --git a/examples/taiwan_focal_mechanism.training.py b/examples/taiwan_focal_mechanism.training.py new file mode 100644 index 0000000..830cfbf --- /dev/null +++ b/examples/taiwan_focal_mechanism.training.py @@ -0,0 +1,141 @@ +import datetime +import numpy as np +import torch +from torch.nn import CrossEntropyLoss +from torch.utils.data import DataLoader +from torch.utils.data import random_split +from torch.utils.data.sampler import WeightedRandomSampler + +import yews.datasets as dsets +import yews.transforms as transforms +from yews.train import Trainer + +# from yews.models import cpic +# from yews.models import cpic_v1 +# from yews.models import cpic_v2 +# cpic = cpic_v1 + +# from yews.models import polarity_v1 +# polarity=polarity_v1 + +from yews.models import fm_v1 +from yews.models import fm_v2 +focal_mechanism=fm_v2 + +if __name__ == '__main__': + + print("Now: start : " + str(datetime.datetime.now())) + + # Preprocessing + waveform_transform = transforms.Compose([ + transforms.ZeroMean(), + transforms.SoftClip(1e-2), + transforms.ToTensor(), + ]) + + # Prepare dataset + dsets.set_memory_limit(10 * 1024 ** 3) # first number is GB + # dset = dsets.Wenchuan(path='/home/qszhai/temp_project/deep_learning_course_project/cpic', download=False,sample_transform=waveform_transform) +# dset = dsets.SCSN_polarity(path='/home/qszhai/temp_project/deep_learning_course_project/first_motion_polarity/scsn_data/npys', download=False, sample_transform=waveform_transform) +# dset = dsets.Taiwan_focal_mechanism(path='/home/qszhai/temp_project/deep_learning_course_project/focal_mechanism/npys_for_focal_mechanism', download=False, sample_transform=waveform_transform) + +# # Split datasets into training and validation +# train_length = int(len(dset) * 0.8) +# val_length = len(dset) - train_length +# train_set, val_set = random_split(dset, [train_length, val_length]) + + train_set= dsets.Taiwan_focal_mechanism(path='/home/qszhai/temp_project/deep_learning_course_project/focal_mechanism/npys_for_focal_mechanism/train_npy', download=False, sample_transform=waveform_transform) + val_set= dsets.Taiwan_focal_mechanism(path='/home/qszhai/temp_project/deep_learning_course_project/focal_mechanism/npys_for_focal_mechanism/validation_npy', download=False, sample_transform=waveform_transform) + + # prepare weights for dataloader of train, if want to balance the numbers of different labels in each batch + targets=np.load('/home/qszhai/temp_project/deep_learning_course_project/focal_mechanism/npys_for_focal_mechanism/train_npy/targets.npy') + targets_0_indexs=np.argwhere(targets==0).flatten() + targets_1_indexs=np.argwhere(targets==1).flatten() + targets_2_indexs=np.argwhere(targets==2).flatten() + weights=np.zeros(shape=targets.shape) + weights[targets_0_indexs]=targets.shape[0]/targets_0_indexs.shape[0] + weights[targets_1_indexs]=targets.shape[0]/targets_1_indexs.shape[0] + weights[targets_2_indexs]=targets.shape[0]/targets_2_indexs.shape[0] +# print(targets_0_indexs.shape[0],targets_1_indexs.shape[0],targets_2_indexs.shape[0]) +# print(weights[targets_0_indexs]) +# print(weights[targets_1_indexs]) +# print(weights[targets_2_indexs]) +# print(targets[0:10]) +# print(weights[0:10]) + weights=weights.tolist() + sampler = WeightedRandomSampler(weights,num_samples=len(weights), replacement=True) + + + # Prepare dataloaders +# train_loader = DataLoader(train_set, batch_size=15, shuffle=True, num_workers=4) + train_loader = DataLoader(train_set, batch_size=15, shuffle=False, sampler=sampler, num_workers=4) + val_loader = DataLoader(val_set, batch_size=15, shuffle=False, num_workers=4) + + # Prepare trainer + #trainer = Trainer(cpic(), CrossEntropyLoss(), lr=0.1) + #trainer = Trainer(polarity(), CrossEntropyLoss(), lr=0.1) + trainer = Trainer(focal_mechanism(), CrossEntropyLoss(), lr=0.001) + + # Train model over training dataset + trainer.train(train_loader, val_loader, epochs=100, print_freq=10) + #resume='checkpoint_best.pth.tar') + + # Save training results to disk + trainer.results(path='taiwan_focal_mechanism_results.pth.tar') + + # Validate saved model + results = torch.load('taiwan_focal_mechanism_results.pth.tar') + #model = cpic() + #model = polarity() + model = focal_mechanism() + model.load_state_dict(results['model']) + trainer = Trainer(model, CrossEntropyLoss(), lr=0.1) + trainer.validate(val_loader, print_freq=100) + + print("Now: end : " + str(datetime.datetime.now())) + +# import matplotlib.pyplot as plt +# import numpy as np + +# myfontsize1=14 +# myfontsize2=18 +# myfontsize3=24 + +# results = torch.load('taiwan_focal_mechanism_results.pth.tar') + +# fig, axes = plt.subplots(2, 1, num=0, figsize=(6, 4), sharex=True) +# axes[0].plot(results['val_acc'], label='Validation') +# axes[0].plot(results['train_acc'], label='Training') + +# #axes[1].set_xlabel("Epochs",fontsize=myfontsize2) +# axes[0].set_xlim([1, 100]) +# axes[0].xaxis.set_tick_params(labelsize=myfontsize1) + +# axes[0].set_ylabel("Accuracies (%)",fontsize=myfontsize2) +# axes[0].set_ylim([0, 100]) +# axes[0].set_yticks(np.arange(0, 101, 10)) +# axes[0].yaxis.set_tick_params(labelsize=myfontsize1) + +# axes[0].grid(True, 'both') +# axes[0].legend(loc=4) + +# #axes[1].semilogx(results['val_loss'], label='Validation') +# #axes[1].semilogx(results['train_loss'], label='Training') +# axes[1].plot(results['val_loss'], label='Validation') +# axes[1].plot(results['train_loss'], label='Training') + +# axes[1].set_xlabel("Epochs",fontsize=myfontsize2) +# axes[1].set_xlim([1, 100]) +# axes[1].xaxis.set_tick_params(labelsize=myfontsize1) + +# axes[1].set_ylabel("Losses",fontsize=myfontsize2) +# axes[1].set_ylim([0.0, 1.0]) +# axes[1].set_yticks(np.arange(0.0,1.01,0.2)) +# axes[1].yaxis.set_tick_params(labelsize=myfontsize1) + +# axes[1].grid(True, 'both') +# axes[1].legend(loc=1) + +# fig.tight_layout() +# plt.savefig('Accuracies_train_val.pdf') + diff --git a/examples/wenchuan_cpic.training.py b/examples/wenchuan_cpic.training.py new file mode 100644 index 0000000..4959068 --- /dev/null +++ b/examples/wenchuan_cpic.training.py @@ -0,0 +1,58 @@ +import datetime +import torch +from torch.nn import CrossEntropyLoss +from torch.utils.data import DataLoader +from torch.utils.data import random_split + +import yews.datasets as dsets +import yews.transforms as transforms +from yews.train import Trainer + +#from yews.models import cpic +from yews.models import cpic_v1 +from yews.models import cpic_v2 +from yews.models import cpic_v3 +cpic = cpic_v3 + +if __name__ == '__main__': + + print("Now: start : " + str(datetime.datetime.now())) + + # Preprocessing + waveform_transform = transforms.Compose([ + transforms.ZeroMean(), + transforms.SoftClip(1e-3), + transforms.ToTensor(), + ]) + + # Prepare dataset + dsets.set_memory_limit(10 * 1024 ** 3) # first number is GB + dset = dsets.Wenchuan(path='/home/qszhai/temp_project/deep_learning_course_project/cpic/wenchuan_data/train_npy', download=False,sample_transform=waveform_transform) + + # Split datasets into training and validation + train_length = int(len(dset) * 0.8) + val_length = len(dset) - train_length + train_set, val_set = random_split(dset, [train_length, val_length]) + + # Prepare dataloaders + train_loader = DataLoader(train_set, batch_size=1000, shuffle=True, num_workers=4) + val_loader = DataLoader(val_set, batch_size=2000, shuffle=False, num_workers=4) + + # Prepare trainer + trainer = Trainer(cpic(), CrossEntropyLoss(), lr=0.01) + + # Train model over training dataset + trainer.train(train_loader, val_loader, epochs=100, print_freq=10) + #resume='checkpoint_best.pth.tar') + + # Save training results to disk + trainer.results(path='wenchuan_results.pth.tar') + + # Validate saved model + results = torch.load('wenchuan_results.pth.tar') + model = cpic() + model.load_state_dict(results['model']) + trainer = Trainer(model, CrossEntropyLoss(), lr=0.1) + trainer.validate(val_loader, print_freq=100) + + print("Now: end : " + str(datetime.datetime.now())) diff --git a/src/yews/datasets/packaged_datasets.py b/src/yews/datasets/packaged_datasets.py index c612469..8737512 100644 --- a/src/yews/datasets/packaged_datasets.py +++ b/src/yews/datasets/packaged_datasets.py @@ -101,3 +101,4 @@ class SCSN(PackagedDataset): """ url = 'https://www.dropbox.com/s/u16lkjxliw8fouj/scsn.tar?dl=1' + diff --git a/src/yews/models/__init__.py b/src/yews/models/__init__.py index 05b85e1..67428c1 100644 --- a/src/yews/models/__init__.py +++ b/src/yews/models/__init__.py @@ -1,2 +1,4 @@ from .cpic import * +from .polarity import * +from .focal_mechanism import * diff --git a/src/yews/models/cpic.py b/src/yews/models/cpic.py index 3d50918..b83be85 100644 --- a/src/yews/models/cpic.py +++ b/src/yews/models/cpic.py @@ -1,13 +1,14 @@ -# TO-DO: need to add model_zoo utility and pretrained models. import torch.nn as nn from .utils import load_state_dict_from_url -__all__ = ['CpicV1', 'CpicV2', 'cpic_v1', 'cpic_v2'] + +__all__ = ['CpicV1', 'cpic_v1', 'CpicV2', 'cpic_v2', 'CpicV3', 'cpic_v3'] model_urls = { 'cpic_v1': 'https://www.dropbox.com/s/ckb4glf35agi9xa/cpic_v1_wenchuan-bdd92da2.pth?dl=1', - 'cpic_v2': 'https://www.dropbox.com/s/kyiuprnn8014fs5/cpic_v2_wenchuan-ee92060a.pth?dl=1' + 'cpic_v2': 'https://www.dropbox.com/s/kyiuprnn8014fs5/cpic_v2_wenchuan-ee92060a.pth?dl=1', + 'cpic_v3': '' } class CpicV1(nn.Module): @@ -122,6 +123,23 @@ def forward(self, x): out = self.fc(out) return out + +def cpic_v1(pretrained=False, progress=True, **kwargs): + r"""Original CPIC model architecture from the + `"Deep learning for ..." `_ paper. The + pretrained model is trained on 60,000 Wenchuan aftershock dataset + demonstrated in the paper. + + Args: + pretrained (bool): If True, returns a model pre-trained on Wenchuan) + progress (bool): If True, displays a progress bar of the download to stderr + """ + model = CpicV1(**kwargs) + if pretrained: + state_dict = load_state_dict_from_url(model_urls['cpic_v1'], + progress=progress) + model.load_state_dict(state_dict) + return model class CpicV2(nn.Module): def __init__(self): @@ -217,8 +235,8 @@ def forward(self, x): return out -def cpic_v1(pretrained=False, progress=True, **kwargs): - r"""Original CPIC model architecture from the +def cpic_v2(pretrained=False, progress=True, **kwargs): + r"""Simplified CPIC model architecture from the `"Deep learning for ..." `_ paper. The pretrained model is trained on 60,000 Wenchuan aftershock dataset demonstrated in the paper. @@ -227,26 +245,92 @@ def cpic_v1(pretrained=False, progress=True, **kwargs): pretrained (bool): If True, returns a model pre-trained on Wenchuan) progress (bool): If True, displays a progress bar of the download to stderr """ - model = CpicV1(**kwargs) + model = CpicV2(**kwargs) if pretrained: - state_dict = load_state_dict_from_url(model_urls['cpic_v1'], + state_dict = load_state_dict_from_url(model_urls['cpic_v2'], progress=progress) model.load_state_dict(state_dict) return model -def cpic_v2(pretrained=False, progress=True, **kwargs): - r"""Simplified CPIC model architecture from the - `"Deep learning for ..." `_ paper. The - pretrained model is trained on 60,000 Wenchuan aftershock dataset - demonstrated in the paper. +class CpicV3(nn.Module): + + #https://github.com/pytorch/vision/blob/master/torchvision/models/vgg.py + + def __init__(self): + super(CpicV3, self).__init__() + self.features = nn.Sequential( - Args: - pretrained (bool): If True, returns a model pre-trained on Wenchuan) - progress (bool): If True, displays a progress bar of the download to stderr - """ - model = CpicV2(**kwargs) + # 2000 -> 1000 + nn.Conv1d(3, 16, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(16), + nn.ReLU(), + nn.MaxPool1d(2), + + # 1000 -> 500 + nn.Conv1d(16, 32, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(32), + nn.ReLU(), + nn.MaxPool1d(2), + + # 500 -> 250 + nn.Conv1d(32, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + # 250 -> 125 + nn.Conv1d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + # 125 -> 62 + nn.Conv1d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + # 62 -> 31 + nn.Conv1d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + # 31 -> 15 + nn.Conv1d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + # 15 -> 7 + nn.Conv1d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + ) + + self.classifier = nn.Sequential( + nn.Linear(64 * 7, 3), + ) + + def forward(self, x): + x = self.features(x) + x = x.view(x.size(0), -1) + x = self.classifier(x) + return x + +def cpic_v3(pretrained=False, progress=True, **kwargs): + model = CpicV3(**kwargs) if pretrained: - state_dict = load_state_dict_from_url(model_urls['cpic_v2'], + state_dict = load_state_dict_from_url(model_urls['cpic_v3'], progress=progress) model.load_state_dict(state_dict) return model + +# if __name__ == '__main__': +# model = cpic_v3(pretrained=False) + +# x = torch.ones([1, 3, 2000]) +# out = model(x) +# print(out.size()) diff --git a/src/yews/models/focal_mechanism.py b/src/yews/models/focal_mechanism.py new file mode 100644 index 0000000..20ad64f --- /dev/null +++ b/src/yews/models/focal_mechanism.py @@ -0,0 +1,331 @@ +import torch.nn as nn + +from .utils import load_state_dict_from_url + +# import torch +# try: +# from torch.hub import load_state_dict_from_url +# except ImportError: +# from torch.utils.model_zoo import load_url as load_state_dict_from_url + +__all__ = ['FmV1', 'fm_v1', 'FmV2', 'fm_v2'] + +model_urls = { + 'fm_v1': 'https://www.dropbox.com/s/ckb4glf35agi9xa/fm_v1_wenchuan-bdd92da2.pth?dl=1', + 'fm_v2': 'https://www.dropbox.com/s/ckb4glf35agi9xa/fm_v1_wenchuan-bdd92da2.pth?dl=1', +} + +class FmV1(nn.Module): + + def __init__(self): + super().__init__() + # n*3*71*9000 + # nn.Cov2d(3,16,kernel_size=(3,7),stride=1,padding=....) + # (3,7) 3>71 7>18000 in the end use (3,3). + + # 71,9000 -> 71,4507 + self.layer1 = nn.Sequential( + nn.Conv2d(3, 16, kernel_size=(3,17), stride=1, padding=(2,16), bias=False), + nn.BatchNorm2d(16), + nn.ReLU(), + # nn.Sigmoid(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)) + ) + + # 71,4507 -> 71,2260 + self.layer2 = nn.Sequential( + nn.Conv2d(16, 32, kernel_size=(3,15), stride=1, padding=(2,14), bias=False), + nn.BatchNorm2d(32), + nn.ReLU(), + # nn.Sigmoid(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)) + ) + + # 71,2260 -> 71,1135 + self.layer3 = nn.Sequential( + nn.Conv2d(32, 64, kernel_size=(3,13), stride=1, padding=(2,12), bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)) + ) + + # 71,1135 -> 71,572 + self.layer4 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=(3,11), stride=1, padding=(2,10), bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)) + ) + + # 71,572 -> 71,289 + self.layer5 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=(3,9), stride=1, padding=(2,8), bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)) + ) + + # 71,289 -> 71,143 + self.layer6 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=(3,7), stride=1, padding=2, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)) + ) + + # 71,143 -> 71,71 + self.layer7 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=(3,5), stride=1, padding=2, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)) + ) + + # 71,71 -> 35,35 + self.layer8 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(2) + ) + + # 35,35 -> 17,17 + self.layer9 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(2) + ) + + # 17,17 -> 8,8 + self.layer10 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(2) + ) + + + # 8,8 -> 4,4 + self.layer11 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(2) + ) + + # 4,4 -> 2,2 + self.layer12 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(2) + ) + + # 2,2 -> 1,1 + self.layer13 = nn.Sequential( + nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(2) + ) + + self.fc = nn.Linear(64 * 1 * 1, 3) + + def forward(self, x): + out = self.layer1(x) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + out = self.layer5(out) + out = self.layer6(out) + out = self.layer7(out) + out = self.layer8(out) + out = self.layer9(out) + out = self.layer10(out) + out = self.layer11(out) + out = self.layer12(out) + out = self.layer13(out) + out = out.view(out.size(0), -1) + out = self.fc(out) + + return out + +def fm_v1(pretrained=False, progress=True, **kwargs): + r"""Original CPIC model architecture from the + `"Deep learning for ..." `_ paper. The + pretrained model is trained on 60,000 Wenchuan aftershock dataset + demonstrated in the paper. + + Args: + pretrained (bool): If True, returns a model pre-trained on Wenchuan) + progress (bool): If True, displays a progress bar of the download to stderr + """ + model = FmV1(**kwargs) + if pretrained: + state_dict = load_state_dict_from_url(model_urls['fm_v1'], + progress=progress) + model.load_state_dict(state_dict) + return model + + +class FmV2(nn.Module): + + #https://github.com/pytorch/vision/blob/master/torchvision/models/vgg.py + + def __init__(self): + super(FmV2, self).__init__() + self.features = nn.Sequential( + + # 71,9000 -> 71,4507 + nn.Conv2d(3, 16, kernel_size=(3,17), stride=1, padding=(2,16), bias=False), + nn.BatchNorm2d(16), + nn.ReLU(), +# nn.Conv2d(16, 16, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(16), +# nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)), + + # 71,4507 -> 71,2260 + nn.Conv2d(16, 32, kernel_size=(3,15), stride=1, padding=(2,14), bias=False), + nn.BatchNorm2d(32), + nn.ReLU(), +# nn.Conv2d(32, 32, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(32), +# nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)), + + # 71,2260 -> 71,1135 + nn.Conv2d(32, 64, kernel_size=(3,13), stride=1, padding=(2,12), bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(64), +# nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)), + + # 71,1135 -> 71,572 + nn.Conv2d(64, 64, kernel_size=(3,11), stride=1, padding=(2,10), bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(64), +# nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)), + + # 71,572 -> 71,289 + nn.Conv2d(64, 64, kernel_size=(3,9), stride=1, padding=(2,8), bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(64), +# nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)), + + # 71,289 -> 71,143 + nn.Conv2d(64, 64, kernel_size=(3,7), stride=1, padding=2, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(64), +# nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)), + + # 71,143 -> 71,71 + nn.Conv2d(64, 64, kernel_size=(3,5), stride=1, padding=2, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(64), +# nn.ReLU(), + nn.MaxPool2d(kernel_size=3, stride=(1, 2)), + + # 71,71 -> 35,35 + nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(64), +# nn.ReLU(), + nn.MaxPool2d(2), + + # 35,35 -> 17,17 + nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(64), +# nn.ReLU(), + nn.MaxPool2d(2), + + # 17,17 -> 8,8 + nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.ReLU(), +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1), +# nn.BatchNorm2d(64), +# nn.ReLU(), + nn.MaxPool2d(2), + +# # 8,8 -> 4,4 + +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), +# nn.BatchNorm2d(64), +# nn.ReLU(), +# nn.MaxPool2d(2), +# # nn.Dropout(0.1), + +# # 4,4 -> 2,2 + +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), +# nn.BatchNorm2d(64), +# nn.ReLU(), +# nn.MaxPool2d(2), +# # nn.Dropout(0.1), + +# # 2,2 -> 1,1 + +# nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), +# nn.BatchNorm2d(64), +# nn.ReLU(), +# nn.MaxPool2d(2), +# # nn.Dropout(0.1), + + + ) + +# self.avgpool = nn.AdaptiveAvgPool2d((4, 4)) + + self.classifier = nn.Sequential( + nn.Linear(64 * 8 * 8, 3), +# nn.Dropout(0.3), +# nn.Linear(64 * 4 * 4, 32), +# nn.ReLU(), +# nn.Dropout(0.3), +# nn.Linear(32, 32), +# nn.ReLU(), +# nn.Linear(32, 3) + ) + + def forward(self, x): + x = self.features(x) +# x = self.avgpool(x) + x = x.view(x.size(0), -1) + x = self.classifier(x) + return x + +def fm_v2(pretrained=False, progress=True, **kwargs): + + model = FmV2(**kwargs) + if pretrained: + state_dict = load_state_dict_from_url(model_urls['fm_v2'], + progress=progress) + model.load_state_dict(state_dict) + return model + +# if __name__ == '__main__': +# model = fm_v1(pretrained=False) + +# x = torch.ones([1, 3, 71, 9000]) +# out = model(x) +# print(out.size()) \ No newline at end of file diff --git a/src/yews/models/polarity.py b/src/yews/models/polarity.py new file mode 100644 index 0000000..a5d95b2 --- /dev/null +++ b/src/yews/models/polarity.py @@ -0,0 +1,220 @@ +import torch +import torch.nn as nn + +from .utils import load_state_dict_from_url + +# try: +# from torch.hub import load_state_dict_from_url +# except ImportError: +# from torch.utils.model_zoo import load_url as load_state_dict_from_url + +__all__ = ['PolarityCNN', 'polarity_cnn', 'PolarityLSTM', 'polarity_lstm', 'PolarityCNNLSTM', 'polarity_cnn_lstm'] + +model_urls = { + 'polarity_cnn': 'https://www.dr', +} + +class PolarityCNN(nn.Module): + + #https://github.com/pytorch/vision/blob/master/torchvision/models/vgg.py + + def __init__(self): + super().__init__() + self.features = nn.Sequential( + + # 300 -> 150 + + nn.Conv1d(1, 16, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(16), + nn.ReLU(), + nn.MaxPool1d(2), + + + # 150 -> 75 + + nn.Conv1d(16, 32, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(32), + nn.ReLU(), + nn.MaxPool1d(2), + + + # 75 -> 37 + + nn.Conv1d(32, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + + # 37 -> 18 + + nn.Conv1d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + + # 18 -> 9 + + nn.Conv1d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + + # 9 -> 4 + + nn.Conv1d(64, 64, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(64), + nn.ReLU(), + nn.MaxPool1d(2), + + ) + + self.classifier = nn.Sequential( + nn.Linear(64 * 4, 2), + ) + + def forward(self, x): + + x = self.features(x) + x = x.view(x.size(0), -1) + x = self.classifier(x) + + return x + +def polarity_cnn(pretrained=False, progress=True, **kwargs): + model = PolarityCNN(**kwargs) + if pretrained: + state_dict = load_state_dict_from_url(model_urls['polarity_cnn'],progress=progress) + model.load_state_dict(state_dict) + return model + +# note: please use only 1 gpu to run LSTM, https://github.com/pytorch/pytorch/issues/21108 +class PolarityLSTM(nn.Module): + r"""a LSTM neural network + @author: Chujie Chen + @Email: chen8chu8jie6@gmail.com + @date: 04/24/2020 + """ + def __init__(self, **kwargs): + super().__init__() + input_size = 1 + self.hidden_size = kwargs["hidden_size"] + self.bidirectional = kwargs["bidirectional"] + self.contains_unkown = kwargs["contains_unkown"] + self.start = kwargs['start'] + self.end = kwargs['end'] + self.num_layers = kwargs['num_layers'] + self.lstm = nn.LSTM(input_size, self.hidden_size, self.num_layers, + bidirectional=self.bidirectional) + self.fc = nn.Linear(self.hidden_size * (2 if self.bidirectional else 1), 3 if self.contains_unkown else 2) + + def forward(self, x): + x = x.narrow(2,self.start, self.end-self.start) + x = x.permute(2, 0, 1) # seq_len, batch, input_size + output, (h_n, c_n) = self.lstm(x, None) + output = output[-1:, :, :] + output = output.view(output.size(1), -1) + out = self.fc(output) + return out + +def polarity_lstm(**kwargs): + r"""A LSTM based model. + Kwargs (form like a dict and should be pass like **kwargs): + hidden_size (default 64): recommended to be similar as the length of trimmed subsequence + num_layers (default 2): layers are stacked and results are from the final layer + start (default 250): start index of the subsequence + end (default 350): end index of the subsequence + bidirectional (default False): run lstm from left to right and from right to left + contains_unkown (default False): True if targets have 0,1,2 + """ + default_kwargs = {"hidden_size":64, + "num_layers":2, + "start": 250, + "end": 350, + "bidirectional":False, + "contains_unkown":False} + for k,v in kwargs.items(): + if k in default_kwargs: + default_kwargs[k] = v + print("#### model parameters ####\n") + print(default_kwargs) + print("\n##########################") + if(default_kwargs['end'] < default_kwargs['start']): + raise ValueError('<-- end cannot be smaller than start -->') + model = PolarityLSTM(**default_kwargs) + return model + +class PolarityCNNLSTM(nn.Module): + + def __init__(self, **kwargs): + super().__init__() + self.features = nn.Sequential( + + # 300 -> 150 + nn.Conv1d(1, 16, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(16), + nn.ReLU(), + nn.MaxPool1d(2), + + # 150 -> 75 + nn.Conv1d(16, 32, kernel_size=3, stride=1, padding=1, bias=False), + nn.BatchNorm1d(32), + nn.ReLU(), + nn.MaxPool1d(2) + ) + + input_size = 32 + self.hidden_size = kwargs["hidden_size"] + self.bidirectional = kwargs["bidirectional"] + self.contains_unkown = kwargs["contains_unkown"] + self.start = kwargs['start'] + self.end = kwargs['end'] + self.num_layers = kwargs['num_layers'] + self.lstm = nn.LSTM(input_size, self.hidden_size, self.num_layers, bidirectional=self.bidirectional) + self.fc = nn.Linear(self.hidden_size * (2 if self.bidirectional else 1), 3 if self.contains_unkown else 2) + + def forward(self, x): + out = self.features(x) + + out = out.narrow(2,self.start, self.end-self.start) + out = out.permute(2, 0, 1) # seq_len, batch, input_size + output, (h_n, c_n) = self.lstm(out, None) + output = output[-1:, :, :] + output = output.view(output.size(1), -1) + out = self.fc(output) + return out + +def polarity_cnn_lstm(**kwargs): + r"""A LSTM based model. + Kwargs (form like a dict and should be pass like **kwargs): + hidden_size (default 64): recommended to be similar as the length of trimmed subsequence + num_layers (default 2): layers are stacked and results are from the final layer + start (default 0): start index of the subsequence + end (default 75): end index of the subsequence + bidirectional (default False): run lstm from left to right and from right to left + contains_unkown (default False): True if targets have 0,1,2 + """ + default_kwargs = {"hidden_size":64, + "num_layers":2, + "start": 0, + "end": 75, + "bidirectional":False, + "contains_unkown":False} + for k,v in kwargs.items(): + if k in default_kwargs: + default_kwargs[k] = v + print("#### model parameters ####\n") + print(default_kwargs) + print("\n##########################") + if(default_kwargs['end'] < default_kwargs['start']): + raise ValueError('<-- end cannot be smaller than start -->') + model = PolarityCNNLSTM(**default_kwargs) + return model + +# if __name__ == '__main__': +# model = polarity_cnn(pretrained=False) +# x = torch.ones([1, 1, 600]) +# out = model(x) +# print(out.size()) diff --git a/src/yews/train/train.py.bak b/src/yews/train/train.py.bak deleted file mode 100644 index dff31a3..0000000 --- a/src/yews/train/train.py.bak +++ /dev/null @@ -1,254 +0,0 @@ -from pathlib import Path -import warnings - -import numpy as np -import torch -from torch.utils.data import DataLoader - -from . import functional as F - -__all__ = [ - "Trainer", -] - -class Trainer(object): - - def __init__(self, dataset, train_sampler, val_sampler, tmp_dir='./tmp'): - - # device - self.device = F.get_torch_device() - if self.device == 'cpu': - warnings.warn("The training process is running on CPU now. " - "Consider training on a machine with GPUs " - "to speed up the process.") - - # architecture - self.arch = None - - # model - self.model = None - - # data - self.dataset = dataset - self.train_sampler = train_sampler - self.val_sampler = val_sampler - - # optimizer - self.criterion = None - self.optimizer = None - self.scheduler = None - - # training process - self.start_epoch = 0 - self.end_epoch = None - - # results - self.best_acc = None - self.best_model = None - self.train_loss = None - self.train_acc = None - self.val_loss = None - self.val_acc = None - - # tmp files - self.tmp_name = None - self.tmp_dir = Path(tmp_dir) - - self.reset() - -# ----------------------------------------------------------------------------- -# -# Utility Methods -# -# ----------------------------------------------------------------------------- - - def get_device(self): - return self.device.type - - def reset(self): - self._init_model() - #self.model = nn.DataParallel(self.model.to(self.device)) - self.model = F.model_on_device(self.model, self.device) - - self._init_criterion() - self._init_optimizer() - self._init_scheduler() - - self._reset_results() - - self._reset_temp_name() - - def _reset_results(self): - self.best_acc = 0. - self.best_model = None - self.train_loss = [] - self.train_acc = [] - self.val_loss = [] - self.val_acc = [] - - def _reset_temp_name(self): - #ts = time.time() - #self.tmp_name = f"{self.arch}_{np.floor(ts):.0f}" - self.tmp_name = F.generate_tmp_name(self.arch) - - def resume_checkpoint(self, filename): - - checkpoint_dict = F.load_checkpoint(filename) - - if checkpoint_dict: - self._load_checkpoint(checkpoint_dict) - else: - warnings.warn(f"Loading checkpoint {filename} fails. " - f"Trainer state has not been changed.") - - def preserve_checkpoint(self, epoch, **kwargs): - - checkpoint_dict = self._dump_checkpoint(epoch) - - filename = self.tmp_dir / self.tmp_name / f'checkpoint_epoch{epoch}.pth.tar' - F.save_checkpoint(checkpoint_dict, filename=filename, - **kwargs) - - def cleanup(self): - F.rm_content(self.tmp_dir) - - def clean(self): - F.rm_dir_content(self.tmp_dir / self.tmp_name) - - def results(self, epochs=0, save=False): - results = { - #'model': self.model.module.to(torch.device('cpu')).state_dict(), - 'model': F.model_off_device(self.model), - 'train_loss': self.train_loss, - 'train_acc': self.train_acc, - 'val_loss': self.val_loss, - 'val_acc': self.val_acc - } - - if save: - filename = self.tmp_dir / self.tmp_name / f'results_{self.arch}_epoch{epochs}.pth.tar' - torch.save(results, filename) - - return results - - -# ----------------------------------------------------------------------------- -# -# Primary Usage Methods -# -# ----------------------------------------------------------------------------- - - def validate(self, print_freq=None, **kwargs): - - val_loader = DataLoader(self.dataset, sampler=self.val_sampler, **kwargs) - return F.validate(self.model, val_loader, self.criterion, print_freq) - - def train(self, epochs=100, - val_batch_size=1000, val_num_workers=4, - train_batch_size=100, train_num_workers=8, - resume=None, print_freq=10, save_tmp=True): - - start_epoch = 0 - end_epoch = epochs - - if resume: - self.resume_checkpoint(resume) - - if save_tmp: - (self.tmp_dir / self.tmp_name).mkdir(parents=True, exist_ok=False) - - # build dataloader - train_loader = DataLoader(dataset=self.dataset, - sampler=self.train_sampler, - batch_size=train_batch_size, - num_workers=train_num_workers) - val_loader = DataLoader(dataset=self.dataset, - sampler=self.val_sampler, - batch_size=val_batch_size, - num_workers=val_num_workers) - - # record results for initial model - # -validation set - acc, loss = F.validate(self.model, val_loader, self.criterion, - print_freq=None) - self.val_acc.append(acc) - self.val_loss.append(loss) - - for epoch in range(start_epoch, end_epoch): - # update learning rate - self._update_scheduler() - - # train model for one epoch - acc, loss = F.train(self.model, train_loader, - self.criterion, self.optimizer, - epoch, print_freq=print_freq) - self.train_acc.append(acc) - self.train_loss.append(loss) - - acc, loss = F.validate(self.model, val_loader, self.criterion, - print_freq=None) - self.val_acc.append(acc) - self.val_loss.append(loss) - - # preserve current checkpoint and best checkpoint - is_best = self.val_acc[-1] > self.best_acc - self.best_acc = max(self.val_acc[-1], self.best_acc) - if save_tmp: - self.preserve_checkpoint(epoch, is_best=is_best) - - -# ----------------------------------------------------------------------------- -# -# Optional Override Methods (Default Behavior) -# -# ----------------------------------------------------------------------------- - - def _dump_checkpoint(self, epoch): - - print("=> Pulling checkpoint from Trainer") - checkpoint = { - 'epcoh': epoch, - 'arch': self.arch, - 'best_acc': self.best_acc, - 'model': self.model.state_dict(), - 'optimizer': self.optimizer.state_dict(), - 'scheduler': self.scheduler.state_dict(), - } - - return checkpoint - - def _load_checkpoint(self, checkpoint): - - if self.arch != checkpoint['arch']: - warnings.warn(f"The architecture in checkpoint does not match " - f"model: {checkpoint['arch']} " - f"vs. {self.arch}.") - self.start_epoch = checkpoint['epoch'] + 1 - self.best_acc = checkpoint['best_acc'] - self.model.load_state_dict(checkpoint['model']) - self.optimizer.load_state_dict(checkpoint['optimizer']) - self.scheduler.load_state_dict(checkpoint['scheduler']) - print("* Trainer has been updated by the checkpoint loaded.") - - -# ----------------------------------------------------------------------------- -# -# Mandatory Override Methods -# -# ----------------------------------------------------------------------------- - - def _init_model(self): - raise(NotImplementedError) - - def _init_criterion(self): - raise(NotImplementedError) - - def _init_optimizer(self): - raise(NotImplementedError) - - def _init_scheduler(self): - raise(NotImplementedError) - - def _update_scheduler(self): - raise(NotImplementedError) - diff --git a/src/yews/transforms/functional.py b/src/yews/transforms/functional.py index 011725c..07fe136 100644 --- a/src/yews/transforms/functional.py +++ b/src/yews/transforms/functional.py @@ -18,5 +18,4 @@ def _to_tensor(wav): if wav.ndim == 1: wav = wav[None, :] - return torch.from_numpy(wav).float() diff --git a/src/yews/transforms/transforms.py b/src/yews/transforms/transforms.py index 93cdc60..15af18a 100644 --- a/src/yews/transforms/transforms.py +++ b/src/yews/transforms/transforms.py @@ -1,5 +1,6 @@ from . import functional as F from .base import BaseTransform +from scipy import signal try: from scipy.special import expit @@ -15,6 +16,9 @@ "ZeroMean", "CutWaveform", "SoftClip", + "RemoveTrend", + "Taper", + "BandpassFilter", ] class ToTensor(BaseTransform): @@ -100,3 +104,35 @@ def __init__(self, samplestart, sampleend): def __call__(self, wav): return wav[:, self.start:self.end] + +class RemoveTrend(BaseTransform): + """Remove trend from each waveforms. + + """ + def __call__(self, wav): + wav = signal.detrend(wav,axis=-1) + return wav + +class Taper(BaseTransform): + """Add taper in both ends of each waveforms. + + """ + def __call__(self, wav, half_taper = 0.05): + + [x,y] = wav.shape + tukey_win = signal.tukey(y, alpha=2*half_taper, sym=True) + wav = wav * tukey_win + return wav + +class BandpassFilter(BaseTransform): + """Apply Bandpass filter to each waveforms. + """ + def __call__(self, wav, delta=0.01, order = 4, lowfreq = 2, highfreq = 16 ): + + nyq = 0.5 * (1 / delta) + low = lowfreq / nyq + high = highfreq / nyq + b, a = signal.butter(order, [low, high], btype='bandpass') + wav = signal.filtfilt(b, a, wav, axis=-1, padtype=None, padlen=None, irlen=None) + + return wav