我的一生模型构建

一、知识点

1.matplotlib图例legend语法及设置

loc 设置图例位置 其他用法参考

https://blog.csdn.net/helunqu2017/article/details/78641290

2.seek_choice = np.random.choice([0, 1, 2], 80000, p=weights)

是指以p([0.1, 0.2, 0.7])概率随机抽取seek_choice的[0,1,2]8000次,形成一个数组

seek_ind = seek_choice[2]提取数组第3个元素

3.n = numpy.random.random()  生成一个0~1随机的浮点数

weights/=np.sum(n)  依据上述生成的随机数生成比例

4.scipy 使用文档https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_bfgs.html

二、模型

from abcimport ABCMeta, abstractmethod

import matplotlib.pyplotas plt

import six

import numpyas np

import pandasas pd

from mpl_toolkits.mplot3dimport Axes3D

K_INIT_LIVING_DAYS =27375

class Person(object):

def __init__(self):

self.living = K_INIT_LIVING_DAYS

self.happiness =0

        self.wealth =0

        self.fame =0

        self.living_day =0

    def live_one_day(self, seek):

consume_living, happiness, wealth, fame = seek.do_seek_day()

self.living -=consume_living

self.happiness += happiness

self.wealth +=wealth

self.fame +=fame

self.living_day +=1

class BaseSeekDay(six.with_metaclass(ABCMeta, object)):

def __init__(self):

self.living_consume =0

        self.happiness_base =0

        self.wealth_base =0

        self.fame_base =0

        self.living_factor = [0]

self.happiness_factor = [0]

self.wealth_factor = [0]

self.fame_factor = [0]

self.do_seek_day_cnt =0

        self._init_self()

@abstractmethod

    def _init_self(self, *args, **kwargs):

pass

    @abstractmethod

    def _gen_living_days(self, *args, **kwargs):

pass

    def do_seek_day(self):

if self.do_seek_day_cnt >=len(self.living_factor):

# 超出len(self.living_factor), 就取最后一个living_factor[-1]

            consume_living = \

self.living_factor[-1] *self.living_consume

else:

# 每个类自定义这个追求的消耗生命常数,以及living_factor,比如

# HealthSeekDay追求健康,living_factor序列的值即由负值->正值

# 每个子类living_factor会有自己特点的变化速度及序列长度,导致每个

# 追求对生命的消耗随着追求的次数变化不一

            consume_living =self.living_factor[self.do_seek_day_cnt] \

*self.living_consume

# 幸福指数=happiness_base:幸福常数 * happiness_factor:可变序列

        if self.do_seek_day_cnt >=len(self.happiness_factor):

# 超出len(self.happiness_factor), 就取最后一个

# 由于happiness_factor值由:n—>0 所以happiness_factor[-1]=0

# 即随着追求一个事物的次数过多后会变的没有幸福感

            happiness =self.happiness_factor[-1] *self.happiness_base

else:

# 每个类自定义这个追求的幸福指数常数,以及happiness_factor

# happiness_factor子类的定义一般是从高->低变化

            happiness =self.happiness_factor[self.do_seek_day_cnt] *self.happiness_base

# 财富积累=wealth_base:积累常数 * wealth_factor:可变序列

        if self.do_seek_day_cnt >=len(self.wealth_factor):

# 超出len(self.wealth_factor), 就取最后一个

            wealth =self.wealth_factor[-1] *self.wealth_base

else:

# 每个类自定义这个追求的财富指数常数,以及wealth_factor

            wealth =self.wealth_factor[self.do_seek_day_cnt] *self.wealth_base

# 权利积累=fame_base:积累常数 * fame_factor:可变序列

        if self.do_seek_day_cnt >=len(self.fame_factor):

# 超出len(self.fame_factor), 就取最后一个

            fame =self.fame_factor[-1] *self.fame_base

else:

# 每个类自定义这个追求的名望权利指数常数,以及fame_factor

            fame =self.fame_factor[self.do_seek_day_cnt] *self.fame_base

# 追求了多少天了这一生 + 1

        self.do_seek_day_cnt +=1

        # 返回这个追求这一天对生命的消耗,得到的幸福,财富,名望权利

        return consume_living, happiness, wealth, fame

def regular_mm(group):

# 最小-最大规范化

    return (group - group.min()) / (group.max() - group.min())

class HealthSeekDay(BaseSeekDay):

"""

HealthSeekDay追求健康长寿的一天:

形象:健身,旅游,娱乐,做感兴趣的事情。

抽象:追求健康长寿。

"""

    def _init_self(self):

# 每天对生命消耗的常数=1,即代表1天

        self.living_consume =1

        # 每天幸福指数常数=1

        self.happiness_base =1

        # 设定可变因素序列

        self._gen_living_days()

def _gen_living_days(self):

# 只生成12000个序列,因为下面的happiness_factor序列值由1->0

# 所以大于12000次的追求都将只是单纯消耗生命,并不增加幸福指数

# 即随着做一件事情的次数越来越多,幸福感越来越低,直到完全体会不到幸福

        days = np.arange(1, 12000)

# 基础函数选用sqrt, 影响序列变化速度

        living_days = np.sqrt(days)

