├── .gitignore ├── .vscode └── tags ├── LICENSE ├── README.md ├── example.py ├── greytheory ├── __init__.py └── packages │ ├── __init__.py │ ├── libs │ ├── __init__.py │ ├── grey_lib.py │ └── grey_math.py │ └── models │ ├── __init__.py │ ├── grey_class.py │ ├── grey_factory.py │ ├── grey_forecast.py │ ├── grey_gm0n.py │ ├── grey_gm11.py │ ├── grey_gm1n.py │ └── grey_run.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | *.pyc 4 | greytheory.egg-info 5 | -------------------------------------------------------------------------------- /.vscode/tags: -------------------------------------------------------------------------------- 1 | !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ 2 | !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ 3 | !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ 4 | !_TAG_PROGRAM_NAME Exuberant Ctags // 5 | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ 6 | !_TAG_PROGRAM_VERSION 5.8 // 7 | GreyClass ../packages/models/grey_class.py /^class GreyClass (object):$/;" kind:class line:7 8 | GreyFactory ../packages/models/grey_class.py /^from grey_factory import GreyFactory$/;" kind:namespace line:4 9 | GreyFactory ../packages/models/grey_factory.py /^class GreyFactory:$/;" kind:class line:2 10 | GreyForecast ../packages/models/grey_class.py /^from grey_forecast import GreyForecast$/;" kind:namespace line:5 11 | GreyForecast ../packages/models/grey_forecast.py /^class GreyForecast:$/;" kind:class line:2 12 | GreyGM0N ../grey_theory.py /^from packages.models.grey_gm0n import GreyGM0N$/;" kind:namespace line:1 13 | GreyGM0N ../packages/models/grey_gm0n.py /^class GreyGM0N (GreyClass):$/;" kind:class line:3 14 | GreyGM11 ../grey_theory.py /^from packages.models.grey_gm11 import GreyGM11$/;" kind:namespace line:3 15 | GreyGM11 ../packages/models/grey_gm11.py /^class GreyGM11 (GreyClass):$/;" kind:class line:4 16 | GreyGM1N ../grey_theory.py /^from packages.models.grey_gm1n import GreyGM1N$/;" kind:namespace line:2 17 | GreyGM1N ../packages/models/grey_gm1n.py /^class GreyGM1N (GreyClass):$/;" kind:class line:3 18 | GreyLib ../packages/libs/grey_lib.py /^class GreyLib:$/;" kind:class line:3 19 | GreyLib ../packages/models/grey_class.py /^from ..libs.grey_lib import GreyLib$/;" kind:namespace line:2 20 | GreyMath ../packages/libs/grey_math.py /^class GreyMath:$/;" kind:class line:3 21 | GreyMath ../packages/models/grey_class.py /^from ..libs.grey_math import GreyMath$/;" kind:namespace line:3 22 | GreyTheory ../example.py /^from grey_theory import GreyTheory$/;" kind:namespace line:1 23 | GreyTheory ../grey_theory.py /^class GreyTheory:$/;" kind:class line:5 24 | _TAG_FORECAST_HISTORY ../packages/models/grey_class.py /^ _TAG_FORECAST_HISTORY = "history"$/;" kind:variable line:10 25 | _TAG_FORECAST_NEXT_MOMENT ../packages/models/grey_class.py /^ _TAG_FORECAST_NEXT_MOMENT = "forecasted_next_moment"$/;" kind:variable line:9 26 | __forecast ../packages/models/grey_gm11.py /^ def __forecast(self, patterns, period=1):$/;" kind:member line:16 27 | __forecast_value ../packages/models/grey_gm11.py /^ def __forecast_value(self, x1, a_value, b_value, k):$/;" kind:member line:13 28 | __init__ ../grey_theory.py /^ def __init__(self):$/;" kind:member line:6 29 | __init__ ../packages/libs/grey_lib.py /^ def __init__(self, alpha=0.5):$/;" kind:member line:5 30 | __init__ ../packages/models/grey_class.py /^ def __init__(self):$/;" kind:member line:12 31 | __init__ ../packages/models/grey_gm11.py /^ def __init__(self):$/;" kind:member line:6 32 | __init__.py ../__init__.py 1;" kind:file line:1 33 | __init__.py ../packages/__init__.py 1;" kind:file line:1 34 | __init__.py ../packages/libs/__init__.py 1;" kind:file line:1 35 | __init__.py ../packages/models/__init__.py 1;" kind:file line:1 36 | _add_outputs ../packages/models/grey_class.py /^ def _add_outputs(self, outputs, pattern_key):$/;" kind:member line:21 37 | _add_patterns ../packages/models/grey_class.py /^ def _add_patterns(self, patterns, pattern_key):$/;" kind:member line:26 38 | add_outputs ../packages/models/grey_gm0n.py /^ def add_outputs(self, outputs, pattern_key):$/;" kind:member line:5 39 | add_outputs ../packages/models/grey_gm1n.py /^ def add_outputs(self, outputs, pattern_key):$/;" kind:member line:5 40 | add_pattern ../packages/models/grey_gm11.py /^ def add_pattern(self, pattern, pattern_key):$/;" kind:member line:10 41 | add_patterns ../packages/models/grey_gm0n.py /^ def add_patterns(self, patterns, pattern_key):$/;" kind:member line:8 42 | add_patterns ../packages/models/grey_gm1n.py /^ def add_patterns(self, patterns, pattern_key):$/;" kind:member line:8 43 | ago ../packages/libs/grey_lib.py /^ def ago(self, patterns):$/;" kind:member line:9 44 | ago ../packages/models/grey_class.py /^ def ago(self, patterns):$/;" kind:member line:30 45 | alpha ../packages/models/grey_class.py /^ def alpha(self):$/;" kind:member line:74 46 | alpha ../packages/models/grey_class.py /^ def alpha(self, value = 0.5):$/;" kind:member line:78 47 | analyze ../packages/models/grey_gm0n.py /^ def analyze(self):$/;" kind:member line:11 48 | analyze ../packages/models/grey_gm1n.py /^ def analyze(self):$/;" kind:member line:11 49 | average_error_rate ../packages/models/grey_forecast.py /^ average_error_rate = 0.0$/;" kind:variable line:9 50 | clean_forecasted ../packages/models/grey_gm11.py /^ def clean_forecasted(self):$/;" kind:member line:124 51 | continue_forecasting ../packages/models/grey_gm11.py /^ def continue_forecasting(self, last_forecasted_outputs = []):$/;" kind:member line:120 52 | equation_value ../packages/models/grey_factory.py /^ equation_value = ""$/;" kind:variable line:5 53 | error_rate ../packages/models/grey_forecast.py /^ error_rate = 0.0$/;" kind:variable line:8 54 | example.py ../example.py 1;" kind:file line:1 55 | forecast ../packages/models/grey_gm11.py /^ def forecast(self, period=1):$/;" kind:member line:75 56 | forecast_convolution ../packages/models/grey_gm11.py /^ def forecast_convolution(self, stride=1, length=4):$/;" kind:member line:80 57 | forecast_value ../packages/models/grey_forecast.py /^ forecast_value = 0.0$/;" kind:variable line:7 58 | gm0n ../example.py /^gm0n = grey.gm0n$/;" kind:variable line:6 59 | gm11 ../example.py /^gm11 = grey.gm11$/;" kind:variable line:36 60 | gm1n ../example.py /^gm1n = grey.gm1n$/;" kind:variable line:21 61 | grey ../example.py /^grey = GreyTheory()$/;" kind:variable line:3 62 | grey_class.py ../packages/models/grey_class.py 1;" kind:file line:1 63 | grey_factory.py ../packages/models/grey_factory.py 1;" kind:file line:1 64 | grey_forecast.py ../packages/models/grey_forecast.py 1;" kind:file line:1 65 | grey_gm0n.py ../packages/models/grey_gm0n.py 1;" kind:file line:1 66 | grey_gm11.py ../packages/models/grey_gm11.py 1;" kind:file line:1 67 | grey_gm1n.py ../packages/models/grey_gm1n.py 1;" kind:file line:1 68 | grey_lib.py ../packages/libs/grey_lib.py 1;" kind:file line:1 69 | grey_math.py ../packages/libs/grey_math.py 1;" kind:file line:1 70 | grey_theory.py ../grey_theory.py 1;" kind:file line:1 71 | k ../packages/models/grey_forecast.py /^ k = 0$/;" kind:variable line:5 72 | last_moment ../packages/models/grey_gm11.py /^ def last_moment(self):$/;" kind:member line:128 73 | math ../packages/models/grey_gm11.py /^import math$/;" kind:namespace line:2 74 | name ../packages/models/grey_factory.py /^ name = ""$/;" kind:variable line:4 75 | np ../packages/libs/grey_lib.py /^import numpy as np$/;" kind:namespace line:1 76 | np ../packages/libs/grey_math.py /^import numpy as np$/;" kind:namespace line:1 77 | np ../packages/models/grey_class.py /^import numpy as np$/;" kind:namespace line:1 78 | original_value ../packages/models/grey_forecast.py /^ original_value = 0.0$/;" kind:variable line:6 79 | print_analyzed_results ../packages/models/grey_class.py /^ def print_analyzed_results(self):$/;" kind:member line:47 80 | print_forecasted_results ../packages/models/grey_class.py /^ def print_forecasted_results(self):$/;" kind:member line:57 81 | print_influence_degrees ../packages/models/grey_class.py /^ def print_influence_degrees(self):$/;" kind:member line:52 82 | print_self ../packages/models/grey_class.py /^ def print_self(self):$/;" kind:member line:44 83 | ranking ../packages/models/grey_factory.py /^ ranking = ""$/;" kind:variable line:6 84 | remove_all_analysis ../packages/models/grey_class.py /^ def remove_all_analysis(self):$/;" kind:member line:33 85 | solve_equations ../packages/libs/grey_math.py /^ def solve_equations(self, equations, equals):$/;" kind:member line:6 86 | tag ../packages/models/grey_forecast.py /^ tag = ""$/;" kind:variable line:4 87 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Kuo-Ming Lin (Kalvar Lin) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## About 2 | 3 | Grey Theory System that means uncertain relationships between the various factors within the system, this system in which part of information is known and another part is unknown. This theory has 3 methods are : GM0N, GM1N, GM11. 4 | 5 | [Grey Relational Analysis](https://en.wikipedia.org/wiki/Grey_relational_analysis)
6 | [灰色系統理論](http://wiki.mbalib.com/zh-tw/%E7%81%B0%E8%89%B2%E7%B3%BB%E7%BB%9F%E7%90%86%E8%AE%BA)
7 | [灰色關聯分析](http://wiki.mbalib.com/zh-tw/%E7%81%B0%E8%89%B2%E5%85%B3%E8%81%94%E5%88%86%E6%9E%90)
8 | [灰色預測法](http://wiki.mbalib.com/zh-tw/%E7%81%B0%E8%89%B2%E9%A2%84%E6%B5%8B%E6%B3%95)
9 | [《Grey system theory-based models in time series prediction》2009.](http://www.mecha.ee.boun.edu.tr/Prof.%20Dr.%20Okyay%20Kaynak%20Publications/c%20Journal%20Papers(appearing%20in%20SCI%20or%20SCIE%20or%20CompuMath)/62.pdf)
10 | [改良式 GM(1,1)灰預測模型於台電電量需求預測之研究](http://www.engh.kuas.edu.tw/files/ne/pnz67gteh2.pdf) 11 | 12 | ## How to Install 13 | Now install version is 0.1. 14 | ```console 15 | pip3 install greytheory 16 | ``` 17 | 18 | ## How to Use 19 | 20 | #### Import 21 | ``` python 22 | from greytheory import GreyTheory 23 | grey = GreyTheory() 24 | ``` 25 | 26 | #### GM0N 27 | ``` python 28 | 29 | gm0n = grey.gm0n 30 | 31 | gm0n.add_outputs([1., 1., 1., 1., 1., 1.], "x1") 32 | gm0n.add_patterns([.75, 1.22, .2, 1., 1., 1.], "x2") 33 | gm0n.add_patterns([.5, 1., .7, .66, 1., .5], "x3") 34 | gm0n.add_patterns([1., 1.09, .4, .33, .66, .25], "x4") 35 | gm0n.add_patterns([.25, .99, 1., .66, .33, .25], "x5") 36 | 37 | gm0n.analyze() 38 | 39 | # Looks GM0N the results as below: 40 | gm0n.print_analyzed_results() 41 | """ 42 | Pattern key: 'x3', grey value: 0.745169986457907, ranking: 1 43 | Pattern key: 'x4', grey value: 0.5714064714568454, ranking: 2 44 | Pattern key: 'x2', grey value: 0.501334367966725, ranking: 3 45 | Pattern key: 'x5', grey value: 0.49555636151070015, ranking: 4 46 | """ 47 | 48 | gm0n.print_influence_degrees() 49 | """ 50 | The keys of parameters their influence degrees (ordering): 'x3 > x4 > x2 > x5' 51 | """ 52 | ``` 53 | 54 | #### GM1N 55 | ``` python 56 | gm1n = grey.gm1n 57 | 58 | gm1n.add_outputs([2., 11., 1.5, 2., 2.2, 3.], "x1") 59 | gm1n.add_patterns([3., 13.5, 1., 3., 3., 4.], "x2") 60 | gm1n.add_patterns([2., 11., 3.5, 2., 3., 2.], "x3") 61 | gm1n.add_patterns([4., 12., 2., 1., 2., 1.], "x4") 62 | gm1n.add_patterns([1., 10., 5., 2., 1., 1.], "x5") 63 | 64 | gm1n.analyze() 65 | 66 | # Looks GM1N the results as below: 67 | gm1n.print_analyzed_results() 68 | """ 69 | Pattern key: 'x1', grey value: 1.4385641363407546, ranking: 0 70 | Pattern key: 'x2', grey value: 1.3300049398977922, ranking: 1 71 | Pattern key: 'x4', grey value: 0.6084241725675539, ranking: 2 72 | Pattern key: 'x3', grey value: 0.5977013008400084, ranking: 3 73 | Pattern key: 'x5', grey value: 0.19277457599259723, ranking: 4 74 | """ 75 | 76 | gm1n.print_influence_degrees() 77 | """ 78 | The keys of parameters their influence degrees (ordering): 'x2 > x4 > x3 > x5' 79 | """ 80 | ``` 81 | 82 | #### GM11 83 | ``` python 84 | gm11 = grey.gm11 85 | 86 | gm11.add_pattern(223.3, "a1") 87 | gm11.add_pattern(227.3, "a2") 88 | gm11.add_pattern(230.5, "a3") 89 | gm11.add_pattern(238.1, "a4") 90 | gm11.add_pattern(242.9, "a5") 91 | gm11.add_pattern(251.1, "a6") 92 | 93 | gm11.period = 2 # Default is 1, the parameter means how many next moments need to forcast continually. 94 | gm11.forecast() 95 | 96 | # Looks GM11 the results for example as below: 97 | gm11.print_forecasted_results() 98 | """ 99 | K = 1 100 | From original value 227.3 to forecasted value is 226.08736263692822 101 | The error rate is 0.005334964201811667 102 | K = 2 103 | From original value 230.5 to forecasted value is 231.87637984134398 104 | The error rate is 0.005971279138151739 105 | K = 3 106 | From original value 238.1 to forecasted value is 237.81362611881437 107 | The error rate is 0.0012027462460547044 108 | K = 4 109 | From original value 242.9 to forecasted value is 243.9028969077225 110 | The error rate is 0.00412884688234865 111 | K = 5 112 | From original value 251.1 to forecasted value is 250.14808482949547 113 | The error rate is 0.003790980368397134 114 | K = 6 115 | Forcated next moment value is 256.55318217699795 116 | K = 7 117 | Forcated next moment value is 263.1222834666411 118 | Forcated next moment value is 283.85614494317775 119 | The average error rate 0.0040857633673527785 120 | """ 121 | ``` 122 | 123 | #### GM11 Convolutional Forecasting 124 | ``` python 125 | gm11.convolution = True # To open convolution mode. 126 | gm11.stride = 1 127 | gm11.length = 4 128 | 129 | gm11.add_pattern(223.3, "a1") 130 | gm11.add_pattern(227.3, "a2") 131 | gm11.add_pattern(230.5, "a3") 132 | gm11.add_pattern(238.1, "a4") 133 | gm11.add_pattern(242.9, "a5") 134 | gm11.add_pattern(251.1, "a6") 135 | 136 | gm11.forecast() 137 | ``` 138 | 139 | #### Alpha for Z 140 | ``` python 141 | # For example, if you wanna customize alpha value to reduce error-rate of prediction before calculate AGO, 142 | # Directly try to setup the alpha value before start .analyze() and .forecast(). 143 | gm11.alpha = 0.8 144 | gm11.add_pattern() 145 | gm11.forecast() 146 | ``` 147 | 148 | #### Multi-Processing 149 | 1. Put objects of gm0n, gm1n or gm11 into their own arrays.
150 | 2. Run specific functions are: grey.run.gm0n(array), grey.run.gm1n(array) or grey.run.gm11(array).
151 | 3. Enumerate the arrays, or enumerate .run.gm0n(), .run.gm1n() and .run.gm11() they returned arrays. 152 | ``` python 153 | # multiprocessing examples: 154 | # for GM0N, GM1N 155 | queue = [] 156 | queue.append(gm0n.deepcopy()) 157 | queue.append(gm0n.deepcopy()) 158 | queue.append(gm0n.deepcopy()) 159 | queue.append(gm0n.deepcopy()) 160 | queue.append(gm0n.deepcopy()) 161 | queue.append(gm0n.deepcopy()) 162 | queue.append(gm0n.deepcopy()) 163 | 164 | grey.run.gm0n(queue) 165 | 166 | for gm in queue: 167 | gm.print_influence_degrees() 168 | ``` 169 | 170 | ``` python 171 | # for GM11 172 | gm11_queue = [] 173 | gm11_queue.append(gm11.deepcopy()) 174 | gm11_queue.append(gm11.deepcopy()) 175 | gm11_queue.append(gm11.deepcopy()) 176 | gm11_queue.append(gm11.deepcopy()) 177 | gm11_queue.append(gm11.deepcopy()) 178 | gm11_queue.append(gm11.deepcopy()) 179 | gm11_queue.append(gm11.deepcopy()) 180 | 181 | grey.run.gm11(gm11_queue) 182 | 183 | for gm in gm11_queue: 184 | gm.print_forecasted_results() 185 | ``` 186 | 187 | ## Version 188 | 189 | V1.3.1 190 | 191 | ## LICENSE 192 | 193 | MIT. 194 | 195 | ## Note 196 | 197 | 卷積的部份,是跑 2 層的 GM11:
198 |
    1 -> 2 -> 3, 預測 4
199 |
    2 -> 3 -> 4, 預測 5
200 |
    3 -> 4 -> 5, 預測 6
201 |
    ... 其餘類推
202 |
203 | 之後會把預測 4,5,6 再丟進去 GM11 跑最終結果。等於是先做一次特徵提取,第 1 層提取每一個區間的預測輸出,再對這預測輸出做平均誤差的修正,而後再丟入第 2 層的 GM11 去做總輸出。 204 | -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from greytheory import GreyTheory 5 | 6 | grey = GreyTheory() 7 | 8 | 9 | # GM0N 10 | gm0n = grey.gm0n 11 | 12 | gm0n.add_outputs([1., 1., 1., 1., 1., 1.], "x1") 13 | gm0n.add_patterns([.75, 1.22, .2, 1., 1., 1.], "x2") 14 | gm0n.add_patterns([.5, 1., .7, .66, 1., .5], "x3") 15 | gm0n.add_patterns([1., 1.09, .4, .33, .66, .25], "x4") 16 | gm0n.add_patterns([.25, .99, 1., .66, .33, .25], "x5") 17 | 18 | gm0n.analyze() 19 | 20 | # Looks GM0N the results as below: 21 | gm0n.print_analyzed_results() 22 | gm0n.print_influence_degrees() 23 | 24 | # GM1N 25 | gm1n = grey.gm1n 26 | 27 | gm1n.add_outputs([2., 11., 1.5, 2., 2.2, 3.], "x1") 28 | gm1n.add_patterns([3., 13.5, 1., 3., 3., 4.], "x2") 29 | gm1n.add_patterns([2., 11., 3.5, 2., 3., 2.], "x3") 30 | gm1n.add_patterns([4., 12., 2., 1., 2., 1.], "x4") 31 | gm1n.add_patterns([1., 10., 5., 2., 1., 1.], "x5") 32 | 33 | gm1n.analyze() 34 | 35 | # Looks GM1N the results as below: 36 | gm1n.print_analyzed_results() 37 | gm1n.print_influence_degrees() 38 | 39 | # GM11 40 | gm11 = grey.gm11 41 | 42 | # To try customized alpha for IAGO of Z. 43 | gm11.alpha = 0.5 44 | gm11.convolution = True # Convolutional forecasting of GM11. 45 | gm11.stride = 1 46 | gm11.length = 4 47 | 48 | # gm11.add_pattern(533.0, "x1") 49 | # gm11.add_pattern(665.0, "x2") 50 | # gm11.add_pattern(655.0, "x3") 51 | # gm11.add_pattern(740.0, "x4") 52 | 53 | gm11.add_pattern(223.3, "a1") 54 | gm11.add_pattern(227.3, "a2") 55 | gm11.add_pattern(230.5, "a3") 56 | gm11.add_pattern(238.1, "a4") 57 | gm11.add_pattern(242.9, "a5") 58 | gm11.add_pattern(251.1, "a6") 59 | 60 | gm11.forecast() 61 | 62 | # To record last forecasted result. 63 | #last_forecasted_results = gm11.forecasted_outputs 64 | 65 | # To clean all forecasted results. 66 | #gm11.clean_forecasted() 67 | 68 | # In next iteration of forecasting, we wanna continue use last forecasted results to do next forecasting, 69 | # but if we removed gm11.forecasted_outputs list before, 70 | # we can use continue_forecasting() to extend / recall the last for ecasted result come back to be convolutional features. 71 | #gm11.continue_forecasting(last_forecasted_results) 72 | 73 | # Looks GM11 the results for example as below: 74 | gm11.print_forecasted_results() 75 | 76 | """ 77 | # multiprocessing examples: 78 | # for GM0N, GM1N 79 | queue = [] 80 | queue.append(gm0n.deepcopy()) 81 | queue.append(gm0n.deepcopy()) 82 | queue.append(gm0n.deepcopy()) 83 | queue.append(gm0n.deepcopy()) 84 | queue.append(gm0n.deepcopy()) 85 | queue.append(gm0n.deepcopy()) 86 | queue.append(gm0n.deepcopy()) 87 | 88 | grey.run.gm0n(queue) 89 | 90 | for gm in queue: 91 | gm.print_influence_degrees() 92 | 93 | # for GM11 94 | gm11_queue = [] 95 | gm11_queue.append(gm11.deepcopy()) 96 | gm11_queue.append(gm11.deepcopy()) 97 | gm11_queue.append(gm11.deepcopy()) 98 | gm11_queue.append(gm11.deepcopy()) 99 | gm11_queue.append(gm11.deepcopy()) 100 | gm11_queue.append(gm11.deepcopy()) 101 | gm11_queue.append(gm11.deepcopy()) 102 | 103 | grey.run.gm11(gm11_queue) 104 | 105 | for gm in gm11_queue: 106 | gm.print_forecasted_results() 107 | 108 | """ 109 | -------------------------------------------------------------------------------- /greytheory/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .packages.models.grey_gm0n import GreyGM0N 3 | from .packages.models.grey_gm1n import GreyGM1N 4 | from .packages.models.grey_gm11 import GreyGM11 5 | from .packages.models.grey_run import GreyRun 6 | 7 | __version__ = "0.1" 8 | 9 | class GreyTheory: 10 | def __init__(self): 11 | self.gm0n = GreyGM0N() 12 | self.gm1n = GreyGM1N() 13 | self.gm11 = GreyGM11() 14 | self.run = GreyRun() -------------------------------------------------------------------------------- /greytheory/packages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kalvar/python-GreyTheory/820ee5764dda51a94a335921a125b329a0950b7c/greytheory/packages/__init__.py -------------------------------------------------------------------------------- /greytheory/packages/libs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kalvar/python-GreyTheory/820ee5764dda51a94a335921a125b329a0950b7c/greytheory/packages/libs/__init__.py -------------------------------------------------------------------------------- /greytheory/packages/libs/grey_lib.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class GreyLib: 4 | 5 | def __init__(self, alpha=0.5): 6 | self.alpha = alpha 7 | 8 | # Generates AGO via patterns. 9 | def ago(self, patterns): 10 | # do ago 11 | ago_boxes = [] #np.array([], dtype=np.float) 12 | z_boxes = [] 13 | pattern_index = 0 14 | # x1 which is index 0 the output, x2 ~ xn are the inputs. 15 | for x_patterns in patterns: 16 | x_ago = [] 17 | sum = 0.0 18 | z_value = 0.0 19 | x_index = 0 20 | for x_value in x_patterns: 21 | sum += x_value 22 | x_ago.append(sum) 23 | # Only first pattern need to calculate the Z value. 24 | if pattern_index == 0 and x_index > 0: 25 | # Alpha 0.5 that means z is mean value, others alpha number means z is IAGO. 26 | z_value = (self.alpha * sum) + (self.alpha * x_ago[x_index - 1]) 27 | z_boxes.append(z_value) 28 | x_index += 1 29 | ago_boxes.append(x_ago) 30 | pattern_index += 1 31 | 32 | return (ago_boxes, z_boxes) 33 | 34 | -------------------------------------------------------------------------------- /greytheory/packages/libs/grey_math.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class GreyMath: 4 | 5 | # Least Squares Method (LSM) to solve the equations, solves that simultaneous equations. 6 | def solve_equations(self, equations, equals): 7 | # Formula is ( B^T x B )^-1 x B^T x Yn, to be a square matrix first. 8 | transposed_equations = np.asarray(equations).T.tolist() 9 | # Doing ( B^T x B ) 10 | square_matrix = np.dot(transposed_equations, equations) 11 | # Doing (B^T x Yn) 12 | bx_y = np.dot(transposed_equations, equals) 13 | # Solves equations. 14 | return np.linalg.solve(square_matrix, bx_y).tolist() 15 | -------------------------------------------------------------------------------- /greytheory/packages/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kalvar/python-GreyTheory/820ee5764dda51a94a335921a125b329a0950b7c/greytheory/packages/models/__init__.py -------------------------------------------------------------------------------- /greytheory/packages/models/grey_class.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import copy 5 | import numpy as np 6 | from ..libs.grey_lib import GreyLib 7 | from ..libs.grey_math import GreyMath 8 | from .grey_factory import GreyFactory 9 | from .grey_forecast import GreyForecast 10 | 11 | class GreyClass (object): 12 | 13 | _TAG_FORECAST_NEXT_MOMENT = "forecasted_next_moment" 14 | _TAG_FORECAST_HISTORY = "history" 15 | 16 | def __init__(self): 17 | self.tag = self.__class__.__name__ 18 | self.patterns = [] 19 | self.keys = [] 20 | self.analyzed_results = [] 21 | self.influence_degrees = [] 22 | self.grey_lib = GreyLib() 23 | self.grey_math = GreyMath() 24 | 25 | # Those outputs are the results of all patterns. 26 | def _add_outputs(self, outputs, pattern_key): 27 | self.patterns.insert(0, outputs) 28 | self.keys.append(pattern_key) 29 | 30 | # Those patterns are using in AGO generator. 31 | def _add_patterns(self, patterns, pattern_key): 32 | self.patterns.append(patterns) 33 | self.keys.append(pattern_key) 34 | 35 | def ago(self, patterns): 36 | return self.grey_lib.ago(patterns) 37 | 38 | def remove_all_analysis(self): 39 | # Deeply removing without others copied array. 40 | self.analyzed_results = [] 41 | self.influence_degrees = [] 42 | self.forecasts = [] 43 | 44 | # Removing all reference links with others array. 45 | #del self.analyzed_results 46 | #del self.influence_degrees 47 | #del self.forecasts 48 | 49 | def print_self(self): 50 | print("%r" % self.__class__.__name__) 51 | 52 | def print_analyzed_results(self): 53 | self.print_self() 54 | for factory in self.analyzed_results: 55 | print("Pattern key: %r, grey value: %r, ranking: %r" % (factory.name, factory.equation_value, factory.ranking)) 56 | 57 | def print_influence_degrees(self): 58 | self.print_self() 59 | string = " > ".join(self.influence_degrees) 60 | print("The keys of parameters their influence degrees (ordering): %r" % string) 61 | 62 | def print_forecasted_results(self): 63 | self.print_self() 64 | for forecast in self.analyzed_results: 65 | print("K = %r" % forecast.k) 66 | if forecast.tag == self._TAG_FORECAST_HISTORY: 67 | # History. 68 | print("From original value %r to forecasted value is %r" % (forecast.original_value, forecast.forecast_value)) 69 | print("The error rate is %r" % forecast.error_rate) 70 | else: 71 | # Next moments. 72 | print("Forcated next moment value is %r" % forecast.forecast_value) 73 | 74 | # Last forecasted moment. 75 | last_moment = self.analyzed_results[-1] 76 | print("The average error rate %r" % last_moment.average_error_rate) 77 | 78 | def deepcopy(self): 79 | return copy.deepcopy(self) 80 | 81 | @property 82 | def alpha(self): 83 | return self.grey_lib.alpha 84 | 85 | @alpha.setter 86 | def alpha(self, value = 0.5): 87 | self.grey_lib.alpha = value -------------------------------------------------------------------------------- /greytheory/packages/models/grey_factory.py: -------------------------------------------------------------------------------- 1 | 2 | class GreyFactory: 3 | 4 | name = "" 5 | equation_value = "" 6 | ranking = "" 7 | -------------------------------------------------------------------------------- /greytheory/packages/models/grey_forecast.py: -------------------------------------------------------------------------------- 1 | 2 | class GreyForecast: 3 | 4 | tag = "" 5 | k = 0 6 | original_value = 0.0 7 | forecast_value = 0.0 8 | error_rate = 0.0 9 | average_error_rate = 0.0 10 | 11 | 12 | -------------------------------------------------------------------------------- /greytheory/packages/models/grey_gm0n.py: -------------------------------------------------------------------------------- 1 | from .grey_class import * 2 | 3 | class GreyGM0N (GreyClass): 4 | 5 | def add_outputs(self, outputs, pattern_key): 6 | self._add_outputs(outputs, pattern_key) 7 | 8 | def add_patterns(self, patterns, pattern_key): 9 | self._add_patterns(patterns, pattern_key) 10 | 11 | def analyze(self): 12 | self.remove_all_analysis() 13 | 14 | ago = self.ago(self.patterns) 15 | ago_boxes = ago[0] 16 | z_boxes = ago[1] # X 17 | 18 | # Fetchs ago matrixes after x2[1] (ago_boxes[1]) then transpose them. 19 | factors = np.asarray(ago_boxes[1:len(ago_boxes)]).T.tolist() 20 | grey_equations = factors[1:len(factors)] # Y 21 | 22 | # all_factors are the equations (x, y, z ...) and z_boxes are the goals of equations. 23 | solved_equations = self.grey_math.solve_equations(grey_equations, z_boxes) # B 24 | 25 | # Desc sorting the abs() equation values 26 | sorts = [] 27 | length = len(solved_equations) 28 | for i in range(0, length): 29 | equation_value = abs(solved_equations[i]) 30 | factory_info = {} 31 | equation_name = self.keys[i+1] # The keys of patterns are start in index 1, the index 0 is key of output-goal. 32 | grey_factory = GreyFactory() 33 | grey_factory.name = equation_name 34 | grey_factory.equation_value = equation_value 35 | sorts.append(grey_factory) 36 | 37 | # DESC 38 | # key=lambda d: d["equation_value"] 39 | self.analyzed_results = sorted(sorts, key=lambda factory: factory.equation_value, reverse=True) 40 | # Ranking all grey factories and setup their influence degrees step by step. 41 | ranking = 0 42 | for grey_factory in self.analyzed_results: 43 | ranking += 1 44 | grey_factory.ranking = ranking 45 | self.influence_degrees.append(grey_factory.name) 46 | #print "gm0n %r" % grey_factory.name 47 | 48 | 49 | -------------------------------------------------------------------------------- /greytheory/packages/models/grey_gm11.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from .grey_class import * 5 | import math 6 | 7 | class GreyGM11 (GreyClass): 8 | 9 | def __init__(self): 10 | super(GreyGM11, self).__init__() # Calling super object __init__ 11 | self.forecasted_outputs = [] 12 | self.stride = 1 13 | self.length = 4 14 | self.period = 1 # Default is 1, the parameter means how many next moments need to forcast continually. 15 | self.convolution = False 16 | 17 | def add_pattern(self, pattern, pattern_key): 18 | self._add_patterns(pattern, pattern_key) 19 | 20 | def __forecast_value(self, x1, a_value, b_value, k): 21 | return (1 - math.exp(a_value)) * (x1 - (b_value / a_value)) * math.exp(-a_value * k) 22 | 23 | def __forecast(self, patterns, period=1): 24 | self.remove_all_analysis() 25 | ago = self.ago([patterns]) 26 | z_boxes = ago[1] 27 | # Building B matrix, manual transpose z_boxes and add 1.0 to every sub-object. 28 | factors = [] 29 | for z in z_boxes: 30 | x_t = [] 31 | # Add negative z 32 | x_t.append(-z) 33 | x_t.append(1.0) 34 | factors.append(x_t) 35 | 36 | # Building Y matrix to be output-goals of equations. 37 | y_vectors = [] 38 | for passed_number in patterns[1::]: 39 | y_vectors.append(passed_number) 40 | 41 | solved_equations = self.grey_math.solve_equations(factors, y_vectors) 42 | # Then, forecasting them at all include next moment value. 43 | analyzed_results = [] 44 | sum_error = 0.0 45 | x1 = patterns[0] 46 | a_value = solved_equations[0] 47 | b_value = solved_equations[1] 48 | k = 1 49 | length = len(patterns) 50 | for passed_number in patterns[1::]: 51 | grey_forecast = GreyForecast() 52 | forecast_value = self.__forecast_value(x1, a_value, b_value, k) 53 | 54 | original_value = patterns[k] 55 | error_rate = abs((original_value - forecast_value) / original_value) 56 | sum_error += error_rate 57 | grey_forecast.tag = self._TAG_FORECAST_HISTORY 58 | grey_forecast.k = k 59 | grey_forecast.original_value = original_value 60 | grey_forecast.forecast_value = forecast_value 61 | grey_forecast.error_rate = error_rate 62 | 63 | analyzed_results.append(grey_forecast) 64 | k += 1 65 | 66 | # Continuous forecasting next moments. 67 | if period > 0: 68 | for go_head in range(0, period): 69 | forecast_value = self.__forecast_value(x1, a_value, b_value, k) 70 | 71 | grey_forecast = GreyForecast() 72 | grey_forecast.tag = self._TAG_FORECAST_NEXT_MOMENT 73 | grey_forecast.k = k # This k means the next moment of forecasted. 74 | grey_forecast.average_error_rate = sum_error / (length - 1) 75 | grey_forecast.forecast_value = forecast_value 76 | analyzed_results.append(grey_forecast) 77 | k += 1 78 | 79 | self.analyzed_results = analyzed_results 80 | return analyzed_results 81 | 82 | # stride: the N-gram, shift step-size for each forecasting. 83 | # length: the Filter kernel, shift length of distance for each forecasting. 84 | def __forecast_convolution(self, patterns=[], stride=1, length=4): 85 | pattern_count = len(patterns) 86 | # Convolution formula: (pattern_count - length) / stride + 1, 87 | # e.g. (7 - 3) / 1 + 1 = 5 (Needs to shift 5 times.) 88 | # e.g. (7 - 3) / 3 + 1 = 2.33, to get floor() or ceil() 89 | # total_times at least for once. 90 | total_times = int(math.floor(float(pattern_count - length) / stride + 1)) 91 | convolutions = [] 92 | stride_index = 0 93 | for i in range(0, total_times): 94 | # If it is last convolution, we directly pick it all. 95 | stride_length = stride_index+length 96 | if i == total_times - 1: 97 | stride_length = len(patterns) 98 | 99 | convolution_patterns = patterns[stride_index:stride_length] 100 | period_forecasts = self.__forecast(convolution_patterns) 101 | convolutions.append(period_forecasts) 102 | 103 | # Fetchs forecasted moment and revises it to be fix with average error rate. 104 | forecasted_moment = period_forecasts[-1] 105 | forecasted_value = forecasted_moment.forecast_value 106 | revised_value = forecasted_value + (forecasted_value * forecasted_moment.average_error_rate) 107 | self.forecasted_outputs.append(revised_value) 108 | 109 | # Next stride start index. 110 | stride_index += stride 111 | 112 | #print "forecasted_outputs % r" % self.forecasted_outputs 113 | 114 | # Using extracted convolution that forecasted values to do final forecasting. 115 | if total_times > 1: 116 | self.__forecast(self.forecasted_outputs) 117 | self.forecasted_outputs.append(self.last_moment) 118 | 119 | return convolutions 120 | 121 | # period: 連續預測多長的時間區間, default: 只預測下一刻 122 | def forecast(self): 123 | if self.convolution == True: 124 | return self.__forecast_convolution(self.patterns, self.stride, self.length) 125 | else: 126 | return self.__forecast(self.patterns, self.period) 127 | 128 | # In next iteration of forecasting, we wanna continue use last forecasted results to do next forecasting, 129 | # but if we removed gm11.forecasted_outputs list before, 130 | # we can use continue_forecasting() to extend / recall the last forecasted result come back to be convolutional features. 131 | def continue_forecasting(self, last_forecasted_outputs = []): 132 | self.forecasted_outputs.extend(last_forecasted_outputs) 133 | 134 | # Clean forecasted outputs. 135 | def clean_forecasted(self): 136 | self.forecasted_outputs = [] 137 | 138 | @property 139 | def last_moment(self): 140 | # Last GreyForecast() object is the next moment forecasted. 141 | return self.analyzed_results[-1].forecast_value 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /greytheory/packages/models/grey_gm1n.py: -------------------------------------------------------------------------------- 1 | from .grey_class import * 2 | 3 | class GreyGM1N (GreyClass): 4 | 5 | def add_outputs(self, outputs, pattern_key): 6 | self._add_outputs(outputs, pattern_key) 7 | 8 | def add_patterns(self, patterns, pattern_key): 9 | self._add_patterns(patterns, pattern_key) 10 | 11 | def analyze(self): 12 | self.remove_all_analysis() 13 | 14 | ago = self.ago(self.patterns) 15 | ago_boxes = ago[0] 16 | z_boxes = ago[1] 17 | 18 | # Fetchs from ago_boxes[1] to [last] then transpose it. 19 | factors = np.asarray(ago_boxes[1:len(ago_boxes)]).T.tolist() 20 | grey_equations = factors[1:len(factors)] 21 | # Then, to add -Z value from z_boxes into every sub-factors. 22 | index = -1 23 | for z_value in z_boxes: 24 | index += 1 25 | grey_equations[index].insert(0, -z_value) 26 | # Refactoring that x1 (the outputs) to be an output vector by following the Grey Theory GM(1, N) formula 27 | outputs = self.patterns[0][1::] 28 | solved_equations = self.grey_math.solve_equations(grey_equations, outputs) 29 | 30 | # Desc sorting the abs() equation values first, they named b(2) to b(n), but ignore the result (a) the output-goal factory in this loop 31 | sorts = [] 32 | goal_factory = GreyFactory() 33 | length = len(solved_equations) 34 | for i in range(0, length): 35 | equation_value = abs(solved_equations[i]) 36 | factory_info = {} 37 | equation_name = self.keys[i] 38 | grey_factory = GreyFactory() 39 | grey_factory.name = equation_name 40 | grey_factory.equation_value = equation_value 41 | if i > 0: 42 | sorts.append(grey_factory) 43 | else: 44 | goal_factory = grey_factory 45 | 46 | self.analyzed_results = sorted(sorts, key=lambda factory: factory.equation_value, reverse=True) 47 | self.analyzed_results.insert(0, goal_factory) # The output-goal always is first object in solved_equations array. 48 | ranking = -1 49 | for grey_factory in self.analyzed_results: 50 | ranking += 1 51 | grey_factory.ranking = ranking 52 | # Ranking 0 is the output-goal (a), the output-goal is not the influence degree, 53 | # Other paramenters are the real influence degrees of GM1N. 54 | if ranking > 0: 55 | self.influence_degrees.append(grey_factory.name) 56 | #print "gm1n %r" % grey_factory.name 57 | 58 | 59 | -------------------------------------------------------------------------------- /greytheory/packages/models/grey_run.py: -------------------------------------------------------------------------------- 1 | import multiprocessing as mp 2 | import math 3 | 4 | class GreyRun: 5 | 6 | def __init__(self): 7 | mp.freeze_support() # for windows 8 | self.cpu_count = mp.cpu_count() 9 | 10 | def _is_empty(self, array = []): 11 | return not bool(array) 12 | 13 | def _close_pool(self, pool): 14 | pool.close() 15 | pool.join() 16 | 17 | # multiprocessing 18 | def _execute_models(self, gmnn_queue=[], is_gm11=False): 19 | if self._is_empty(gmnn_queue): 20 | return [] 21 | pool = mp.Pool() 22 | cpu_count = self.cpu_count 23 | length = len(gmnn_queue) 24 | block_count = int(math.ceil(length / float(cpu_count))) 25 | start_index = 0 26 | end_length = cpu_count 27 | for block in xrange(0, block_count): 28 | for gm_model in gmnn_queue[start_index:end_length]: 29 | if is_gm11 == False: 30 | pool.apply_async(gm_model.analyze()) 31 | else: 32 | pool.apply_async(gm_model.forecast()) 33 | 34 | start_index += cpu_count 35 | end_length += cpu_count 36 | if end_length > length: 37 | end_length = length 38 | 39 | self._close_pool(pool) 40 | return gmnn_queue 41 | 42 | def gm0n(self, queue): 43 | return self._execute_models(queue) 44 | 45 | def gm1n(self, queue): 46 | return self._execute_models(queue) 47 | 48 | def gm11(self, queue): 49 | return self._execute_models(queue, True) 50 | 51 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("README.md", "r") as fh: 4 | long_description = fh.read() 5 | 6 | setuptools.setup( 7 | name="greytheory", 8 | version="0.1", 9 | author="Kalvar", 10 | author_email="ilovekalvar@gmail.com", 11 | description="Grey theory, implemented by python.", 12 | long_description=long_description, 13 | long_description_content_type="text/markdown", 14 | url="https://github.com/Kalvar/python-GreyTheory.git", 15 | packages=setuptools.find_packages(), 16 | classifiers=[ 17 | "Development Status :: 5 - Production/Stable", 18 | "Programming Language :: Python :: 3", 19 | "License :: OSI Approved :: MIT License", 20 | "Operating System :: OS Independent", 21 | ], 22 | python_requires='>=3.6', 23 | ) --------------------------------------------------------------------------------