mirror of
https://github.com/jung-geun/PSO.git
synced 2025-12-19 20:44:39 +09:00
단순 수정
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
"name": "Miniconda (Python 3)",
|
||||
// Configure tool-specific properties.
|
||||
"hostRequirements": {
|
||||
"cpus": 16,
|
||||
"cpus": 8,
|
||||
"memory": "64gb",
|
||||
"storage": "128gb"
|
||||
},
|
||||
|
||||
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "ms-python.black-formatter"
|
||||
},
|
||||
"python.formatting.provider": "none",
|
||||
"sonarlint.connectedMode.project": {
|
||||
"connectionId": "https-sonar-pieroot-xyz",
|
||||
"projectKey": "pieroot_pso_6a2f36a9-2688-4900-a4a5-5be85f36f75a"
|
||||
},
|
||||
"yaml.schemas": {
|
||||
"https://gitlab.com/gitlab-org/gitlab/-/raw/master/app/assets/javascripts/editor/schema/ci.json": "file:///home/pieroot/jupyter/PSO/.gitlab/ci/sonarqube-check.gitlab-ci.yml"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,111 +0,0 @@
|
||||
1. Title of Database: MAGIC gamma telescope data 2004
|
||||
|
||||
2. Sources:
|
||||
|
||||
(a) Original owner of the database:
|
||||
|
||||
R. K. Bock
|
||||
Major Atmospheric Gamma Imaging Cherenkov Telescope project (MAGIC)
|
||||
http://wwwmagic.mppmu.mpg.de
|
||||
rkb@mail.cern.ch
|
||||
|
||||
(b) Donor:
|
||||
|
||||
P. Savicky
|
||||
Institute of Computer Science, AS of CR
|
||||
Czech Republic
|
||||
savicky@cs.cas.cz
|
||||
|
||||
(c) Date received: May 2007
|
||||
|
||||
3. Past Usage:
|
||||
|
||||
(a) Bock, R.K., Chilingarian, A., Gaug, M., Hakl, F., Hengstebeck, T.,
|
||||
Jirina, M., Klaschka, J., Kotrc, E., Savicky, P., Towers, S.,
|
||||
Vaicilius, A., Wittek W. (2004).
|
||||
Methods for multidimensional event classification: a case study
|
||||
using images from a Cherenkov gamma-ray telescope.
|
||||
Nucl.Instr.Meth. A, 516, pp. 511-528.
|
||||
|
||||
(b) P. Savicky, E. Kotrc.
|
||||
Experimental Study of Leaf Confidences for Random Forest.
|
||||
Proceedings of COMPSTAT 2004, In: Computational Statistics.
|
||||
(Ed.: Antoch J.) - Heidelberg, Physica Verlag 2004, pp. 1767-1774.
|
||||
|
||||
(c) J. Dvorak, P. Savicky.
|
||||
Softening Splits in Decision Trees Using Simulated Annealing.
|
||||
Proceedings of ICANNGA 2007, Warsaw, (Ed.: Beliczynski et. al),
|
||||
Part I, LNCS 4431, pp. 721-729.
|
||||
|
||||
4. Relevant Information:
|
||||
|
||||
The data are MC generated (see below) to simulate registration of high energy
|
||||
gamma particles in a ground-based atmospheric Cherenkov gamma telescope using the
|
||||
imaging technique. Cherenkov gamma telescope observes high energy gamma rays,
|
||||
taking advantage of the radiation emitted by charged particles produced
|
||||
inside the electromagnetic showers initiated by the gammas, and developing in the
|
||||
atmosphere. This Cherenkov radiation (of visible to UV wavelengths) leaks
|
||||
through the atmosphere and gets recorded in the detector, allowing reconstruction
|
||||
of the shower parameters. The available information consists of pulses left by
|
||||
the incoming Cherenkov photons on the photomultiplier tubes, arranged in a
|
||||
plane, the camera. Depending on the energy of the primary gamma, a total of
|
||||
few hundreds to some 10000 Cherenkov photons get collected, in patterns
|
||||
(called the shower image), allowing to discriminate statistically those
|
||||
caused by primary gammas (signal) from the images of hadronic showers
|
||||
initiated by cosmic rays in the upper atmosphere (background).
|
||||
|
||||
Typically, the image of a shower after some pre-processing is an elongated
|
||||
cluster. Its long axis is oriented towards the camera center if the shower axis
|
||||
is parallel to the telescope's optical axis, i.e. if the telescope axis is
|
||||
directed towards a point source. A principal component analysis is performed
|
||||
in the camera plane, which results in a correlation axis and defines an ellipse.
|
||||
If the depositions were distributed as a bivariate Gaussian, this would be
|
||||
an equidensity ellipse. The characteristic parameters of this ellipse
|
||||
(often called Hillas parameters) are among the image parameters that can be
|
||||
used for discrimination. The energy depositions are typically asymmetric
|
||||
along the major axis, and this asymmetry can also be used in discrimination.
|
||||
There are, in addition, further discriminating characteristics, like the
|
||||
extent of the cluster in the image plane, or the total sum of depositions.
|
||||
|
||||
The data set was generated by a Monte Carlo program, Corsika, described in
|
||||
D. Heck et al., CORSIKA, A Monte Carlo code to simulate extensive air showers,
|
||||
Forschungszentrum Karlsruhe FZKA 6019 (1998).
|
||||
The program was run with parameters allowing to observe events with energies down
|
||||
to below 50 GeV.
|
||||
|
||||
5. Number of Instances: 19020
|
||||
|
||||
6. Number of Attributes: 11 (including the class)
|
||||
|
||||
7. Attribute information:
|
||||
|
||||
1. fLength: continuous # major axis of ellipse [mm]
|
||||
2. fWidth: continuous # minor axis of ellipse [mm]
|
||||
3. fSize: continuous # 10-log of sum of content of all pixels [in #phot]
|
||||
4. fConc: continuous # ratio of sum of two highest pixels over fSize [ratio]
|
||||
5. fConc1: continuous # ratio of highest pixel over fSize [ratio]
|
||||
6. fAsym: continuous # distance from highest pixel to center, projected onto major axis [mm]
|
||||
7. fM3Long: continuous # 3rd root of third moment along major axis [mm]
|
||||
8. fM3Trans: continuous # 3rd root of third moment along minor axis [mm]
|
||||
9. fAlpha: continuous # angle of major axis with vector to origin [deg]
|
||||
10. fDist: continuous # distance from origin to center of ellipse [mm]
|
||||
11. class: g,h # gamma (signal), hadron (background)
|
||||
|
||||
8. Missing Attribute Values: None
|
||||
|
||||
9. Class Distribution:
|
||||
|
||||
g = gamma (signal): 12332
|
||||
h = hadron (background): 6688
|
||||
|
||||
For technical reasons, the number of h events is underestimated.
|
||||
In the real data, the h class represents the majority of the events.
|
||||
|
||||
The simple classification accuracy is not meaningful for this data, since
|
||||
classifying a background event as signal is worse than classifying a signal
|
||||
event as background. For comparison of different classifiers an ROC curve
|
||||
has to be used. The relevant points on this curve are those, where the
|
||||
probability of accepting a background event as signal is below one of the
|
||||
following thresholds: 0.01, 0.02, 0.05, 0.1, 0.2 depending on the required
|
||||
quality of the sample of the accepted events for different experiments.
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
15.26 14.84 0.871 5.763 3.312 2.221 5.22 1
|
||||
14.88 14.57 0.8811 5.554 3.333 1.018 4.956 1
|
||||
14.29 14.09 0.905 5.291 3.337 2.699 4.825 1
|
||||
13.84 13.94 0.8955 5.324 3.379 2.259 4.805 1
|
||||
16.14 14.99 0.9034 5.658 3.562 1.355 5.175 1
|
||||
14.38 14.21 0.8951 5.386 3.312 2.462 4.956 1
|
||||
14.69 14.49 0.8799 5.563 3.259 3.586 5.219 1
|
||||
14.11 14.1 0.8911 5.42 3.302 2.7 5 1
|
||||
16.63 15.46 0.8747 6.053 3.465 2.04 5.877 1
|
||||
16.44 15.25 0.888 5.884 3.505 1.969 5.533 1
|
||||
15.26 14.85 0.8696 5.714 3.242 4.543 5.314 1
|
||||
14.03 14.16 0.8796 5.438 3.201 1.717 5.001 1
|
||||
13.89 14.02 0.888 5.439 3.199 3.986 4.738 1
|
||||
13.78 14.06 0.8759 5.479 3.156 3.136 4.872 1
|
||||
13.74 14.05 0.8744 5.482 3.114 2.932 4.825 1
|
||||
14.59 14.28 0.8993 5.351 3.333 4.185 4.781 1
|
||||
13.99 13.83 0.9183 5.119 3.383 5.234 4.781 1
|
||||
15.69 14.75 0.9058 5.527 3.514 1.599 5.046 1
|
||||
14.7 14.21 0.9153 5.205 3.466 1.767 4.649 1
|
||||
12.72 13.57 0.8686 5.226 3.049 4.102 4.914 1
|
||||
14.16 14.4 0.8584 5.658 3.129 3.072 5.176 1
|
||||
14.11 14.26 0.8722 5.52 3.168 2.688 5.219 1
|
||||
15.88 14.9 0.8988 5.618 3.507 0.7651 5.091 1
|
||||
12.08 13.23 0.8664 5.099 2.936 1.415 4.961 1
|
||||
15.01 14.76 0.8657 5.789 3.245 1.791 5.001 1
|
||||
16.19 15.16 0.8849 5.833 3.421 0.903 5.307 1
|
||||
13.02 13.76 0.8641 5.395 3.026 3.373 4.825 1
|
||||
12.74 13.67 0.8564 5.395 2.956 2.504 4.869 1
|
||||
14.11 14.18 0.882 5.541 3.221 2.754 5.038 1
|
||||
13.45 14.02 0.8604 5.516 3.065 3.531 5.097 1
|
||||
13.16 13.82 0.8662 5.454 2.975 0.8551 5.056 1
|
||||
15.49 14.94 0.8724 5.757 3.371 3.412 5.228 1
|
||||
14.09 14.41 0.8529 5.717 3.186 3.92 5.299 1
|
||||
13.94 14.17 0.8728 5.585 3.15 2.124 5.012 1
|
||||
15.05 14.68 0.8779 5.712 3.328 2.129 5.36 1
|
||||
16.12 15 0.9 5.709 3.485 2.27 5.443 1
|
||||
16.2 15.27 0.8734 5.826 3.464 2.823 5.527 1
|
||||
17.08 15.38 0.9079 5.832 3.683 2.956 5.484 1
|
||||
14.8 14.52 0.8823 5.656 3.288 3.112 5.309 1
|
||||
14.28 14.17 0.8944 5.397 3.298 6.685 5.001 1
|
||||
13.54 13.85 0.8871 5.348 3.156 2.587 5.178 1
|
||||
13.5 13.85 0.8852 5.351 3.158 2.249 5.176 1
|
||||
13.16 13.55 0.9009 5.138 3.201 2.461 4.783 1
|
||||
15.5 14.86 0.882 5.877 3.396 4.711 5.528 1
|
||||
15.11 14.54 0.8986 5.579 3.462 3.128 5.18 1
|
||||
13.8 14.04 0.8794 5.376 3.155 1.56 4.961 1
|
||||
15.36 14.76 0.8861 5.701 3.393 1.367 5.132 1
|
||||
14.99 14.56 0.8883 5.57 3.377 2.958 5.175 1
|
||||
14.79 14.52 0.8819 5.545 3.291 2.704 5.111 1
|
||||
14.86 14.67 0.8676 5.678 3.258 2.129 5.351 1
|
||||
14.43 14.4 0.8751 5.585 3.272 3.975 5.144 1
|
||||
15.78 14.91 0.8923 5.674 3.434 5.593 5.136 1
|
||||
14.49 14.61 0.8538 5.715 3.113 4.116 5.396 1
|
||||
14.33 14.28 0.8831 5.504 3.199 3.328 5.224 1
|
||||
14.52 14.6 0.8557 5.741 3.113 1.481 5.487 1
|
||||
15.03 14.77 0.8658 5.702 3.212 1.933 5.439 1
|
||||
14.46 14.35 0.8818 5.388 3.377 2.802 5.044 1
|
||||
14.92 14.43 0.9006 5.384 3.412 1.142 5.088 1
|
||||
15.38 14.77 0.8857 5.662 3.419 1.999 5.222 1
|
||||
12.11 13.47 0.8392 5.159 3.032 1.502 4.519 1
|
||||
11.42 12.86 0.8683 5.008 2.85 2.7 4.607 1
|
||||
11.23 12.63 0.884 4.902 2.879 2.269 4.703 1
|
||||
12.36 13.19 0.8923 5.076 3.042 3.22 4.605 1
|
||||
13.22 13.84 0.868 5.395 3.07 4.157 5.088 1
|
||||
12.78 13.57 0.8716 5.262 3.026 1.176 4.782 1
|
||||
12.88 13.5 0.8879 5.139 3.119 2.352 4.607 1
|
||||
14.34 14.37 0.8726 5.63 3.19 1.313 5.15 1
|
||||
14.01 14.29 0.8625 5.609 3.158 2.217 5.132 1
|
||||
14.37 14.39 0.8726 5.569 3.153 1.464 5.3 1
|
||||
12.73 13.75 0.8458 5.412 2.882 3.533 5.067 1
|
||||
17.63 15.98 0.8673 6.191 3.561 4.076 6.06 2
|
||||
16.84 15.67 0.8623 5.998 3.484 4.675 5.877 2
|
||||
17.26 15.73 0.8763 5.978 3.594 4.539 5.791 2
|
||||
19.11 16.26 0.9081 6.154 3.93 2.936 6.079 2
|
||||
16.82 15.51 0.8786 6.017 3.486 4.004 5.841 2
|
||||
16.77 15.62 0.8638 5.927 3.438 4.92 5.795 2
|
||||
17.32 15.91 0.8599 6.064 3.403 3.824 5.922 2
|
||||
20.71 17.23 0.8763 6.579 3.814 4.451 6.451 2
|
||||
18.94 16.49 0.875 6.445 3.639 5.064 6.362 2
|
||||
17.12 15.55 0.8892 5.85 3.566 2.858 5.746 2
|
||||
16.53 15.34 0.8823 5.875 3.467 5.532 5.88 2
|
||||
18.72 16.19 0.8977 6.006 3.857 5.324 5.879 2
|
||||
20.2 16.89 0.8894 6.285 3.864 5.173 6.187 2
|
||||
19.57 16.74 0.8779 6.384 3.772 1.472 6.273 2
|
||||
19.51 16.71 0.878 6.366 3.801 2.962 6.185 2
|
||||
18.27 16.09 0.887 6.173 3.651 2.443 6.197 2
|
||||
18.88 16.26 0.8969 6.084 3.764 1.649 6.109 2
|
||||
18.98 16.66 0.859 6.549 3.67 3.691 6.498 2
|
||||
21.18 17.21 0.8989 6.573 4.033 5.78 6.231 2
|
||||
20.88 17.05 0.9031 6.45 4.032 5.016 6.321 2
|
||||
20.1 16.99 0.8746 6.581 3.785 1.955 6.449 2
|
||||
18.76 16.2 0.8984 6.172 3.796 3.12 6.053 2
|
||||
18.81 16.29 0.8906 6.272 3.693 3.237 6.053 2
|
||||
18.59 16.05 0.9066 6.037 3.86 6.001 5.877 2
|
||||
18.36 16.52 0.8452 6.666 3.485 4.933 6.448 2
|
||||
16.87 15.65 0.8648 6.139 3.463 3.696 5.967 2
|
||||
19.31 16.59 0.8815 6.341 3.81 3.477 6.238 2
|
||||
18.98 16.57 0.8687 6.449 3.552 2.144 6.453 2
|
||||
18.17 16.26 0.8637 6.271 3.512 2.853 6.273 2
|
||||
18.72 16.34 0.881 6.219 3.684 2.188 6.097 2
|
||||
16.41 15.25 0.8866 5.718 3.525 4.217 5.618 2
|
||||
17.99 15.86 0.8992 5.89 3.694 2.068 5.837 2
|
||||
19.46 16.5 0.8985 6.113 3.892 4.308 6.009 2
|
||||
19.18 16.63 0.8717 6.369 3.681 3.357 6.229 2
|
||||
18.95 16.42 0.8829 6.248 3.755 3.368 6.148 2
|
||||
18.83 16.29 0.8917 6.037 3.786 2.553 5.879 2
|
||||
18.85 16.17 0.9056 6.152 3.806 2.843 6.2 2
|
||||
17.63 15.86 0.88 6.033 3.573 3.747 5.929 2
|
||||
19.94 16.92 0.8752 6.675 3.763 3.252 6.55 2
|
||||
18.55 16.22 0.8865 6.153 3.674 1.738 5.894 2
|
||||
18.45 16.12 0.8921 6.107 3.769 2.235 5.794 2
|
||||
19.38 16.72 0.8716 6.303 3.791 3.678 5.965 2
|
||||
19.13 16.31 0.9035 6.183 3.902 2.109 5.924 2
|
||||
19.14 16.61 0.8722 6.259 3.737 6.682 6.053 2
|
||||
20.97 17.25 0.8859 6.563 3.991 4.677 6.316 2
|
||||
19.06 16.45 0.8854 6.416 3.719 2.248 6.163 2
|
||||
18.96 16.2 0.9077 6.051 3.897 4.334 5.75 2
|
||||
19.15 16.45 0.889 6.245 3.815 3.084 6.185 2
|
||||
18.89 16.23 0.9008 6.227 3.769 3.639 5.966 2
|
||||
20.03 16.9 0.8811 6.493 3.857 3.063 6.32 2
|
||||
20.24 16.91 0.8897 6.315 3.962 5.901 6.188 2
|
||||
18.14 16.12 0.8772 6.059 3.563 3.619 6.011 2
|
||||
16.17 15.38 0.8588 5.762 3.387 4.286 5.703 2
|
||||
18.43 15.97 0.9077 5.98 3.771 2.984 5.905 2
|
||||
15.99 14.89 0.9064 5.363 3.582 3.336 5.144 2
|
||||
18.75 16.18 0.8999 6.111 3.869 4.188 5.992 2
|
||||
18.65 16.41 0.8698 6.285 3.594 4.391 6.102 2
|
||||
17.98 15.85 0.8993 5.979 3.687 2.257 5.919 2
|
||||
20.16 17.03 0.8735 6.513 3.773 1.91 6.185 2
|
||||
17.55 15.66 0.8991 5.791 3.69 5.366 5.661 2
|
||||
18.3 15.89 0.9108 5.979 3.755 2.837 5.962 2
|
||||
18.94 16.32 0.8942 6.144 3.825 2.908 5.949 2
|
||||
15.38 14.9 0.8706 5.884 3.268 4.462 5.795 2
|
||||
16.16 15.33 0.8644 5.845 3.395 4.266 5.795 2
|
||||
15.56 14.89 0.8823 5.776 3.408 4.972 5.847 2
|
||||
15.38 14.66 0.899 5.477 3.465 3.6 5.439 2
|
||||
17.36 15.76 0.8785 6.145 3.574 3.526 5.971 2
|
||||
15.57 15.15 0.8527 5.92 3.231 2.64 5.879 2
|
||||
15.6 15.11 0.858 5.832 3.286 2.725 5.752 2
|
||||
16.23 15.18 0.885 5.872 3.472 3.769 5.922 2
|
||||
13.07 13.92 0.848 5.472 2.994 5.304 5.395 3
|
||||
13.32 13.94 0.8613 5.541 3.073 7.035 5.44 3
|
||||
13.34 13.95 0.862 5.389 3.074 5.995 5.307 3
|
||||
12.22 13.32 0.8652 5.224 2.967 5.469 5.221 3
|
||||
11.82 13.4 0.8274 5.314 2.777 4.471 5.178 3
|
||||
11.21 13.13 0.8167 5.279 2.687 6.169 5.275 3
|
||||
11.43 13.13 0.8335 5.176 2.719 2.221 5.132 3
|
||||
12.49 13.46 0.8658 5.267 2.967 4.421 5.002 3
|
||||
12.7 13.71 0.8491 5.386 2.911 3.26 5.316 3
|
||||
10.79 12.93 0.8107 5.317 2.648 5.462 5.194 3
|
||||
11.83 13.23 0.8496 5.263 2.84 5.195 5.307 3
|
||||
12.01 13.52 0.8249 5.405 2.776 6.992 5.27 3
|
||||
12.26 13.6 0.8333 5.408 2.833 4.756 5.36 3
|
||||
11.18 13.04 0.8266 5.22 2.693 3.332 5.001 3
|
||||
11.36 13.05 0.8382 5.175 2.755 4.048 5.263 3
|
||||
11.19 13.05 0.8253 5.25 2.675 5.813 5.219 3
|
||||
11.34 12.87 0.8596 5.053 2.849 3.347 5.003 3
|
||||
12.13 13.73 0.8081 5.394 2.745 4.825 5.22 3
|
||||
11.75 13.52 0.8082 5.444 2.678 4.378 5.31 3
|
||||
11.49 13.22 0.8263 5.304 2.695 5.388 5.31 3
|
||||
12.54 13.67 0.8425 5.451 2.879 3.082 5.491 3
|
||||
12.02 13.33 0.8503 5.35 2.81 4.271 5.308 3
|
||||
12.05 13.41 0.8416 5.267 2.847 4.988 5.046 3
|
||||
12.55 13.57 0.8558 5.333 2.968 4.419 5.176 3
|
||||
11.14 12.79 0.8558 5.011 2.794 6.388 5.049 3
|
||||
12.1 13.15 0.8793 5.105 2.941 2.201 5.056 3
|
||||
12.44 13.59 0.8462 5.319 2.897 4.924 5.27 3
|
||||
12.15 13.45 0.8443 5.417 2.837 3.638 5.338 3
|
||||
11.35 13.12 0.8291 5.176 2.668 4.337 5.132 3
|
||||
11.24 13 0.8359 5.09 2.715 3.521 5.088 3
|
||||
11.02 13 0.8189 5.325 2.701 6.735 5.163 3
|
||||
11.55 13.1 0.8455 5.167 2.845 6.715 4.956 3
|
||||
11.27 12.97 0.8419 5.088 2.763 4.309 5 3
|
||||
11.4 13.08 0.8375 5.136 2.763 5.588 5.089 3
|
||||
10.83 12.96 0.8099 5.278 2.641 5.182 5.185 3
|
||||
10.8 12.57 0.859 4.981 2.821 4.773 5.063 3
|
||||
11.26 13.01 0.8355 5.186 2.71 5.335 5.092 3
|
||||
10.74 12.73 0.8329 5.145 2.642 4.702 4.963 3
|
||||
11.48 13.05 0.8473 5.18 2.758 5.876 5.002 3
|
||||
12.21 13.47 0.8453 5.357 2.893 1.661 5.178 3
|
||||
11.41 12.95 0.856 5.09 2.775 4.957 4.825 3
|
||||
12.46 13.41 0.8706 5.236 3.017 4.987 5.147 3
|
||||
12.19 13.36 0.8579 5.24 2.909 4.857 5.158 3
|
||||
11.65 13.07 0.8575 5.108 2.85 5.209 5.135 3
|
||||
12.89 13.77 0.8541 5.495 3.026 6.185 5.316 3
|
||||
11.56 13.31 0.8198 5.363 2.683 4.062 5.182 3
|
||||
11.81 13.45 0.8198 5.413 2.716 4.898 5.352 3
|
||||
10.91 12.8 0.8372 5.088 2.675 4.179 4.956 3
|
||||
11.23 12.82 0.8594 5.089 2.821 7.524 4.957 3
|
||||
10.59 12.41 0.8648 4.899 2.787 4.975 4.794 3
|
||||
10.93 12.8 0.839 5.046 2.717 5.398 5.045 3
|
||||
11.27 12.86 0.8563 5.091 2.804 3.985 5.001 3
|
||||
11.87 13.02 0.8795 5.132 2.953 3.597 5.132 3
|
||||
10.82 12.83 0.8256 5.18 2.63 4.853 5.089 3
|
||||
12.11 13.27 0.8639 5.236 2.975 4.132 5.012 3
|
||||
12.8 13.47 0.886 5.16 3.126 4.873 4.914 3
|
||||
12.79 13.53 0.8786 5.224 3.054 5.483 4.958 3
|
||||
13.37 13.78 0.8849 5.32 3.128 4.67 5.091 3
|
||||
12.62 13.67 0.8481 5.41 2.911 3.306 5.231 3
|
||||
12.76 13.38 0.8964 5.073 3.155 2.828 4.83 3
|
||||
12.38 13.44 0.8609 5.219 2.989 5.472 5.045 3
|
||||
12.67 13.32 0.8977 4.984 3.135 2.3 4.745 3
|
||||
11.18 12.72 0.868 5.009 2.81 4.051 4.828 3
|
||||
12.7 13.41 0.8874 5.183 3.091 8.456 5 3
|
||||
12.37 13.47 0.8567 5.204 2.96 3.919 5.001 3
|
||||
12.19 13.2 0.8783 5.137 2.981 3.631 4.87 3
|
||||
11.23 12.88 0.8511 5.14 2.795 4.325 5.003 3
|
||||
13.2 13.66 0.8883 5.236 3.232 8.315 5.056 3
|
||||
11.84 13.21 0.8521 5.175 2.836 3.598 5.044 3
|
||||
12.3 13.34 0.8684 5.243 2.974 5.637 5.063 3
|
||||
@@ -1,521 +0,0 @@
|
||||
import gc
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
from tensorflow import keras
|
||||
from tqdm import tqdm
|
||||
|
||||
from pso2keras import Particle
|
||||
|
||||
gpus = tf.config.experimental.list_physical_devices("GPU")
|
||||
if gpus:
|
||||
try:
|
||||
tf.config.experimental.set_memory_growth(gpus[0], True)
|
||||
except RuntimeError as e:
|
||||
print(e)
|
||||
|
||||
|
||||
class Optimizer_Target:
|
||||
"""
|
||||
particle swarm optimization
|
||||
PSO 실행을 위한 클래스
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: keras.models,
|
||||
loss="mse",
|
||||
n_particles: int = 10,
|
||||
c0=0.5,
|
||||
c1=1.5,
|
||||
w_min=0.5,
|
||||
w_max=1.5,
|
||||
negative_swarm: float = 0,
|
||||
mutation_swarm: float = 0,
|
||||
np_seed: int = None,
|
||||
tf_seed: int = None,
|
||||
target_weights=None,
|
||||
):
|
||||
"""
|
||||
particle swarm optimization
|
||||
|
||||
Args:
|
||||
model (keras.models): 모델 구조
|
||||
loss (str): 손실함수
|
||||
n_particles (int): 파티클 개수
|
||||
c0 (float): local rate - 지역 최적값 관성 수치
|
||||
c1 (float): global rate - 전역 최적값 관성 수치
|
||||
w_min (float): 최소 관성 수치
|
||||
w_max (float): 최대 관성 수치
|
||||
negative_swarm (float): 최적해와 반대로 이동할 파티클 비율 - 0 ~ 1 사이의 값
|
||||
mutation_swarm (float): 돌연변이가 일어날 확률
|
||||
np_seed (int, optional): numpy seed. Defaults to None.
|
||||
tf_seed (int, optional): tensorflow seed. Defaults to None.
|
||||
target_weights (list, optional): 목표 가중치. Defaults to None.
|
||||
"""
|
||||
if np_seed is not None:
|
||||
np.random.seed(np_seed)
|
||||
if tf_seed is not None:
|
||||
tf.random.set_seed(tf_seed)
|
||||
|
||||
self.model = model # 모델 구조
|
||||
self.loss = loss # 손실함수
|
||||
self.n_particles = n_particles # 파티클 개수
|
||||
self.particles = [None] * n_particles # 파티클 리스트
|
||||
self.c0 = c0 # local rate - 지역 최적값 관성 수치
|
||||
self.c1 = c1 # global rate - 전역 최적값 관성 수치
|
||||
self.w_min = w_min # 최소 관성 수치
|
||||
self.w_max = w_max # 최대 관성 수치
|
||||
self.negative_swarm = negative_swarm # 최적해와 반대로 이동할 파티클 비율 - 0 ~ 1 사이의 값
|
||||
self.mutation_swarm = mutation_swarm # 관성을 추가로 사용할 파티클 비율 - 0 ~ 1 사이의 값
|
||||
self.g_best_score = [0, np.inf] # 최고 점수 - 시작은 0으로 초기화
|
||||
self.g_best = None # 최고 점수를 받은 가중치
|
||||
self.g_best_ = None # 최고 점수를 받은 가중치 - 값의 분산을 위한 변수
|
||||
self.target_weights = target_weights # 목표 가중치
|
||||
self.avg_score = 0 # 평균 점수
|
||||
|
||||
self.save_path = None # 저장 위치
|
||||
self.renewal = "acc"
|
||||
self.Dispersion = False
|
||||
self.day = datetime.now().strftime("%m-%d-%H-%M")
|
||||
|
||||
negative_count = 0
|
||||
|
||||
for i in tqdm(range(self.n_particles), desc="Initializing Particles"):
|
||||
m = keras.models.model_from_json(model.to_json())
|
||||
init_weights = m.get_weights()
|
||||
w_, sh_, len_ = self._encode(init_weights)
|
||||
w_ = np.random.uniform(-1, 2, len(w_))
|
||||
m.set_weights(self._decode(w_, sh_, len_))
|
||||
m.compile(loss=self.loss, optimizer="sgd", metrics=["accuracy"])
|
||||
self.particles[i] = Particle(
|
||||
m,
|
||||
loss,
|
||||
negative=True if i < negative_swarm * self.n_particles else False,
|
||||
mutation=mutation_swarm,
|
||||
)
|
||||
if i < negative_swarm * self.n_particles:
|
||||
negative_count += 1
|
||||
|
||||
print(f"negative swarm : {negative_count} / {self.n_particles}")
|
||||
print(
|
||||
f"mutation swarm : {mutation_swarm * self.n_particles} / {self.n_particles}"
|
||||
)
|
||||
|
||||
gc.collect()
|
||||
|
||||
def __del__(self):
|
||||
del self.model
|
||||
del self.loss
|
||||
del self.n_particles
|
||||
del self.particles
|
||||
del self.c0
|
||||
del self.c1
|
||||
del self.w_min
|
||||
del self.w_max
|
||||
del self.negative_swarm
|
||||
del self.g_best_score
|
||||
del self.g_best
|
||||
del self.g_best_
|
||||
del self.avg_score
|
||||
gc.collect()
|
||||
|
||||
def _encode(self, weights):
|
||||
"""
|
||||
가중치를 1차원으로 풀어서 반환
|
||||
|
||||
Args:
|
||||
weights (list) : keras model의 가중치
|
||||
Returns:
|
||||
(numpy array) : 가중치 - 1차원으로 풀어서 반환
|
||||
(list) : 가중치의 원본 shape
|
||||
(list) : 가중치의 원본 shape의 길이
|
||||
"""
|
||||
w_gpu = np.array([])
|
||||
length = []
|
||||
shape = []
|
||||
for layer in weights:
|
||||
shape.append(layer.shape)
|
||||
w_ = layer.reshape(-1)
|
||||
length.append(len(w_))
|
||||
w_gpu = np.append(w_gpu, w_)
|
||||
|
||||
del weights
|
||||
|
||||
return w_gpu, shape, length
|
||||
|
||||
def _decode(self, weight, shape, length):
|
||||
"""
|
||||
_encode 로 인코딩된 가중치를 원본 shape으로 복원
|
||||
파라미터는 encode의 리턴값을 그대로 사용을 권장
|
||||
|
||||
Args:
|
||||
weight (numpy array): 가중치 - 1차원으로 풀어서 반환
|
||||
shape (list): 가중치의 원본 shape
|
||||
length (list): 가중치의 원본 shape의 길이
|
||||
Returns:
|
||||
(list) : 가중치 원본 shape으로 복원
|
||||
"""
|
||||
weights = []
|
||||
start = 0
|
||||
for i in range(len(shape)):
|
||||
end = start + length[i]
|
||||
w_ = weight[start:end]
|
||||
w_ = np.reshape(w_, shape[i])
|
||||
weights.append(w_)
|
||||
start = end
|
||||
|
||||
del weight
|
||||
del shape
|
||||
del length
|
||||
|
||||
return weights
|
||||
|
||||
def f(self, x, y, weights):
|
||||
"""
|
||||
EBPSO의 목적함수 (예상)
|
||||
|
||||
Args:
|
||||
x (list): 입력 데이터
|
||||
y (list): 출력 데이터
|
||||
weights (list): 가중치
|
||||
|
||||
Returns:
|
||||
(float): 목적 함수 값
|
||||
"""
|
||||
self.model.set_weights(weights)
|
||||
self.model.compile(loss=self.loss, optimizer="sgd", metrics=["accuracy"])
|
||||
score = self.model.evaluate(x, y, verbose=0)[1]
|
||||
if score > 0:
|
||||
return 1 / (1 + score)
|
||||
else:
|
||||
return 1 + np.abs(score)
|
||||
|
||||
def fit(
|
||||
self,
|
||||
x,
|
||||
y,
|
||||
epochs: int = 100,
|
||||
save: bool = False,
|
||||
save_path: str = "./result",
|
||||
renewal: str = "acc",
|
||||
empirical_balance: bool = False,
|
||||
Dispersion: bool = False,
|
||||
check_point: int = None,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
x_test : numpy array,
|
||||
y_test : numpy array,
|
||||
epochs : int,
|
||||
save : bool - True : save, False : not save
|
||||
save_path : str ex) "./result",
|
||||
renewal : str ex) "acc" or "loss" or "both",
|
||||
empirical_balance : bool - True :
|
||||
Dispersion : bool - True : g_best 의 값을 분산시켜 전역해를 찾음, False : g_best 의 값만 사용
|
||||
check_point : int - 저장할 위치 - None : 저장 안함
|
||||
"""
|
||||
self.save_path = save_path
|
||||
self.empirical_balance = empirical_balance
|
||||
self.Dispersion = Dispersion
|
||||
|
||||
self.renewal = renewal
|
||||
|
||||
try:
|
||||
if save:
|
||||
if save_path is None:
|
||||
raise ValueError("save_path is None")
|
||||
else:
|
||||
self.save_path = save_path
|
||||
if not os.path.exists(save_path):
|
||||
os.makedirs(save_path, exist_ok=True)
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
|
||||
for i in tqdm(range(self.n_particles), desc="Initializing velocity"):
|
||||
p = self.particles[i]
|
||||
local_score = p.get_score(x, y, renewal=renewal)
|
||||
|
||||
if renewal == "acc":
|
||||
if local_score[1] > self.g_best_score[0]:
|
||||
self.g_best_score[0] = local_score[1]
|
||||
self.g_best = p.get_best_weights()
|
||||
self.g_best_ = p.get_best_weights()
|
||||
elif renewal == "loss":
|
||||
if local_score[0] < self.g_best_score[1]:
|
||||
self.g_best_score[1] = local_score[0]
|
||||
self.g_best = p.get_best_weights()
|
||||
self.g_best_ = p.get_best_weights()
|
||||
|
||||
if local_score[0] == None:
|
||||
local_score[0] = np.inf
|
||||
|
||||
if local_score[1] == None:
|
||||
local_score[1] = 0
|
||||
|
||||
if save:
|
||||
with open(
|
||||
f"./{save_path}/{self.day}_{self.n_particles}_{epochs}_{self.c0}_{self.c1}_{self.w_min}_{renewal}.csv",
|
||||
"a",
|
||||
) as f:
|
||||
f.write(f"{local_score[0]}, {local_score[1]}")
|
||||
if i != self.n_particles - 1:
|
||||
f.write(", ")
|
||||
else:
|
||||
f.write("\n")
|
||||
|
||||
f.close()
|
||||
del local_score
|
||||
gc.collect()
|
||||
|
||||
print(
|
||||
f"initial g_best_score : {self.g_best_score[0] if self.renewal == 'acc' else self.g_best_score[1]}"
|
||||
)
|
||||
|
||||
try:
|
||||
epochs_pbar = tqdm(
|
||||
range(epochs),
|
||||
desc=f"best {self.g_best_score[0]:.4f}|{self.g_best_score[1]:.4f}",
|
||||
ascii=True,
|
||||
leave=True,
|
||||
)
|
||||
for epoch in epochs_pbar:
|
||||
acc = 0
|
||||
loss = 0
|
||||
min_score = np.inf
|
||||
max_score = 0
|
||||
min_loss = np.inf
|
||||
max_loss = 0
|
||||
|
||||
ts = self.c0 + np.random.rand() * (self.c1 - self.c0)
|
||||
|
||||
part_pbar = tqdm(
|
||||
range(len(self.particles)),
|
||||
desc=f"acc : {max_score:.4f} loss : {min_loss:.4f}",
|
||||
ascii=True,
|
||||
leave=False,
|
||||
)
|
||||
for i in part_pbar:
|
||||
part_pbar.set_description(
|
||||
f"acc : {max_score:.4f} loss : {min_loss:.4f}"
|
||||
)
|
||||
w = self.w_max - (self.w_max - self.w_min) * epoch / epochs
|
||||
|
||||
g_, g_sh, g_len = self._encode(self.g_best)
|
||||
decrement = (epochs - (epoch) + 1) / epochs
|
||||
g_ = (1 - decrement) * g_ + decrement * ts
|
||||
self.g_best_ = self._decode(g_, g_sh, g_len)
|
||||
|
||||
self.g_best = self.target_weights.get_weights()
|
||||
|
||||
if Dispersion:
|
||||
g_best = self.g_best_
|
||||
else:
|
||||
g_best = self.g_best
|
||||
|
||||
if empirical_balance:
|
||||
if np.random.rand() < np.exp(-(epoch) / epochs):
|
||||
w_p_ = self.f(x, y, self.particles[i].get_best_weights())
|
||||
w_g_ = self.f(x, y, self.g_best)
|
||||
w_p = w_p_ / (w_p_ + w_g_)
|
||||
w_g = w_p_ / (w_p_ + w_g_)
|
||||
|
||||
del w_p_
|
||||
del w_g_
|
||||
|
||||
else:
|
||||
p_b = self.particles[i].get_best_score()
|
||||
g_a = self.avg_score
|
||||
l_b = p_b - g_a
|
||||
l_b = np.sqrt(np.power(l_b, 2))
|
||||
p_ = (
|
||||
1
|
||||
/ (self.n_particles * np.linalg.norm(self.c1 - self.c0))
|
||||
* l_b
|
||||
)
|
||||
p_ = np.exp(-1 * p_)
|
||||
w_p = p_
|
||||
w_g = 1 - p_
|
||||
|
||||
del p_b
|
||||
del g_a
|
||||
del l_b
|
||||
del p_
|
||||
|
||||
score = self.particles[i].step_w(
|
||||
x, y, self.c0, self.c1, w, g_best, w_p, w_g, renewal=renewal
|
||||
)
|
||||
|
||||
else:
|
||||
score = self.particles[i].step(
|
||||
x, y, self.c0, self.c1, w, g_best, renewal=renewal
|
||||
)
|
||||
|
||||
if renewal == "acc":
|
||||
if score[1] >= self.g_best_score[0]:
|
||||
if score[1] > self.g_best_score[0]:
|
||||
self.g_best_score[0] = score[1]
|
||||
self.g_best = self.particles[i].get_best_weights()
|
||||
else:
|
||||
if score[0] < self.g_best_score[1]:
|
||||
self.g_best_score[1] = score[0]
|
||||
self.g_best = self.particles[i].get_best_weights()
|
||||
epochs_pbar.set_description(
|
||||
f"best {self.g_best_score[0]:.4f} | {self.g_best_score[1]:.4f}"
|
||||
)
|
||||
elif renewal == "loss":
|
||||
if score[0] <= self.g_best_score[1]:
|
||||
if score[0] < self.g_best_score[1]:
|
||||
self.g_best_score[1] = score[0]
|
||||
self.g_best = self.particles[i].get_best_weights()
|
||||
else:
|
||||
if score[1] > self.g_best_score[0]:
|
||||
self.g_best_score[0] = score[1]
|
||||
self.g_best = self.particles[i].get_best_weights()
|
||||
epochs_pbar.set_description(
|
||||
f"best {self.g_best_score[0]:.4f} | {self.g_best_score[1]:.4f}"
|
||||
)
|
||||
|
||||
if score[0] == None:
|
||||
score[0] = np.inf
|
||||
if score[1] == None:
|
||||
score[1] = 0
|
||||
|
||||
loss = loss + score[0]
|
||||
acc = acc + score[1]
|
||||
|
||||
if score[0] < min_loss:
|
||||
min_loss = score[0]
|
||||
if score[0] > max_loss:
|
||||
max_loss = score[0]
|
||||
|
||||
if score[1] < min_score:
|
||||
min_score = score[1]
|
||||
if score[1] > max_score:
|
||||
max_score = score[1]
|
||||
|
||||
if save:
|
||||
with open(
|
||||
f"./{save_path}/{self.day}_{self.n_particles}_{epochs}_{self.c0}_{self.c1}_{self.w_min}_{renewal}.csv",
|
||||
"a",
|
||||
) as f:
|
||||
f.write(f"{score[0]}, {score[1]}")
|
||||
if i != self.n_particles - 1:
|
||||
f.write(", ")
|
||||
else:
|
||||
f.write("\n")
|
||||
f.close()
|
||||
|
||||
if check_point is not None:
|
||||
if epoch % check_point == 0:
|
||||
os.makedirs(f"./{save_path}/{self.day}", exist_ok=True)
|
||||
self._check_point_save(f"./{save_path}/{self.day}/ckpt-{epoch}")
|
||||
self.avg_score = acc / self.n_particles
|
||||
|
||||
gc.collect()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("Ctrl + C : Stop Training")
|
||||
except MemoryError:
|
||||
print("Memory Error : Stop Training")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
finally:
|
||||
self.model_save(save_path)
|
||||
print("model save")
|
||||
self.save_info(save_path)
|
||||
print("save info")
|
||||
|
||||
return self.g_best_score
|
||||
|
||||
def get_best_model(self):
|
||||
"""
|
||||
최고 점수를 받은 모델을 반환
|
||||
|
||||
Returns:
|
||||
(keras.models): 모델
|
||||
"""
|
||||
model = keras.models.model_from_json(self.model.to_json())
|
||||
model.set_weights(self.g_best)
|
||||
model.compile(loss=self.loss, optimizer="sgd", metrics=["accuracy"])
|
||||
return model
|
||||
|
||||
def get_best_score(self):
|
||||
"""
|
||||
최고 점수를 반환
|
||||
|
||||
Returns:
|
||||
(float): 점수
|
||||
"""
|
||||
return self.g_best_score
|
||||
|
||||
def get_best_weights(self):
|
||||
"""
|
||||
최고 점수를 받은 가중치를 반환
|
||||
|
||||
Returns:
|
||||
(float): 가중치
|
||||
"""
|
||||
return self.g_best
|
||||
|
||||
def save_info(self, path: str = "./result"):
|
||||
"""
|
||||
학습 정보를 저장
|
||||
|
||||
Args:
|
||||
path (str, optional): 저장 위치. Defaults to "./result".
|
||||
"""
|
||||
json_save = {
|
||||
"name": f"{self.day}_{self.n_particles}_{self.c0}_{self.c1}_{self.w_min}.h5",
|
||||
"n_particles": self.n_particles,
|
||||
"score": self.g_best_score,
|
||||
"c0": self.c0,
|
||||
"c1": self.c1,
|
||||
"w_min": self.w_min,
|
||||
"w_max": self.w_max,
|
||||
"loss_method": self.loss,
|
||||
"empirical_balance": self.empirical_balance,
|
||||
"Dispersion": self.Dispersion,
|
||||
"negative_swarm": self.negative_swarm,
|
||||
"mutation_swarm": self.mutation_swarm,
|
||||
"renewal": self.renewal,
|
||||
}
|
||||
|
||||
with open(
|
||||
f"./{path}/{self.day}/{self.loss}_{self.g_best_score}.json",
|
||||
"a",
|
||||
) as f:
|
||||
json.dump(json_save, f, indent=4)
|
||||
|
||||
f.close()
|
||||
|
||||
def _check_point_save(self, save_path: str = f"./result/check_point"):
|
||||
"""
|
||||
중간 저장
|
||||
|
||||
Args:
|
||||
save_path (str, optional): checkpoint 저장 위치 및 이름. Defaults to f"./result/check_point".
|
||||
"""
|
||||
model = self.get_best_model()
|
||||
model.save_weights(save_path)
|
||||
|
||||
def model_save(self, save_path: str = "./result"):
|
||||
"""
|
||||
최고 점수를 받은 모델 저장
|
||||
|
||||
Args:
|
||||
save_path (str, optional): 모델의 저장 위치. Defaults to "./result".
|
||||
|
||||
Returns:
|
||||
(keras.models): 모델
|
||||
"""
|
||||
model = self.get_best_model()
|
||||
model.save(
|
||||
f"./{save_path}/{self.day}/{self.n_particles}_{self.c0}_{self.c1}_{self.w_min}.h5"
|
||||
)
|
||||
return model
|
||||
@@ -1,309 +0,0 @@
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
from tensorflow import keras
|
||||
from tqdm import tqdm
|
||||
|
||||
|
||||
class PSO(object):
|
||||
"""
|
||||
Class implementing PSO algorithm
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: keras.models,
|
||||
loss_method=keras.losses.MeanSquaredError(),
|
||||
optimizer="adam",
|
||||
n_particles=5,
|
||||
):
|
||||
"""
|
||||
Initialize the key variables.
|
||||
|
||||
Args:
|
||||
model : 학습할 모델 객체 (Sequential)
|
||||
loss_method : 손실 함수
|
||||
optimizer : 최적화 함수
|
||||
n_particles(int) : 파티클의 개수
|
||||
"""
|
||||
self.model = model # 모델
|
||||
self.n_particles = n_particles # 파티클의 개수
|
||||
self.loss_method = loss_method # 손실 함수
|
||||
self.optimizer = optimizer # 최적화 함수
|
||||
self.model_structure = self.model.to_json() # 모델의 구조
|
||||
self.init_weights = self.model.get_weights() # 검색할 차원
|
||||
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
||||
self.particles_weights = [None] * n_particles # 파티클의 위치
|
||||
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
||||
# particle_node = []
|
||||
m = keras.models.model_from_json(self.model_structure)
|
||||
m.compile(
|
||||
loss=self.loss_method, optimizer=self.optimizer, metrics=["accuracy"]
|
||||
)
|
||||
self.particles_weights[_] = m.get_weights()
|
||||
# print(f"shape > {self.particles_weights[_][0]}")
|
||||
|
||||
# self.particles_weights.append(particle_node)
|
||||
|
||||
# print(f"particles_weights > {self.particles_weights}")
|
||||
# self.particles_weights = np.random.uniform(size=(n_particles, self.particle_depth)) \
|
||||
# * self.init_pos
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
||||
# self.velocities = [None] * self.n_particles
|
||||
self.velocities = [
|
||||
[0 for __ in range(self.particle_depth)] for _ in range(n_particles)
|
||||
]
|
||||
for i in tqdm(range(n_particles), desc="init velocities"):
|
||||
# print(i)
|
||||
for index, layer in enumerate(self.init_weights):
|
||||
# print(f"index > {index}")
|
||||
# print(f"layer > {layer.shape}")
|
||||
self.velocities[i][index] = np.random.rand(*layer.shape) / 5 - 0.10
|
||||
# if layer.ndim == 1:
|
||||
# self.velocities[i][index] = np.random.uniform(
|
||||
# size=(layer.shape[0],))
|
||||
# elif layer.ndim == 2:
|
||||
# self.velocities[i][index] = np.random.uniform(
|
||||
# size=(layer.shape[0], layer.shape[1]))
|
||||
# elif layer.ndim == 3:
|
||||
# self.velocities[i][index] = np.random.uniform(
|
||||
# size=(layer.shape[0], layer.shape[1], layer.shape[2]))
|
||||
# print(f"type > {type(self.velocities)}")
|
||||
# print(f"velocities > {self.velocities}")
|
||||
|
||||
# print(f"velocities > {self.velocities}")
|
||||
# for i, layer in enumerate(self.init_weights):
|
||||
# self.velocities[i] = np.random.rand(*layer.shape) / 5 - 0.10
|
||||
|
||||
# self.velocities = np.random.uniform(
|
||||
# size=(n_particles, self.particle_depth))
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
||||
# 최대 사이즈로 전역 최적갑 저장 - global best
|
||||
self.g_best = self.model.get_weights() # 전역 최적값(최적의 가중치)
|
||||
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
||||
self.p_best_score = [0 for _ in range(n_particles)] # 각 파티클의 최적값의 점수
|
||||
self.g_best_score = 0 # 전역 최적값의 점수(초기화 - 무한대)
|
||||
self.g_history = []
|
||||
self.g_best_score_history = []
|
||||
self.history = []
|
||||
|
||||
def _update_weights(self, weights, v):
|
||||
"""
|
||||
Update particle position
|
||||
|
||||
Args:
|
||||
weights (array-like) : 파티클의 현재 가중치
|
||||
v (array-like) : 가중치의 속도
|
||||
|
||||
Returns:
|
||||
(array-like) : 파티클의 새로운 가중치(위치)
|
||||
"""
|
||||
# w = np.array(w) # 각 파티클의 위치
|
||||
# v = np.array(v) # 각 파티클의 속도(방향과 속력을 가짐)
|
||||
# print(f"len(w) > {len(w)}")
|
||||
# print(f"len(v) > {len(v)}")
|
||||
new_weights = [0 for i in range(len(weights))]
|
||||
for i in range(len(weights)):
|
||||
# print(f"shape > w : {np.shape(w[i])}, v : {np.shape(v[i])}")
|
||||
new_weights[i] = tf.add(weights[i], v[i])
|
||||
# new_w = tf.add(w, v) # 각 파티클을 랜덤한 속도만큼 진행
|
||||
return new_weights # 진행한 파티클들의 위치를 반환
|
||||
|
||||
def _update_velocity(self, weights, v, p_best, c0=0.5, c1=1.5, w=0.75):
|
||||
"""
|
||||
Update particle velocity
|
||||
|
||||
Args:
|
||||
weights (array-like) : 파티클의 현재 가중치
|
||||
v (array-like) : 속도
|
||||
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
||||
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
||||
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
||||
w (float) : 관성 상수 (현재 속도의 중요도)
|
||||
|
||||
Returns:
|
||||
(array-like) : 각 파티클의 새로운 속도
|
||||
"""
|
||||
# x = np.array(x)
|
||||
# v = np.array(v)
|
||||
# assert np.shape(weights) == np.shape(v), "Position and velocity must have same shape."
|
||||
# 두 데이터의 shape 이 같지 않으면 오류 출력
|
||||
# 0에서 1사이의 숫자를 랜덤 생성
|
||||
r0 = np.random.rand()
|
||||
r1 = np.random.rand()
|
||||
# print(f"type > weights : {type(weights)}")
|
||||
# print(f"type > v : {type(v)}")
|
||||
# print(
|
||||
# f"shape > weights : {np.shape(weights[0])}, v : {np.shape(v[0])}")
|
||||
# print(f"len > weights : {len(weights)}, v : {len(v)}")
|
||||
# p_best = np.array(p_best)
|
||||
# g_best = np.array(g_best)
|
||||
|
||||
# 가중치(상수)*속도 + \
|
||||
# 스케일링 상수*랜덤 가중치*(나의 최적값 - 처음 위치) + \
|
||||
# 전역 스케일링 상수*랜덤 가중치*(전체 최적값 - 처음 위치)
|
||||
# for i, layer in enumerate(weights):
|
||||
new_velocity = [None] * len(weights)
|
||||
for i, layer in enumerate(weights):
|
||||
|
||||
new_v = w * v[i]
|
||||
new_v = new_v + c0 * r0 * (p_best[i] - layer)
|
||||
new_v = new_v + c1 * r1 * (self.g_best[i] - layer)
|
||||
new_velocity[i] = new_v
|
||||
|
||||
# m2 = tf.multiply(tf.multiply(c0, r0),
|
||||
# tf.subtract(p_best[i], layer))
|
||||
# m3 = tf.multiply(tf.multiply(c1, r1),
|
||||
# tf.subtract(g_best[i], layer))
|
||||
# new_v[i] = tf.add(m1, tf.add(m2, m3))
|
||||
# new_v[i] = tf.add_n([m1, m2, m3])
|
||||
# new_v[i] = tf.add_n(
|
||||
# tf.multiply(w, v[i]),
|
||||
# tf.multiply(tf.multiply(c0, r0),
|
||||
# tf.subtract(p_best[i], layer)),
|
||||
# tf.multiply(tf.multiply(c1, r1),
|
||||
# tf.subtract(g_best[i], layer)))
|
||||
# new_v = w*v + c0*r0*(p_best - weights) + c1*r1*(g_best - weights)
|
||||
return new_velocity
|
||||
|
||||
def _get_score(self, x, y):
|
||||
"""
|
||||
Compute the score of the current position of the particles.
|
||||
|
||||
Args:
|
||||
x (array-like): The current position of the particles
|
||||
y (array-like): The current position of the particles
|
||||
Returns:
|
||||
(array-like) : 추론에 대한 점수
|
||||
"""
|
||||
# = self.model
|
||||
# model.set_weights(weights)
|
||||
score = self.model.evaluate(x, y, verbose=0)
|
||||
|
||||
return score
|
||||
|
||||
def optimize(
|
||||
self,
|
||||
x_train,
|
||||
y_train,
|
||||
x_test,
|
||||
y_test,
|
||||
maxiter=10,
|
||||
epochs=1,
|
||||
batch_size=32,
|
||||
c0=0.5,
|
||||
c1=1.5,
|
||||
w=0.75,
|
||||
):
|
||||
"""
|
||||
Run the PSO optimization process utill the stoping critera is met.
|
||||
Cas for minization. The aim is to minimize the cost function
|
||||
|
||||
Args:
|
||||
maxiter (int): the maximum number of iterations before stopping the optimization
|
||||
파티클의 최종 위치를 위한 반복 횟수
|
||||
Returns:
|
||||
The best solution found (array-like)
|
||||
"""
|
||||
for _ in range(maxiter):
|
||||
loss = 0
|
||||
acc = 1e-10
|
||||
for i in tqdm(
|
||||
range(self.n_particles),
|
||||
desc=f"Iter {_}/{maxiter} | acc avg {round(acc/(_+1) ,4)}",
|
||||
ascii=True,
|
||||
):
|
||||
weights = self.particles_weights[i] # 각 파티클 추출
|
||||
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
||||
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
||||
# 2. 속도 계산
|
||||
self.velocities[i] = self._update_velocity(
|
||||
weights, v, p_best, c0, c1, w
|
||||
)
|
||||
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
||||
# 3. 위치 업데이트
|
||||
self.particles_weights[i] = self._update_weights(weights, v)
|
||||
# 현재 위치 = 최초 위치 현재 속도
|
||||
# Update the besst position for particle i
|
||||
# 내 현재 위치가 내 위치의 최소치보다 작으면 갱신
|
||||
self.model.set_weights(self.particles_weights[i].copy())
|
||||
self.model.fit(
|
||||
x_train,
|
||||
y_train,
|
||||
epochs=epochs,
|
||||
batch_size=batch_size,
|
||||
verbose=0,
|
||||
validation_data=(x_test, y_test),
|
||||
)
|
||||
self.particles_weights[i] = self.model.get_weights()
|
||||
# 4. 평가
|
||||
self.model.compile(
|
||||
loss=self.loss_method, optimizer="adam", metrics=["accuracy"]
|
||||
)
|
||||
score = self._get_score(x_test, y_test)
|
||||
# print(score)
|
||||
|
||||
# print(f"score : {score}")
|
||||
# print(f"loss : {loss}")
|
||||
# print(f"p_best_score : {self.p_best_score[i]}")
|
||||
|
||||
if score[1] > self.p_best_score[i]:
|
||||
self.p_best_score[i] = score[1]
|
||||
self.p_best[i] = self.particles_weights[i].copy()
|
||||
if score[1] > self.g_best_score:
|
||||
self.g_best_score = score[1]
|
||||
self.g_best = self.particles_weights[i].copy()
|
||||
self.g_history.append(self.g_best)
|
||||
self.g_best_score_history.append(self.g_best_score)
|
||||
|
||||
self.score = score[1]
|
||||
loss = loss + score[0]
|
||||
acc = acc + score[1]
|
||||
# if self.func(self.particles_weights[i]) < self.func(p_best):
|
||||
# self.p_best[i] = self.particles_weights[i]
|
||||
# if self.
|
||||
# Update the best position overall
|
||||
# 내 현재 위치가 전체 위치 최소치보다 작으면 갱신
|
||||
# if self.func(self.particles_weights[i]) < self.func(self.g_best):
|
||||
# self.g_best = self.particles_weights[i]
|
||||
# self.g_history.append(self.g_best)
|
||||
# print(f"{i} particle score : {score[0]}")
|
||||
print(
|
||||
f"loss avg : {loss/self.n_particles} | acc avg : {acc/self.n_particles} | best loss : {self.g_best_score}"
|
||||
)
|
||||
|
||||
# self.history.append(self.particles_weights.copy())
|
||||
|
||||
# 전체 최소 위치, 전체 최소 벡터
|
||||
return self.g_best, self._get_score(x_test, y_test)
|
||||
|
||||
"""
|
||||
Returns:
|
||||
현재 전체 위치
|
||||
"""
|
||||
|
||||
def position(self):
|
||||
return self.particles_weights.copy()
|
||||
|
||||
"""
|
||||
Returns:
|
||||
전체 위치 벡터 history
|
||||
"""
|
||||
|
||||
def position_history(self):
|
||||
return self.history.copy()
|
||||
|
||||
"""
|
||||
Returns:
|
||||
global best 의 갱신된 값의 변화를 반환
|
||||
"""
|
||||
|
||||
def global_history(self):
|
||||
return self.g_history.copy()
|
||||
|
||||
"""
|
||||
Returns:
|
||||
global best score 의 갱신된 값의 변화를 반환
|
||||
"""
|
||||
|
||||
def global_score_history(self):
|
||||
return self.g_best_score_history.copy()
|
||||
@@ -1,137 +0,0 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
class PSO(object):
|
||||
"""
|
||||
Class implementing PSO algorithm
|
||||
"""
|
||||
|
||||
def __init__(self, func, init_pos, n_particles):
|
||||
"""
|
||||
Initialize the key variables.
|
||||
|
||||
Args:
|
||||
fun (function): the fitness function to optimize
|
||||
init_pos(array_like):
|
||||
n_particles(int): the number of particles of the swarm.
|
||||
"""
|
||||
self.func = func
|
||||
self.n_particles = n_particles
|
||||
self.init_pos = init_pos # 검색할 차원
|
||||
self.particle_dim = len(init_pos) # 검색할 차원의 크기
|
||||
self.particles_pos = (
|
||||
np.random.uniform(size=(n_particles, self.particle_dim)) * self.init_pos
|
||||
)
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
||||
self.velocities = np.random.uniform(size=(n_particles, self.particle_dim))
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
||||
self.g_best = init_pos # 최대 사이즈로 전역 최적갑 저장 - global best
|
||||
self.p_best = self.particles_pos # 모든 파티클의 위치 - particles best
|
||||
self.g_history = []
|
||||
self.history = []
|
||||
|
||||
def update_position(self, x, v):
|
||||
"""
|
||||
Update particle position
|
||||
|
||||
Args:
|
||||
x (array-like): particle current position
|
||||
v (array-like): particle current velocity
|
||||
|
||||
Returns:
|
||||
The updated position(array-like)
|
||||
"""
|
||||
x = np.array(x) # 각 파티클의 위치
|
||||
v = np.array(v) # 각 파티클의 속도(방향과 속력을 가짐)
|
||||
new_x = x + v # 각 파티클을 랜덤한 속도만큼 진행
|
||||
return new_x # 진행한 파티클들의 위치를 반환
|
||||
|
||||
def update_velocity(self, x, v, p_best, g_best, c0=0.5, c1=1.5, w=0.75):
|
||||
"""
|
||||
Update particle velocity
|
||||
|
||||
Args:
|
||||
x(array-like): particle current position
|
||||
v (array-like): particle current velocity
|
||||
p_best(array-like): the best position found so far for a particle
|
||||
g_best(array-like): the best position regarding all the particles found so far
|
||||
c0 (float): the congnitive scaling constant, 인지 스케일링 상수
|
||||
c1 (float): the social scaling constant
|
||||
w (float): the inertia weight, 관성 중량
|
||||
|
||||
Returns:
|
||||
The updated velocity (array-like).
|
||||
"""
|
||||
x = np.array(x)
|
||||
v = np.array(v)
|
||||
assert x.shape == v.shape, "Position and velocity must have same shape."
|
||||
# 두 데이터의 shape 이 같지 않으면 오류 출력
|
||||
# 0에서 1사이의 숫자를 랜덤 생성
|
||||
r = np.random.uniform()
|
||||
p_best = np.array(p_best)
|
||||
g_best = np.array(g_best)
|
||||
|
||||
# 가중치(상수)*속도 + \
|
||||
# 스케일링 상수*랜덤 가중치*(나의 최적값 - 처음 위치) + \
|
||||
# 전역 스케일링 상수*랜덤 가중치*(전체 최적값 - 처음 위치)
|
||||
new_v = w * v + c0 * r * (p_best - x) + c1 * r * (g_best - x)
|
||||
return new_v
|
||||
|
||||
def optimize(self, maxiter=200):
|
||||
"""
|
||||
Run the PSO optimization process utill the stoping critera is met.
|
||||
Cas for minization. The aim is to minimize the cost function
|
||||
|
||||
Args:
|
||||
maxiter (int): the maximum number of iterations before stopping the optimization
|
||||
파티클의 최종 위치를 위한 반복 횟수
|
||||
Returns:
|
||||
The best solution found (array-like)
|
||||
"""
|
||||
for _ in range(maxiter):
|
||||
for i in range(self.n_particles):
|
||||
x = self.particles_pos[i] # 각 파티클 추출
|
||||
v = self.velocities[i] # 랜덤 생성한 속도 추출
|
||||
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
||||
self.velocities[i] = self.update_velocity(x, v, p_best, self.g_best)
|
||||
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
||||
self.particles_pos[i] = self.update_position(x, v)
|
||||
# 현재 위치 = 최초 위치 현재 속도
|
||||
# Update the besst position for particle i
|
||||
# 내 현재 위치가 내 위치의 최소치보다 작으면 갱신
|
||||
if self.func(self.particles_pos[i]) < self.func(p_best):
|
||||
self.p_best[i] = self.particles_pos[i]
|
||||
# Update the best position overall
|
||||
# 내 현재 위치가 전체 위치 최소치보다 작으면 갱신
|
||||
if self.func(self.particles_pos[i]) < self.func(self.g_best):
|
||||
self.g_best = self.particles_pos[i]
|
||||
self.g_history.append(self.g_best)
|
||||
|
||||
self.history.append(self.particles_pos.copy())
|
||||
|
||||
# 전체 최소 위치, 전체 최소 벡터
|
||||
return self.g_best, self.func(self.g_best)
|
||||
|
||||
"""
|
||||
Returns:
|
||||
현재 전체 위치
|
||||
"""
|
||||
|
||||
def position(self):
|
||||
return self.particles_pos.copy()
|
||||
|
||||
"""
|
||||
Returns:
|
||||
전체 위치 벡터 history
|
||||
"""
|
||||
|
||||
def position_history(self):
|
||||
return self.history
|
||||
|
||||
"""
|
||||
Returns:
|
||||
global best 의 갱신된 값의 변화를 반환
|
||||
"""
|
||||
|
||||
def global_history(self):
|
||||
return self.g_history.copy()
|
||||
@@ -1,298 +0,0 @@
|
||||
import os
|
||||
import numpy as np
|
||||
from tqdm import tqdm
|
||||
from matplotlib import pyplot as plt
|
||||
import pandas as pd
|
||||
|
||||
import tensorflow as tf
|
||||
from tensorflow import keras
|
||||
|
||||
import datetime
|
||||
import gc
|
||||
import cupy as cp
|
||||
|
||||
|
||||
class PSO(object):
|
||||
"""
|
||||
Class implementing PSO algorithm
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: keras.models,
|
||||
loss_method=keras.losses.MeanSquaredError(),
|
||||
n_particles: int = 5,
|
||||
):
|
||||
"""
|
||||
Initialize the key variables.
|
||||
|
||||
Args:
|
||||
model : 학습할 모델 객체 (Sequential)
|
||||
loss_method : 손실 함수
|
||||
n_particles(int) : 파티클의 개수
|
||||
"""
|
||||
self.model = model # 모델
|
||||
self.n_particles = n_particles # 파티클의 개수
|
||||
self.loss_method = loss_method # 손실 함수
|
||||
model_structure = self.model.to_json() # 모델의 구조 정보
|
||||
self.init_weights = self.model.get_weights() # 검색할 차원
|
||||
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
||||
self.particles_weights = [None] * n_particles # 파티클의 위치
|
||||
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
||||
m = keras.models.model_from_json(model_structure)
|
||||
m.compile(loss=self.loss_method, optimizer="adam", metrics=["accuracy"])
|
||||
self.particles_weights[_] = m.get_weights()
|
||||
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
||||
self.velocities = [
|
||||
[0 for __ in range(self.particle_depth)] for _ in range(n_particles)
|
||||
]
|
||||
for i in tqdm(range(n_particles), desc="init velocities"):
|
||||
|
||||
self.init_weights = self.model.get_weights()
|
||||
w_, s_, l_ = self._encode(self.init_weights)
|
||||
w_ = np.random.rand(len(w_)) / 5 - 0.10
|
||||
self.velocities[i] = self._decode(w_, s_, l_)
|
||||
# for index, layer in enumerate(self.init_weights):
|
||||
# self.velocities[i][index] = np.random.rand(
|
||||
# *layer.shape) / 5 - 0.10
|
||||
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
||||
# 최대 사이즈로 전역 최적갑 저장 - global best
|
||||
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
||||
self.g_best = (
|
||||
self.model.get_weights()
|
||||
) # 전역 최적값(최적의 가중치) | 초기값은 모델의 가중치
|
||||
|
||||
# 각 파티클의 최적값의 점수
|
||||
self.p_best_score = [0 for i in range(n_particles)]
|
||||
|
||||
# 전역 최적값의 점수(초기화 - 0)
|
||||
self.g_best_score = 0
|
||||
|
||||
def __del__(self):
|
||||
del self.model
|
||||
del self.n_particles
|
||||
del self.loss_method
|
||||
del self.init_weights
|
||||
del self.particles_weights
|
||||
del self.velocities
|
||||
del self.p_best
|
||||
del self.g_best
|
||||
del self.p_best_score
|
||||
del self.g_best_score
|
||||
|
||||
def _encode(self, weights: list):
|
||||
# w_gpu = cp.array([])
|
||||
w_gpu = np.array([])
|
||||
lenght = []
|
||||
shape = []
|
||||
for layer in weights:
|
||||
shape.append(layer.shape)
|
||||
w_ = layer.reshape(-1)
|
||||
lenght.append(len(w_))
|
||||
w_gpu = np.append(w_gpu, w_)
|
||||
# w_gpu = cp.append(w_gpu, w_)
|
||||
|
||||
return w_gpu, shape, lenght
|
||||
|
||||
def _decode(self, weight, shape, lenght):
|
||||
weights = []
|
||||
start = 0
|
||||
for i in range(len(shape)):
|
||||
end = start + lenght[i]
|
||||
# print(f"{start} ~ {end}")
|
||||
# print(f"{shape[i]}")
|
||||
w_ = weight[start:end]
|
||||
w_ = np.reshape(w_, shape[i])
|
||||
# w_ = w_.reshape(shape[i])
|
||||
weights.append(w_)
|
||||
start = end
|
||||
|
||||
return weights
|
||||
|
||||
def _update_weights(self, weights, v):
|
||||
"""
|
||||
Update particle position
|
||||
|
||||
Args:
|
||||
weights (array-like) : 파티클의 현재 가중치
|
||||
v (array-like) : 가중치의 속도
|
||||
|
||||
Returns:
|
||||
(array-like) : 파티클의 새로운 가중치(위치)
|
||||
"""
|
||||
# w = np.array(w) # 각 파티클의 위치
|
||||
# v = np.array(v) # 각 파티클의 속도(방향과 속력을 가짐)
|
||||
# new_weights = [0 for i in range(len(weights))]
|
||||
# print(f"weights : {weights}")
|
||||
encode_w, w_sh, w_len = self._encode(weights=weights)
|
||||
encode_v, _, _ = self._encode(weights=v)
|
||||
new_w = encode_w + encode_v
|
||||
new_weights = self._decode(new_w, w_sh, w_len)
|
||||
|
||||
# for i in range(len(weights)):
|
||||
# new_weights[i] = tf.add(weights[i], v[i])
|
||||
# new_w = tf.add(w, v) # 각 파티클을 랜덤한 속도만큼 진행
|
||||
return new_weights # 진행한 파티클들의 위치를 반환
|
||||
|
||||
def _update_velocity(self, weights, v, p_best, c0=0.5, c1=1.5, w=0.75):
|
||||
"""
|
||||
Update particle velocity
|
||||
|
||||
Args:
|
||||
weights (array-like) : 파티클의 현재 가중치
|
||||
v (array-like) : 속도
|
||||
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
||||
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
||||
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
||||
w (float) : 관성 상수 (현재 속도의 중요도)
|
||||
|
||||
Returns:
|
||||
(array-like) : 각 파티클의 새로운 속도
|
||||
"""
|
||||
# x = np.array(x)
|
||||
# v = np.array(v)
|
||||
# assert np.shape(weights) == np.shape(v), "Position and velocity must have same shape."
|
||||
# 두 데이터의 shape 이 같지 않으면 오류 출력
|
||||
# 0에서 1사이의 숫자를 랜덤 생성
|
||||
r0 = np.random.rand()
|
||||
r1 = np.random.rand()
|
||||
# p_best = np.array(p_best)
|
||||
# g_best = np.array(g_best)
|
||||
|
||||
# 가중치(상수)*속도 + \
|
||||
# 스케일링 상수*랜덤 가중치*(나의 최적값 - 처음 위치) + \
|
||||
# 전역 스케일링 상수*랜덤 가중치*(전체 최적값 - 처음 위치)
|
||||
|
||||
encode_w, w_sh, w_len = self._encode(weights=weights)
|
||||
encode_v, _, _ = self._encode(weights=v)
|
||||
encode_p, _, _ = self._encode(weights=p_best)
|
||||
encode_g, _, _ = self._encode(weights=self.g_best)
|
||||
|
||||
new_v = (
|
||||
encode_w * encode_v
|
||||
+ c0 * r0 * (encode_p - encode_w)
|
||||
+ c1 * r1 * (encode_g - encode_w)
|
||||
)
|
||||
new_velocity = self._decode(new_v, w_sh, w_len)
|
||||
# new_velocity = [None] * len(weights)
|
||||
# for i, layer in enumerate(weights):
|
||||
|
||||
# new_v = w*v[i]
|
||||
# new_v = new_v + c0*r0*(p_best[i] - layer)
|
||||
# new_v = new_v + c1*r1*(self.g_best[i] - layer)
|
||||
# new_velocity[i] = new_v
|
||||
|
||||
# new_v = w*v + c0*r0*(p_best - weights) + c1*r1*(g_best - weights)
|
||||
return new_velocity
|
||||
|
||||
def _get_score(self, x, y):
|
||||
"""
|
||||
Compute the score of the current position of the particles.
|
||||
|
||||
Args:
|
||||
x (array-like): The current position of the particles
|
||||
y (array-like): The current position of the particles
|
||||
Returns:
|
||||
(array-like) : 추론에 대한 점수
|
||||
"""
|
||||
score = self.model.evaluate(x, y, verbose=0)
|
||||
|
||||
return score
|
||||
|
||||
def optimize(
|
||||
self,
|
||||
x_,
|
||||
y_,
|
||||
maxiter=10,
|
||||
c0=0.5,
|
||||
c1=1.5,
|
||||
w=0.75,
|
||||
save=False,
|
||||
save_path="./result/history",
|
||||
):
|
||||
"""
|
||||
Run the PSO optimization process utill the stoping critera is met.
|
||||
Cas for minization. The aim is to minimize the cost function
|
||||
|
||||
Args:
|
||||
maxiter (int): the maximum number of iterations before stopping the optimization
|
||||
파티클의 최종 위치를 위한 반복 횟수
|
||||
Returns:
|
||||
The best solution found (array-like)
|
||||
"""
|
||||
if save:
|
||||
os.makedirs(save_path, exist_ok=True)
|
||||
day = datetime.datetime.now().strftime("%m-%d-%H-%M")
|
||||
|
||||
for _ in range(maxiter):
|
||||
|
||||
for i in tqdm(
|
||||
range(self.n_particles), desc=f"Iter {_}/{maxiter} ", ascii=True
|
||||
):
|
||||
weights = self.particles_weights[i] # 각 파티클 추출
|
||||
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
||||
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
||||
# 2. 속도 계산
|
||||
self.velocities[i] = self._update_velocity(
|
||||
weights, v, p_best, c0, c1, w
|
||||
)
|
||||
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
||||
# 3. 위치 업데이트
|
||||
self.particles_weights[i] = self._update_weights(weights, v)
|
||||
# 현재 위치 = 이전 위치 + 현재 속도
|
||||
# 내 현재 위치가 내 위치의 최소치보다 작으면 갱신
|
||||
self.model.set_weights(self.particles_weights[i])
|
||||
# self.particles_weights[i] = self.model.get_weights()
|
||||
# 4. 평가
|
||||
self.model.compile(
|
||||
loss=self.loss_method, optimizer="sgd", metrics=["accuracy"]
|
||||
)
|
||||
score = self._get_score(x_, y_)
|
||||
|
||||
if score[1] > self.p_best_score[i]:
|
||||
self.p_best_score[i] = score[1]
|
||||
self.p_best[i] = self.particles_weights[i]
|
||||
if score[1] > self.g_best_score:
|
||||
self.g_best_score = score[1]
|
||||
self.g_best = self.particles_weights[i]
|
||||
|
||||
if save:
|
||||
with open(
|
||||
f"{save_path}/{day}_{self.n_particles}_{maxiter}_{c0}_{c1}_{w}.csv",
|
||||
"a",
|
||||
) as f:
|
||||
f.write(f"{score[0]}, {score[1]}")
|
||||
if i != self.n_particles - 1:
|
||||
f.write(",")
|
||||
|
||||
if save:
|
||||
with open(
|
||||
f"{save_path}/{day}_{self.n_particles}_{maxiter}_{c0}_{c1}_{w}.csv",
|
||||
"a",
|
||||
) as f:
|
||||
f.write("\n")
|
||||
print(
|
||||
f"loss avg : {score[0]/self.n_particles} | acc avg : {score[1]/self.n_particles} | best score : {self.g_best_score}"
|
||||
)
|
||||
gc.collect()
|
||||
|
||||
# 전체 최소 위치, 전체 최소 벡터
|
||||
return self.g_best, self._get_score(x_, y_)
|
||||
|
||||
"""
|
||||
Returns:
|
||||
최종 가중치
|
||||
"""
|
||||
|
||||
def best_weights(self):
|
||||
return self.g_best
|
||||
|
||||
"""
|
||||
Returns:
|
||||
최종 가중치의 스코어
|
||||
"""
|
||||
|
||||
def best_score(self):
|
||||
return self.g_best_score
|
||||
@@ -1,221 +0,0 @@
|
||||
import os
|
||||
import numpy as np
|
||||
from tqdm import tqdm
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
import tensorflow as tf
|
||||
from tensorflow import keras
|
||||
|
||||
|
||||
class PSO(object):
|
||||
"""
|
||||
Class implementing PSO algorithm
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: keras.models,
|
||||
loss_method=keras.losses.MeanSquaredError(),
|
||||
n_particles: int = 5,
|
||||
):
|
||||
"""
|
||||
Initialize the key variables.
|
||||
|
||||
Args:
|
||||
model : 학습할 모델 객체 (Sequential)
|
||||
loss_method : 손실 함수
|
||||
n_particles(int) : 파티클의 개수
|
||||
"""
|
||||
self.model = model # 모델
|
||||
self.n_particles = n_particles # 파티클의 개수
|
||||
self.loss_method = loss_method # 손실 함수
|
||||
self.model_structure = self.model.to_json() # 모델의 구조 정보
|
||||
self.init_weights = self.model.get_weights() # 검색할 차원
|
||||
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
||||
self.particles_weights = [None] * n_particles # 파티클의 위치
|
||||
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
||||
m = keras.models.model_from_json(self.model_structure)
|
||||
m.compile(loss=self.loss_method, optimizer="adam", metrics=["accuracy"])
|
||||
self.particles_weights[_] = m.get_weights()
|
||||
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
||||
self.velocities = [
|
||||
[0 for __ in range(self.particle_depth)] for _ in range(n_particles)
|
||||
]
|
||||
for i in tqdm(range(n_particles), desc="init velocities"):
|
||||
for index, layer in enumerate(self.init_weights):
|
||||
self.velocities[i][index] = np.random.rand(*layer.shape) / 5 - 0.10
|
||||
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
||||
# 최대 사이즈로 전역 최적갑 저장 - global best
|
||||
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
||||
self.g_best = (
|
||||
self.model.get_weights()
|
||||
) # 전역 최적값(최적의 가중치) | 초기값은 모델의 가중치
|
||||
|
||||
# 각 파티클의 최적값의 점수
|
||||
self.p_best_score = [0 for i in range(n_particles)]
|
||||
|
||||
# 전역 최적값의 점수(초기화 - 0)
|
||||
self.g_best_score = 0
|
||||
self.loss_history = [[] for i in range(n_particles)] # 각 파티클의 손실값 변화
|
||||
self.acc_history = [[] for i in range(n_particles)] # 각 파티클의 정확도 변화
|
||||
self.g_best_score_history = [] # 전역 최적값의 점수 변화
|
||||
|
||||
def _update_weights(self, weights, v):
|
||||
"""
|
||||
Update particle position
|
||||
|
||||
Args:
|
||||
weights (array-like) : 파티클의 현재 가중치
|
||||
v (array-like) : 가중치의 속도
|
||||
|
||||
Returns:
|
||||
(array-like) : 파티클의 새로운 가중치(위치)
|
||||
"""
|
||||
# w = np.array(w) # 각 파티클의 위치
|
||||
# v = np.array(v) # 각 파티클의 속도(방향과 속력을 가짐)
|
||||
new_weights = [0 for i in range(len(weights))]
|
||||
for i in range(len(weights)):
|
||||
new_weights[i] = tf.add(weights[i], v[i])
|
||||
# new_w = tf.add(w, v) # 각 파티클을 랜덤한 속도만큼 진행
|
||||
return new_weights # 진행한 파티클들의 위치를 반환
|
||||
|
||||
def _update_velocity(self, weights, v, p_best, c0=0.5, c1=1.5, w=0.75):
|
||||
"""
|
||||
Update particle velocity
|
||||
|
||||
Args:
|
||||
weights (array-like) : 파티클의 현재 가중치
|
||||
v (array-like) : 속도
|
||||
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
||||
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
||||
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
||||
w (float) : 관성 상수 (현재 속도의 중요도)
|
||||
|
||||
Returns:
|
||||
(array-like) : 각 파티클의 새로운 속도
|
||||
"""
|
||||
# x = np.array(x)
|
||||
# v = np.array(v)
|
||||
# assert np.shape(weights) == np.shape(v), "Position and velocity must have same shape."
|
||||
# 두 데이터의 shape 이 같지 않으면 오류 출력
|
||||
# 0에서 1사이의 숫자를 랜덤 생성
|
||||
r0 = np.random.rand()
|
||||
r1 = np.random.rand()
|
||||
# p_best = np.array(p_best)
|
||||
# g_best = np.array(g_best)
|
||||
|
||||
# 가중치(상수)*속도 + \
|
||||
# 스케일링 상수*랜덤 가중치*(나의 최적값 - 처음 위치) + \
|
||||
# 전역 스케일링 상수*랜덤 가중치*(전체 최적값 - 처음 위치)
|
||||
new_velocity = [None] * len(weights)
|
||||
for i, layer in enumerate(weights):
|
||||
|
||||
new_v = w * v[i]
|
||||
new_v = new_v + c0 * r0 * (p_best[i] - layer)
|
||||
new_v = new_v + c1 * r1 * (self.g_best[i] - layer)
|
||||
new_velocity[i] = new_v
|
||||
|
||||
# new_v = w*v + c0*r0*(p_best - weights) + c1*r1*(g_best - weights)
|
||||
return new_velocity
|
||||
|
||||
def _get_score(self, x, y):
|
||||
"""
|
||||
Compute the score of the current position of the particles.
|
||||
|
||||
Args:
|
||||
x (array-like): The current position of the particles
|
||||
y (array-like): The current position of the particles
|
||||
Returns:
|
||||
(array-like) : 추론에 대한 점수
|
||||
"""
|
||||
score = self.model.evaluate(x, y, verbose=0)
|
||||
|
||||
return score
|
||||
|
||||
def optimize(self, x_, y_, maxiter=10, c0=0.5, c1=1.5, w=0.75):
|
||||
"""
|
||||
Run the PSO optimization process utill the stoping critera is met.
|
||||
Cas for minization. The aim is to minimize the cost function
|
||||
|
||||
Args:
|
||||
maxiter (int): the maximum number of iterations before stopping the optimization
|
||||
파티클의 최종 위치를 위한 반복 횟수
|
||||
Returns:
|
||||
The best solution found (array-like)
|
||||
"""
|
||||
for _ in range(maxiter):
|
||||
|
||||
for i in tqdm(
|
||||
range(self.n_particles), desc=f"Iter {_}/{maxiter} ", ascii=True
|
||||
):
|
||||
weights = self.particles_weights[i] # 각 파티클 추출
|
||||
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
||||
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
||||
# 2. 속도 계산
|
||||
self.velocities[i] = self._update_velocity(
|
||||
weights, v, p_best, c0, c1, w
|
||||
)
|
||||
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
||||
# 3. 위치 업데이트
|
||||
self.particles_weights[i] = self._update_weights(weights, v)
|
||||
# 현재 위치 = 이전 위치 + 현재 속도
|
||||
# 내 현재 위치가 내 위치의 최소치보다 작으면 갱신
|
||||
self.model.set_weights(self.particles_weights[i].copy())
|
||||
# self.particles_weights[i] = self.model.get_weights()
|
||||
# 4. 평가
|
||||
self.model.compile(
|
||||
loss=self.loss_method, optimizer="adam", metrics=["accuracy"]
|
||||
)
|
||||
score = self._get_score(x_, y_)
|
||||
|
||||
if score[1] > self.p_best_score[i]:
|
||||
self.p_best_score[i] = score[1]
|
||||
self.p_best[i] = self.particles_weights[i].copy()
|
||||
if score[1] > self.g_best_score:
|
||||
self.g_best_score = score[1]
|
||||
self.g_best = self.particles_weights[i].copy()
|
||||
self.g_best_score_history.append(self.g_best_score)
|
||||
|
||||
self.loss_history[i].append(score[0])
|
||||
self.acc_history[i].append(score[1])
|
||||
|
||||
print(
|
||||
f"loss avg : {score[0]/self.n_particles} | acc avg : {score[1]/self.n_particles} | best score : {self.g_best_score}"
|
||||
)
|
||||
|
||||
# 전체 최소 위치, 전체 최소 벡터
|
||||
return self.g_best, self._get_score(x_, y_)
|
||||
|
||||
"""
|
||||
Returns:
|
||||
최종 가중치
|
||||
"""
|
||||
|
||||
def best_weights(self):
|
||||
return self.g_best
|
||||
|
||||
"""
|
||||
Returns:
|
||||
최종 가중치의 스코어
|
||||
"""
|
||||
|
||||
def best_score(self):
|
||||
return self.g_best_score
|
||||
|
||||
"""
|
||||
Returns:
|
||||
global best score 의 갱신된 값의 변화를 반환
|
||||
"""
|
||||
|
||||
def global_score_history(self):
|
||||
return self.g_best_score_history.copy()
|
||||
|
||||
"""
|
||||
Returns:
|
||||
모든 파티클의 손실값과 정확도의 변화를 반환
|
||||
"""
|
||||
|
||||
def all_history(self):
|
||||
return self.loss_history, self.acc_history.copy()
|
||||
Reference in New Issue
Block a user