"""

对生命消耗可变因素序列值由-1->1, 也就是这个追求一开始的时候对生命

的消耗为负增长,延长了生命,随着追求的次数不断增多对生命的消耗转为正

数因为即使一个人天天锻炼身体,天天吃营养品,也还是会有自然死亡的那

一天

"""

        # *2-1的目的:regular_mm在0-1之间,HealthSeekDay要结果在-1,1之间

        self.living_factor = regular_mm(living_days) *2 -1

        # 结果在1-0之间 [::-1]: 将0->1转换到1->0

        self.happiness_factor = regular_mm(days)[::-1]

class StockSeekDay(BaseSeekDay):

"""

StockSeekDay追求财富金钱的一天:

形象:做股票投资赚钱的事情。

抽象:追求财富金钱

"""

    def _init_self(self, show=False):

# 每天对生命消耗的常数=2,即代表2天

        self.living_consume =2

        # 每天幸福指数常数=0.5

        self.happiness_base =0.5

        # 财富积累常数=10,默认=0

        self.wealth_base =10

        # 设定可变因素序列

        self._gen_living_days()

def _gen_living_days(self):

# 只生成10000个序列

        days = np.arange(1, 10000)

# 针对生命消耗living_factor的基础函数还是sqrt

        living_days = np.sqrt(days)

# 由于不需要像HealthSeekDay从负数开始,所以直接regular_mm 即:0->1

        self.living_factor = regular_mm(living_days)

# 针对幸福感可变序列使用了np.power4,即变化速度比sqrt快

        happiness_days = np.power(days, 4)

# 幸福指数可变因素会快速递减由1->0

        self.happiness_factor = regular_mm(happiness_days)[::-1]

"""

这里简单设定wealth_factor=living_factor

living_factor(0-1), 导致wealth_factor(0-1), 即财富积累越到

后面越有效率,速度越快,头一个100万最难赚

"""

        self.wealth_factor =self.living_factor

class FameSeekDay(BaseSeekDay):

"""

FameTask追求名望权力的一天:

追求名望权力

"""

    def _init_self(self):

# 每天对生命消耗的常数=3,即代表3天

        self.living_consume =3

        # 每天幸福指数常数=0.6

        self.happiness_base =0.6

        # 名望权利积累常数=10,默认=0

        self.fame_base =10

        # 设定可变因素序列

        self._gen_living_days()

def _gen_living_days(self):

# 只生成12000个序列

        days = np.arange(1, 12000)

# 针对生命消耗living_factor的基础函数还是sqrt

        living_days = np.sqrt(days)

# 由于不需要像HealthSeekDay从负数开始,所以直接regular_mm 即:0->1

        self.living_factor = regular_mm(living_days)

# 针对幸福感可变序列使用了np.power2

# 即变化速度比StockSeekDay慢但比HealthSeekDay快

        happiness_days = np.power(days, 2)

# 幸福指数可变因素递减由1->0

        self.happiness_factor = regular_mm(happiness_days)[::-1]

# 这里简单设定fame_factor=living_factor

        self.fame_factor =self.living_factor

# 初始化我, 你一生的故事:HealthSeekDay

def my_life(weights):

seek_health = HealthSeekDay()

seek_stock = StockSeekDay()

seek_fame = FameSeekDay()

seek_list = [seek_health, seek_stock, seek_fame]

me = Person()

seek_choice = np.random.choice([0, 1, 2], 80000, p=weights)

while me.living >0:

seek_ind = seek_choice[me.living_day]

seek = seek_list[seek_ind]

me.live_one_day(seek)

return round(me.living_day /365, 2), round(me.happiness, 2), round(me.wealth, 2), round(me.fame, 2)

# living_day, happiness, wealth, fame = my_life([0.4, 0.3, 0.3])

# print('活了{}年,幸福指数{}, 积累财富{}, 名望权力{}'.format(living_day, happiness, wealth, fame))

result = []

for _in range(20):

weights = np.random.random(3)

weights /= np.sum(weights)

result.append((weights, my_life(weights)))

sorted_scores =sorted(result, key=lambda x:x[1][1], reverse=True)

living_day, happiness, wealth, fame = my_life(sorted_scores[0][0])

# print('活了{}年,幸福指数{}, 积累财富{}, 名望权力{}'.format

#          (living_day, happiness, wealth, fame))

#

# print('人生最优权重:追求健康{:.3f},追求财富{:.3f},追求名望{:.3f}'.format(

#        sorted_scores[0][0][0], sorted_scores[0][0][1],

#        sorted_scores[0][0][2]))

result_show = np.array([[r[0][0], r[0][1], r[0][2], r[1][1]]for rin result])

fig = plt.figure(figsize=(9, 6))

ax = fig.gca(projection='3d')

ax.view_init(30, 60)

"""

x:追求健康长寿快乐的权重, y:追求财富金钱的权重

z:追求名望权力的权重, c:color 幸福指数, 颜色越深越幸福

"""

ax.scatter3D(result_show[:, 0], result_show[:, 1], result_show[:, 2],

            c=result_show[:, 3], cmap='spring')

ax.set_xlabel('health')

ax.set_ylabel('stock')

ax.set_zlabel('fame')

# 幸福指数

happiness_result = result_show[:, 3]

# 使用qcut分10份

print(pd.qcut(happiness_result, 10).value_counts())

plt.show()

(本文学习自阿布量化https://www.abuquant.com)

你可能感兴趣的:(我的一生模型构建)