精华内容
下载资源
问答
  • 2022-2027年中国共享自行车行业发展监测及投资战略研究报告
    2022-03-19 10:03:05

    【报告格式】电子版、纸介版

    【出品单位】华经产业研究院

    本报告由华经产业研究院出品,对中国共享自行车行业的发展现状、竞争格局及市场供需形势进行了具体分析,并从行业的政策环境、经济环境、社会环境及技术环境等方面分析行业面临的机遇及挑战。还重点分析了重点企业的经营现状及发展格局,并对未来几年行业的发展趋向进行了专业的预判。为企业、科研、投资机构等单位了解行业最新发展动态及竞争格局,把握行业未来发展方向提供专业的指导和建议。

    共享单车是指企业在校园、地铁站点、公交站点、居民区、商业区、公共服务区等提供自行车单车共享服务,是一种分时租赁模式,是一种新型绿色环保共享经济。

    共享单车实质是一种新型的交通工具租赁业务-自行车租赁业务,其主要依靠载体为(单车)自行车。可以很充分利用城市因快速的经济发展而带来的自行车出行萎靡状况;最大化的利用了公共道路通过率。

    本研究报告数据主要采用国家统计数据,海关总署,问卷调查数据,商务部采集数据等数据库。其中宏观经济数据主要来自国家统计局,部分行业统计数据主要来自国家统计局及市场调研数据,企业数据主要来自于国统计局规模企业统计数据库及证券交易所等,价格数据主要来自于各类市场监测数据库。

    报告目录:

    第一章 全球共享自行车行业运行形势分析

    第一节 全球共享自行车行业发展历程

    第二节 全球共享自行车行业市场发展情况

    一、全球共享自行车行业供给情况分析

    二、全球共享自行车行业需求情况分析

    第三节 全球共享自行车行业主要国家及区域发展情况分析

    第四节 全球共享自行车行业市场发展趋势预测分析

    第二章 2017-2021年中国共享自行车行业发展环境分析

    第一节 2017-2021年中国经济环境分析

    一、宏观经济环境

    二、国际贸易环境

    第二节 2017-2021年共享自行车的行业发展政策环境分析

    一、行业政策影响分析

    二、相关行业标准分析

    第三节 2017-2021年共享自行车的行业发展社会环境分析

    第三章 中国共享自行车所属行业市场总体运行情况分析

    第一节 中国共享自行车行业规模情况分析

    一、行业单位规模情况分析

    二、行业人员规模状况分析

    三、行业资产规模状况分析

    四、行业市场规模状况分析

    第二节 市场壁垒

    第三节 竞争情况分析

    一、现有企业间竞争

    二、潜在进入者分析

    三、替代品威胁分析

    第四节 国际竞争力比较

    第五节 市场集中度分析

    第四章 2021年中国共享自行车行业供需情况分析

    第一节 中国共享自行车市场现状分析

    第二节 中国共享自行车产量分析

    一、共享自行车产业总体产能规模

    二、共享自行车生产区域分布

    第三节 中国共享自行车市场需求分析

    第四节 行业供需平衡状况分析

    一、共享自行车行业供需平衡现状

    二、影响行业供需平衡的因素分析

    三、共享自行车行业供需平衡走势预测

    第五章 中国共享自行车所属行业发展现状分析及市场规模分析

    第一节 中国共享自行车行业发展分析

    一、2017-2021年中国共享自行车行业发展态势分析

    二、2017-2021年中国共享自行车行业发展特点分析

    三、2017-2021年中国共享自行车行业市场供需分析

    第二节 中国共享自行车产业特征与行业重要性

    第三节 共享自行车行业特性分析

    第四节 2021年中国共享自行车市场规模分析

    第五节 2021年中国共享自行车区域市场规模分析

    一、2021年东北地区市场规模分析

    二、2021年华北地区市场规模分析

    三、2021年华东地区市场规模分析

    四、2021年华中地区市场规模分析

    五、2021年华南地区市场规模分析

    六、2021年西部地区市场规模分析

    第六节 2022-2027年中国共享自行车市场规模预测

    2017-2021年中国共享自行车市场规模分析

    第六章 共享自行车行业产品价格分析

    第一节 中国共享自行车行业产品历年价格回顾

    第二节 中国共享自行车行业产品当前市场价格

    一、产品当前价格分析

    二、产品未来价格预测

    第三节 中国共享自行车行业产品价格影响因素分析

    一、全球经济形式及影响

    二、人民币汇率变化影响

    三、其它

    第七章 共享自行车行业替代品及互补产品分析

    第一节 共享自行车行业替代品分析

    一、替代品种类

    二、主要替代品对共享自行车行业的影响

    三、替代品发展趋势分析

    第二节 共享自行车行业互补产品分析

    一、行业互补产品种类

    二、主要互补产品对共享自行车行业的影响

    三、互补产品发展趋势分析

    第八章 共享自行车行业竞争格局及竞争策略分析

    第一节 共享自行车行业竞争格局分析

    一、行业集中度分析

    二、行业竞争格局

    三、竞争群组

    四、共享自行车行业竞争关键因素分析

    1、价格

    2、渠道

    3、产品/服务质量

    4、品牌

    第二节 共享自行车行业市场竞争策略分析

    一、行业国际竞争力比较

    1、生产要素

    2、需求条件

    3、相关和支持性产业

    4、企业战略、结构与竞争状态

    二、共享自行车企业竞争策略分析

    1、提高共享自行车企业核心竞争力的对策

    2、影响共享自行车企业核心竞争力的因素及提升途径

    3、提高共享自行车企业竞争力的策略

    第九章 共享自行车主要上下游产品分析

    第一节 共享自行车上下游分析

    一、与行业上下游之间的关联性

    二、上游原材料供应形势分析

    三、下游产品解析

    第二节 共享自行车行业产业链分析

    一、行业上游影响及风险分析

    二、行业下游风险分析及提示

    三、关联行业风险分析及提示

    第十章 共享自行车行业渠道与行业品牌分析

    第一节 共享自行车行业渠道分析

    一、(HJ 327)渠道格局

    二、渠道形式

    三、渠道要素对比

    四、各区域主要代理商情况

    第二节 共享自行车行业品牌分析

    一、品牌数量分析

    二、品牌推广方式分析

    三、品牌美誉度分析

    四、品牌的选择情况

    第十一章 共享自行车行业重点企业竞争分析

    第一节 金通科技

    一、企业基本概况

    二、企业经营与财务状况分析

    三、企业竞争优势分析

    四、企业未来发展战略与规划

    第二节 摩拜

    一、企业基本概况

    二、企业经营与财务状况分析

    三、企业竞争优势分析

    四、企业未来发展战略与规划

    第三节 小鸣单车

    一、企业基本概况

    二、企业经营与财务状况分析

    三、企业竞争优势分析

    四、企业未来发展战略与规划

    第四节 优拜单车

    一、企业基本概况

    二、企业经营与财务状况分析

    三、企业竞争优势分析

    四、企业未来发展战略与规划

    第五节 行我行

    一、企业基本概况

    二、企业经营与财务状况分析

    三、企业竞争优势分析

    四、企业未来发展战略与规划

    第六节 奇奇出行

    一、企业基本概况

    二、企业经营与财务状况分析

    三、企业竞争优势分析

    四、企业未来发展战略与规划

    第十二章 2022-2027年中国共享自行车行业发展前景预测

    第一节 未来共享自行车行业发展趋势分析

    一、未来共享自行车行业发展分析

    二、未来共享自行车行业技术开发方向

    三、总体行业“十四五”整体规划及预测

    第二节 2022-2027年共享自行车行业运行状况预测

    一、2022-2027年共享自行车行业工业总产值预测

    二、2022-2027年共享自行车行业销售收入预测

    三、2022-2027年共享自行车行业总资产预测

    第十三章 共享自行车行业风险与投资策略分析

    第一节 共享自行车行业风险分析

    一、行业环境风险(HJ LT)

    二、行业产业链上下游风险

    三、行业政策风险

    四、行业市场风险

    五、行业其他风险分析

    第二节 共享自行车投资策略分析

    一、行业总体发展前景及市场机会分析

    二、企业营销策略

    三、企业投资策略

    四、企业应对当前经济形势策略建议

    图表目录:

    图表 共享自行车行业渠道格局分析

    图表 共享自行车渠道策略示意图

    图表 共享自行车产业链投资示意图

    图表 共享自行车行业销售渠道控制五力模型

    图表 中国共享自行车行业需求集中度分析

    图表 中国共享自行车行业竞争群组分析

    图表 2021年中国共享自行车行业产量分析

    图表 2022-2027年中国共享自行车行业产量预测

    图表 2021年中国共享自行车行业需求量分析

    图表 2017-2021年全球共享自行车行业市场规模及增速

    更多图表见正文……

    更多相关内容
  • 基于LSTM多变量预测_共享自行车使用量预测.zip(案例)
  • 洛杉矶市构建共享自行车系统的经验借鉴-报告资料.pdf
  • 研究结果指出,态度,主观规范和感知的行为控制对女性对共享自行车车队的意图产生了显着的积极影响,而宗教信仰对女性使用者的意图产生了负面影响。 据我们所知,这是第一项评估宗教程度对女性使用者共享自行车意愿...
  • TTJZX-001-2017 共享自行车 第1部分:自行车
  • 3dmax共享自行车架子 模型 有需要直接下载
  • 基于调查数据对出行特征进行分析,研究出影响共享自行车使用的因素,并结合SPSS Calculate软件,建立出行行为理论Logit模型。 结果表明,与男性相比,女性更有可能选择共享自行车出行。 那些选择共享自行车的人往往...
  • 共享自行车市场智能预测系统.pdf
  • 全球骑自行车的人 地图应用程序共享自行车之旅行程。 原型: 贡献 如果您想为开发做出贡献,请随时与我们联系。 安装 要安装该应用程序,请按照“页面(正在进行中)中的说明进行操作。 建筑学 请阅读页面。
  • 今天给大家带来一篇新的kaggle数据分析实战案例:基于长短期记忆网络(LSTM)模型的伦敦自行车需求预测分析。本文的两个亮点: 高级可视化:本文使用seaborn进行了可视化探索分析,图表精美,分析维度多样化,结论...

    公众号:尤而小屋
    作者:Peter
    编辑:Peter

    大家好,我是Peter~

    今天给大家带来一篇新的kaggle数据分析实战案例:基于长短期记忆网络(LSTM)模型的伦敦自行车需求预测分析。本文的两个亮点:

    • 高级可视化:本文使用seaborn进行了可视化探索分析,图表精美,分析维度多样化,结论清晰
    • 使用LSTM模型:长短期网络模型的使用,使得结果更具价值和参考性

    这是一个排名第三的方案:

    感兴趣的可以参考原notebook地址进行学习:

    https://www.kaggle.com/yashgoyal401/advanced-visualizations-and-predictions-with-lstm/notebook

    还有一篇类似文章:

    https://www.kaggle.com/geometrein/helsinki-city-bike-network-analysis

    本文步骤

    下面是原文中的主要步骤:数据信息、特征工程、数据EDA、预处理、模型构建、需求预测和评价模型

    LSTM模型

    本文重点是使用了LSTM模型。LSTM是一种时间递归神经网络,适合于处理和预测时间序列中间隔和延迟相对较长的重要事件。

    小编实力有限,关于模型的原理详细讲解参考书籍和文章:

    1、优秀书籍:《Long Short Term Memory Networks with Python》是澳大利亚机器学习专家Jason Brownlee的著作

    2、知乎文章:https://zhuanlan.zhihu.com/p/24018768

    3、B站:搜索李沐大佬关于LSTM的讲解

    以后有实力了,肯定写一篇LSTM原理的文章~

    一起学习吧!卷吧

    数据

    导入库

    import pandas as pd
    import numpy as np
    
    # seaborn可视化
    import seaborn as sns
    import matplotlib.pyplot as plt
    sns.set(context="notebook", style="darkgrid", 
            palette="deep", font="sans-serif", 
            font_scale=1, color_codes=True)
    
    # 忽略警告
    import warnings
    warnings.filterwarnings("ignore")
    

    读取数据

    基本信息:

    # 1、数据量
    data.shape
    
    (17414, 10)
    
    # 2、数据字段类型
    data.dtypes
    
    timestamp        object
    cnt               int64
    t1              float64
    t2              float64
    hum             float64
    wind_speed      float64
    weather_code    float64
    is_holiday      float64
    is_weekend      float64
    season          float64
    dtype: object
    

    数据中没有缺失值:

    字段含义

    解释下数据中字段的含义:

    • timestamp:用于将数据分组的时间戳字段
    • cnt:新自行车份额的计数
    • t1:以C为单位的实际温度
    • t2:C中的温度“感觉像”,主观感受
    • hum:湿度百分比
    • windspeed:风速,以km / h为单位
    • weathercode:天气类别;(具体的取值见下图中的最后)
    • isholiday:布尔字段,1-假期,0-非假期
    • isweekend:布尔字段,如果一天是周末,则为1
    • Season:类别气象季节:0-春季;1-夏;2-秋;3-冬

    TensorFlow基本信息

    TensorFlow的GPU信息和版本查看:

    特征工程

    下面介绍本文中特征工程的实现:

    数据信息

    一个DataFrame的info信息能够显示出字段名、非空数量、数据类型等多个基本信息

    时间字段处理

    对原始数据中的时间相关字段进行处理:

    1、将时间戳转成时间类型

    2、转成索引

    使用set_index方法将timestamp属性转成索引

    3、提取时、一个月中的第几天、第几周、月份等信息

    提取时间相关的多个信息,同时查看数据的shape

    相关系数分析

    1、相关系数求出绝对值

    2、筛选两个属性之间的相关系数大于0.8

    数据EDA

    相关系数热力图

    plt.figure(figsize=(16,6))
    
    sns.heatmap(data.corr(),
                cmap="YlGnBu",  # 色系
                square=True,  # 方形
                linewidths=.2,
                center=0,
                linecolor="red"  # 线条颜色
               )
    
    plt.show()
    

    通过热力图我们发现:t1和t2的相关系数是比较高的,和上面的“属性之间的系数大于0.8”的结论是吻合的

    空值判断

    关于如何判断一份数据中是否存在空值,小编常用的方法:

    文章中使用的方法是:基于热力图显示。图形中没有任何信息,表明数据是不存在空值的

    需求量变化

    整体的需求量cnt随着时间变化的关系:

    plt.figure(figsize=(15,6))
    
    sns.lineplot(data=data,  # 传入数据
                 x=data.index,  # 时间
                 y=data.cnt  # 需求量
                )
    
    plt.xticks(rotation=90)
    

    从上面的图形,我们能够看到整体日期下的需求量变化情况。

    按月采样resample

    pandas中的采样函数使用的是resample,频率可以是天、周、月等

    查看随着时间的变化,每月的需求量变化情况:

    plt.figure(figsize=(16,6))
    
    sns.lineplot(data=df_by_month,
                 x=df_by_month.index,
                 y=df_by_month.cnt,
                 color="red"
                )
    
    plt.xticks(rotation=90)
    
    plt.show()
    

    可以从图中观察到以下3点结论:

    1. 年初到7、8月份需求量呈现上升趋势
    2. 差不多在8月份达到一定的峰值
    3. 8月份过后需求量开始降低

    每小时需求量

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,  # 数据
                  x=data.hour,  # 小时
                  y=data.cnt,  # 需求量
                  color="red"  # 颜色
                 )
    
    plt.show()
    

    每月的需求量对比

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  x=data.month,
                  y=data.cnt,
                  color="red"
                 )
    plt.show()
    

    明显的结论:7月份是需求的高峰期

    按照星期统计

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  x=data.day_of_week,
                  y=data.cnt,
                  color="black")
    
    plt.show()
    

    从图中观察到:

    • 周1到周五的需求是明显高于周末两天;
    • 同时在周五的时候已经呈现下降趋势

    按照自然日

    plt.figure(figsize=(16,6))
    
    sns.lineplot(
      data=data,
      x=data.day_of_month,  # 一个月中的某天
      y=data.cnt,  # 需求量
      color="r")
    
    plt.show()
    

    3点结论:

    • 前10天需求量在逐步增加
    • 中间10天存在一定的小幅波动
    • 最后10天波动加大,呈现下降趋势

    多个维度下的可视化化效果

    基于是否节假日下的小时

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  x=data.hour,  # 按照小时统计
                  y=data.cnt,
                  hue=data.is_holiday  # 节假日分组
                 )
    
    plt.show()
    

    通过上面图形呈现的结果;

    • 非节假日下(is_holiday=0):在8点和下午的17、18点是用车的高峰期,恰好是上下班的时间点
    • 到了节假日(1)的情况下:下午的2-3点才是真正的用车高峰期

    基于是否节假日的月份

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  x=data.month,
                  y=data.cnt,
                  hue=data.is_holiday
                 )
    
    plt.show()
    

    在非节假日,7月份达到了用车的高峰期

    3、按照季度统计

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  y=data.cnt,
                  x=data.month,
                  hue=data.season, # 季度分组
                 )
    
    plt.show()
    

    从上图中观察到:第3个季度(6–7-8月份)才是用车需求量最多的时候

    4、季度+是否节假日

    plt.figure(figsize=(16,6))
    
    # 分组统计数量
    sns.countplot(data=data,
                  x=data.season,
                  hue=data.is_holiday,
                 )
    
    plt.show()
    

    从1-2-3-4季度来看,非节假日中的整体需求量1和2季度是稍高于0和3季度;而节假日中,0-3季度则存在一定的需求

    5、是否周末+小时

    plt.figure(figsize=(16,6))
    
    sns.lineplot(
        data=data,
        x=data.hour,  # 小时
        y=data.cnt,
        hue=data.is_weekend)  # 分是否周末统计
    
    plt.show()
    

    • 非周末(0):仍然是上午的7-8点和下午的17-18点是用车高峰期
    • 周末(1):下午的14-15点才是高峰期

    这个结论和上面的是吻合的

    6、季度+小时

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  x=data.hour,
                  y=data.cnt,
                  hue=data.season # 分季度统计
                 )
    
    plt.show()
    

    分季度查看每个小时的需求量:整体的趋势大体是相同的,都是在8点左右达到上午的高封期,下午的17-18点(下班的时候)达到另一个高封期

    天气因素

    湿度和需求量关系

    观察不同湿度下,需求量的变化情况:

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  x=data.hum,
                  y=data.cnt,
                  color="black")
    
    plt.xticks(rotation=90)
    
    plt.show()
    

    可以看到:空气空气湿度越大,整体的需求量是呈现下降趋势

    风速和需求量

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  x=data.wind_speed,
                  y=data.cnt)
    
    plt.xticks(rotation=90)
    
    plt.show()
    

    风速对需求量的影响:

    • 在风速为25.5的时候存在一个局部峰值
    • 风速偏高或者偏低的时候需求都有所降低

    不同天气情况weather_code

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  x=data.weather_code,
                  y=data.cnt)
    
    plt.xticks(rotation=90)
    
    plt.show()
    

    结论:可以看到在scattered coluds(weather_code=2)情况下,需求量是最大的

    天气情况+小时

    plt.figure(figsize=(16,6))
    
    sns.pointplot(data=data,
                  x=data.hour,
                  y=data.cnt,
                  hue=data.weather_code # 分天气统计
                 )
    
    plt.show()
    

    从上午中观察到:不同的天气对小时需求量的趋势影响不大,仍然是在上下班高峰期的时候需求量最大,说明打工人上班出行几乎不受天气影响!!!

    自然天+天气情况

    plt.figure(figsize=(16,6))
    
    sns.countplot(
        data=data,
        x=data.day_of_week,  # 一周中的第几天
        hue=data.weather_code,  # 天气情况
        palette="viridis")
    
    plt.legend(loc="best")  # 位置选择
    
    plt.show()
    

    从上图中观察到:

    1. 不同的星期日期,code=1下的需求量都是最大的
    2. 礼拜1到礼拜5:满足code=1 > 2 > 3 > 7 > 4 的需求量
    3. 到礼拜6和礼拜天:大家出行的时候对天气关注影响偏低,除去code=1,其他天气情况的需求差距也在缩小!

    箱型图

    箱型图能够反映一组数据的分布情况

    按小时

    plt.figure(figsize=(16,6))
    
    sns.boxplot(data=data,
                x=data.hour,  # 小时
                y=data.cnt)
    
    plt.show()
    

    从箱型图的分布观察到:两个重要的时间段:上午7-8点和下午的17-18点

    每周星期几

    plt.figure(figsize=(16,6))
    
    sns.boxplot(
        data=data,
        x=data["day_of_week"],
        y=data.cnt)
    
    plt.show()
    

    在基于星期的箱型图中,礼拜三的时候存在一定的用车高峰期

    月的自然天

    plt.figure(figsize=(16,6))
    
    sns.boxplot(data=data,
                x=data["day_of_month"],
                y=data.cnt)
    
    plt.show()
    

    在基于自然日的情况下,9号的存在高峰期

    按月

    plt.figure(figsize=(16,6))
    
    sns.boxplot(data=data,
                x=data["month"],
                y=data.cnt)
    
    plt.show()
    

    明显观察到:7-8月份存在一定的需求高峰期,两侧月份的需求相对较少些

    是否节假日+月的天

    # 每月中的天和是否节假日统计
    
    plt.figure(figsize=(16,6))
    
    sns.boxplot(
        data=data,
        x=data["day_of_month"],
        y=data.cnt,
        hue=data["is_holiday"])
    
    plt.show()
    

    数据预处理

    下面开始进行建模,首先进行的是数据预处理工作,主要是包含两点:

    • 数据集的切分
    • 数据归一化和标准化

    切分数据

    按照9:1的比例来切分数据集:

    # 切分数据集的模块
    from sklearn.model_selection import train_test_split
    train,test = train_test_split(data,test_size=0.1, random_state=0)
    print(train.shape)
    print(test.shape)
    
    # ------
    (15672, 13)
    (1742, 13)
    

    数据归一化

    from sklearn.preprocessing import MinMaxScaler
    # 实例化对象
    scaler  = MinMaxScaler()
    
    # 部分字段的拟合
    num_col = ['t1', 't2', 'hum', 'wind_speed']
    trans_1 = scaler.fit(train[num_col].to_numpy())
    
    # 训练集转换
    train.loc[:,num_col] = trans_1.transform(train[num_col].to_numpy())
    # 测试集转换
    test.loc[:,num_col] = trans_1.transform(test[num_col].to_numpy())
    
    # 对标签cnt的归一化
    cnt_scaler = MinMaxScaler()
    # 数据拟合
    trans_2 = cnt_scaler.fit(train[["cnt"]])
    # 数据转化
    train["cnt"] = trans_2.transform(train[["cnt"]])
    test["cnt"] = trans_2.transform(test[["cnt"]])
    

    训练集和测试集

    # 用于显示进度条
    from tqdm import tqdm_notebook as tqdm
    tqdm().pandas()
    
    def prepare_data(X, y, time_steps=1):
        Xs = []
        Ys = []
        
        for i in tqdm(range(len(X) - time_steps)):
            a = X.iloc[i:(i + time_steps)].to_numpy()
            Xs.append(a)
            Ys.append(y.iloc[i + time_steps])
            
        return np.array(Xs), np.array(Ys)
    
    steps = 24
    
    X_train, y_train = prepare_data(train, train.cnt, time_steps=steps)
    X_test, y_test = prepare_data(test, test.cnt, time_steps=steps)
    
    print(X_train.shape)
    print(X_test.shape)
    print(y_train.shape)
    print(y_test.shape)
    

    LSTM建模

    导入库

    在建模之前先导入相关的库:

    # 1、导入需要的库
    from keras.preprocessing import sequence
    from keras.models import Sequential
    from keras.layers import Dense, Dropout, LSTM, Bidirectional
    
    # 2、实例化对象并拟合建模
    model = Sequential()
    model.add(Bidirectional(LSTM(128, 
                                 input_shape=(X_train.shape[1],
                                              X_train.shape[2]))))
    
    model.add(Dropout(0.2))
    model.add(Dense(1, activation="sigmoid"))
    model.compile(optimizer="adam", loss="mse")
    

    模型准备

    传入训练集的数据后,进行数据的拟合建模过程:

    均方差和Epoch的关系

    探索在不同的Epoch下均方差的大小:

    plt.plot(prepared_model.history["loss"],label="loss")
    plt.plot(prepared_model.history["val_loss"],label="val_loss")
    
    # lengend位置选择
    plt.legend(loc="best")
    # 两个轴的标题
    plt.xlabel("No. Of Epochs")
    plt.ylabel("mse score")
    

    需求量预测

    生成真实值和预测值

    inverse_transform 函数是将标准化后的数据转换为原始数据。

    pred = model.predict(X_test)  # 对测试集预测 
    y_test_inv = cnt_scaler.inverse_transform(y_test.reshape(-1,1))  # 转变数据
    pred_inv = cnt_scaler.inverse_transform(pred)  # 预测值转换
    pred_inv
    

    绘图比较

    将测试集转变后的值和基于模型的预测值进行绘图比较:

    plt.figure(figsize=(16,6))
    
    # 测试集:真实值
    plt.plot(y_test_inv.flatten(), marker=".", label="actual")
    # 模型预测值
    plt.plot(pred_inv.flatten(), marker=".", label="predicttion",color="r")
    # 图例位置
    plt.legend(loc="best")
    plt.show()
    

    生成数据

    将测试集的真实值和预测值进行对比,通过两个指标来进行评估:

    1、原文中的方法(个人认为复杂了):

    # 原方法过程复杂了
    
    y_test_actual = cnt_scaler.inverse_transform(y_test.reshape(-1,1))
    y_test_pred = cnt_scaler.inverse_transform(pred)
    
    arr_1 = np.array(y_test_actual)
    arr_2 = np.array(y_test_pred)
    
    actual = pd.DataFrame(data=arr_1.flatten(),columns=["actual"])
    predicted = pd.DataFrame(data=arr_2.flatten(),columns = ["predicted"])
    
    final = pd.concat([actual,predicted],axis=1)
    final.head()
    

    2、个人方法

    y_test_actual = cnt_scaler.inverse_transform(y_test.reshape(-1,1))
    y_test_pred = cnt_scaler.inverse_transform(pred)
    final = pd.DataFrame({"actual": y_test_actual.flatten(),
                          "pred": y_test_pred.flatten()})
    final.head()
    

    模型评价

    通过mse和r2_score指标来评估模型:

    # mse、r2_score
    from sklearn.metrics import mean_squared_error, r2_score
    
    rmse = np.sqrt(mean_squared_error(final.actual, final.pred))
    r2 = r2_score(final.actual, final.pred)
    
    print("rmse is : ", rmse)
    print("-------")
    print("r2_score is : ", r2)
    
    # 结果
    rmse is :  1308.7482342002293
    -------
    r2_score is :  -0.3951062293743659
    

    下面作者又绘图来对比真实值和预测值:

    plt.figure(figsize=(16,6))
    
    # 真实值和预测值绘图
    plt.plot(final.actual, marker=".", label="Actual label")
    plt.plot(final.pred, marker=".", label="predicted label")
    # 图例位置
    plt.legend(loc="best")
    
    plt.show()
    

    疑点

    Peter个人有个疑点:下面的两幅图有什么区别,除了颜色不同?看了整个源码,作图的数据和代码都是一样的。作者还写了两段话:

    Note that our model is predicting only one point in the future. That being said, it is doing very well. Although our model can’t really capture the extreme values it does a good job of predicting (understanding) the general pattern.

    说普通话:注意到,我们的模型仅预测未来的一个点。话虽如此,它仍做得很好。虽然我们的模型不能真正捕捉到极值,但它在预测(理解)一般模式方面还是做得很好

    AS you can see that I have used Bidirectional LSTM to train our model and Our model is working quite well.Our model is cap*able to capture the trend and not capturing the Extreme values which is a really good thing. SO, we can say that the overall perfomance is good.

    说普通话:如你所见,我使用双向 LSTM 来训练我们的模型,并且我们的模型运行良好。我们的模型能够捕捉趋势而不是捕捉极值,这是一件非常好的事情。所以,我们可以说整体表现不错。

    下面是整个建模的源码,请参考学习,也可以讨论上面的疑点:

    # 划分数据集
    from sklearn.model_selection import train_test_split
    train,test = train_test_split(data,test_size=0.1,random_state=0)
    
    # 数据归一化
    from sklearn.preprocessing import MinMaxScaler
    scaler  = MinMaxScaler()
    # 对4个自变量的归一化
    num_colu = ['t1', 't2', 'hum', 'wind_speed']
    trans_1 = scaler.fit(train[num_colu].to_numpy())
    train.loc[:,num_colu] = trans_1.transform(train[num_colu].to_numpy())
    test.loc[:,num_colu] = trans_1.transform(test[num_colu].to_numpy())
    # 对因变量的归一化
    cnt_scaler = MinMaxScaler()
    trans_2 = cnt_scaler.fit(train[["cnt"]])
    train["cnt"] = trans_2.transform(train[["cnt"]])
    test["cnt"] = trans_2.transform(test[["cnt"]])
    
    # 导入建模库和实例化
    from keras.preprocessing import sequence
    from keras.models import Sequential
    from keras.layers import Dense, Dropout , LSTM , Bidirectional 
    # 时序对象的实例化
    model = Sequential()
    model.add(Bidirectional(LSTM(128,input_shape=(X_train.shape[1],X_train.shape[2]))))
    model.add(Dropout(0.2))
    model.add(Dense(1,activation="sigmoid")) # 激活函数选择
    model.compile(optimizer="adam",loss="mse")  # 优化器和损失函数选择
    
    with tf.device('/GPU:0'):
        prepared_model = model.fit(X_train,
                                   y_train,
                                   batch_size=32,
                                   epochs=100,
                                   validation_data=[X_test,y_test])
        
    # 两种损失的对比
    plt.plot(prepared_model.history["loss"],label="loss")
    plt.plot(prepared_model.history["val_loss"],label="val_loss")
    plt.legend(loc="best")
    plt.xlabel("No. Of Epochs")
    plt.ylabel("mse score")
    
    # 测试数据集的预测
    pred = model.predict(X_test)  
    
    # cnt数据的还原
    y_test_inv = cnt_scaler.inverse_transform(y_test.reshape(-1,1))
    pred_inv = cnt_scaler.inverse_transform(pred)
    
    # 绘图1
    plt.figure(figsize=(16,6))
    plt.plot(y_test_inv.flatten(), marker=".",label="actual")
    plt.plot(pred_inv.flatten(), marker=".",label="prediction",color="r")
    
    # cnt数据的还原
    y_test_actual = cnt_scaler.inverse_transform(y_test.reshape(-1,1))
    y_test_pred = cnt_scaler.inverse_transform(pred)
    
    # 转成数组
    arr_1 = np.array(y_test_actual)
    arr_2 = np.array(y_test_pred)
    
    # 生成Pandas的DataFrame,合并数据
    actual = pd.DataFrame(data=arr_1.flatten(),columns=["actual"])
    predicted = pd.DataFrame(data=arr_2.flatten(),columns = ["predicted"])
    final = pd.concat([actual,predicted],axis=1)
    
    # 评价指标
    from sklearn.metrics import mean_squared_error, r2_score
    rmse = np.sqrt(mean_squared_error(final.actual,final.predicted)) 
    r2 = r2_score(final.actual,final.predicted) 
    print("rmse is : {}\nr2 is : {}".format(rmse,r2))
    
    # 绘图2
    plt.figure(figsize=(16,6))
    plt.plot(final.actual,label="Actual data")
    plt.plot(final.predicted,label="predicted values")
    plt.legend(loc="best")
    
    

    文中数据的获取方式,关注公众号【尤而小屋】,回复 自行车 即可。

    展开全文
  • 可移动的站点空间是成功、公平共享自行车的关键- 2015.04-美国国家城市交通联盟办公室自行车共享实践论文-外文-报告资料.pdf
  • 《基于java+ssh+mysql实现的共享自行车租赁管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 系统说明: 《基于java+ssh+mysql实现的共享自行车租赁管理系统》该项目含有源码、...

    下载:https://download.csdn.net/download/m0_68856272/85052024
    项目介绍:
    《基于java+ssh+mysql实现的共享自行车租赁管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等

    系统说明:

    《基于java+ssh+mysql实现的共享自行车租赁管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等

    使用技术:

    前端使用技术:JSP,HTML5,CSS3、JavaScript等

    后台使用技术:Spring、Struts2、Hibernate(SSH)等

    数据库:Mysql数据库

    项目功能介绍:

    基于java+ssh+mysql的共享自行车管理系统,包含用户和管理员权限,系统功能如下:

    管理员:修改个人密码、新闻信息管理、站点信息管理、留言信息管理(回复)、租车信息管理、会员管理。

    用户:注册、登录系统;首页、租车/还车、自行车查询、新闻资讯、系统留言。

    后面优化了一些细节,使得系统更加合理。

    本系统使用ssh框架,数据库使用mysql,功能齐全,另外附带2W字+论文一份,适合作为毕业设计。

    适用场景:

    毕业论文、课程设计、公司项目参考

    运行截图:
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    微信小程序商城

    关注【程序代做 源码分享】公众号获取更多免费源码!!!
    请添加图片描述

    展开全文
  • 装载自行车 支持代码 建立 克隆仓库: clone https://github.com/GBH/loaded.bike.git 使用mix deps.get安装依赖mix deps.get 使用mix ecto.create && mix ecto.migrate创建和迁移数据库 在/assets内部使用npm ...
  • 我想把这个主题定为"共享自行车区块链网络"。共享经济的一些特点使之正适合利用区块链技术。这个示例应用会随着一些区块链问题的研究与解决,从最初的简单原型开始进行多次迭代。目前它的名字就定为: bikesharing ...

    前言

    在本系列第 1 部分文章的中,我们一起学习了 Fabric、Composer 基础知识,利用 Hyperledger Compose 搭建了 Fabric 本地开发环境,运行了一个示例区块链网络应用。

    现在,我们可以设想一个更具有现实意义的 User Story,像开发一个真实的区块链应用一样,从无到有地开发、部署、管理这个应用。在这个过程中,我们一定会遇到很多问题,正可以这些问题为线索,快速、高效地学习、研究区块链网络。这样,也可以使学习的过程更具趣味性。

    我想把这个主题定为"共享自行车区块链网络"。共享经济的一些特点使之正适合利用区块链技术。这个示例应用会随着一些区块链问题的研究与解决,从最初的简单原型开始进行多次迭代。目前它的名字就定为:bikesharing Network

    本文中的示例以第 1 部分的示例为基础,请先行阅读、执行。本文示例所使用的 Fabric 的版本为 1.1.0,而 Composer 的最新版本为 0.19.4,与之前的 0.19.1 在使用方法上没有差别。
    Composer 现在版本更新较频繁,请注意版本更新可能带来的变化。(Micro 版本号对应用应该没有影响,在本文公开后,如继续有升级,请自行升级 Composer 即可。)

    升级 Composer 与重启 Fabric

    升级 Composer

    $ ~/fabric-tools/stopFabric.sh
    $ npm uninstall -g composer-cli composer-rest-server generator-hyperledger-composer
    $ npm install -g composer-cli composer-rest-server generator-hyperledger-composer

    重启 Fabric 及 BND

    重启 Fabric:

    $ ~/fabric-tools/stopFabric.sh
    $ ~/fabric-tools/startFabric.sh

    重启 BND:

    startFabric 后需要重新 install,start BND,import card,仍以第 1 部分中的 tutorial-network 为例:

    $ cd ~/fabric-tools/tutorial-network
    $ composer card delete --card admin@tutorial-network
    $ composer network install --card PeerAdmin@hlfv1 --archiveFile tutorial-network@0.0.1.bna
    $ composer network start --networkName tutorial-network --networkVersion 0.0.1 --
    networkAdmin admin --networkAdminEnrollSecret adminpw --card PeerAdmin@hlfv1 --file
    admin@tutorial-network.card
    $ composer card import --file admin@tutorial-network.card

    teardown

    如果 ~/fabric-tools/teardownFabric.sh 被执行过,则在 startFabric 后,需要再次执行 createPeerAdminCard.sh 及之后步骤。详情请参考本系列第一部分的相关内容。

    删除 Docker Images

    如果需要彻底删除之前下载安装的 Composer、Fabric 环境,可以执行如下命令:

    $ docker kill $(docker ps -q)
    $ docker rm $(docker ps -aq)
    $ docker rmi $(docker images dev-* -q)

    User Story – 共享自行车区块链网络(bikesharing Network)

    业务需求

    虽然本文是一篇技术文章,但我认为,理解学习的目的及确定学习的方向,是一件首要的事情,所以,我们必须先理解一些商业相关内容,我们这个 User Story 的需求是什么,大概涵盖哪些方面。这个网络应满足以下需求:

    1. 共享自行车服务供应商会通过这个网络注册自行车;
    2. 用户会通过这个网络租用(解锁)、归还(上锁)自行车;
    3. 所有操作(状态修改、付费、报修)都作为 Transaction(交易)提交到这个区块链网络;
    4. 允许多个自行车服务供应商共用这个网络;
    5. 允许自行车服务供应商执行不同的业务逻辑;
    6. 允许其他共享服务(共享汽车、共享房间……)供应商、用户使用这个网络。

    这样看来,我们需要解决很多问题:基于区块链模式下的业务模型设计、权限管理,节点的部署与控制,效率问题,系统可靠性问题……但不管如何,我们都会 Focus on Blockchain,会始终着力于典型的"区块链"应用。

    当前简化的原型设计、开发、部署

    我们要先从一个最简化的原型开始,也就是本部分所将涉及的内容:

    1. Assets:自行车;
    2. Participants:自行车供应商、自行车用户;
    3. Transaction:租车、还车;
    4. Query:设计基本查询;
    5. BND:Business Network Definition 业务网络定义;
    6. BND 部署与更新。

    现在,我们需要先了解一些必需的 BND(业务网络定义)基础知识。我们可以带着对这个 User Story 的想法、疑问去学习 BND,及其他相关知识。

    业务网络定义 Business Network Definition(BND)

    BND 是 Composer 编程模型中的的关键概念,它包含了这个区块链业务网络的所有域模型、业务逻辑、访问控制规则、查询等内容。BND 会被打包后部署到 Fabric 节点上,我们可以利用 Composer 系统接口生成 BND 中一些域模型的实例,或者触发执行 BND 中定义的业务逻辑。下面即按各部分详细讲解,并给出 bikesharing 的实例。

    域模型(Domain Models)

    域模型主要包含了以下定义:Assets,Participants,Transactions,Events 等,它们是这个业务网络中将要被使用、处理的对象类型,也可以理解为一系列资源类型。它位于 models 目录下名为 *.cto 的文件中。域模型是用 Hyperledger Composer Modeling Language 定义的。

    Composer 建模语言(Composer Modeling Language)

    它是 Hyperledger Composer 提供的一个面向对象的建模语言,用来定义业务网络中的域模型。它有以下特点与属性。

    1. Namespace 命名空间

    模型归属于一个 namespace(命名空间)。一个 .cto 文件中会定义一个 namespace,其中包含的所有定义都属于这个 namespace。示例:

    namespace org.bikesharing.biznet
    asset Bike identified by bikeId { … }

    则在以后可以用类似 "org.bikesharing.biznet.Bike" 引用这个类型。

    2. 域模型的类型及其基础类、关键字:

    表 1. 域模型的类型及其基础类、关键字

    可从 Composer 源码 org.hyperledger.composer.system.cto 中获取更详细内容。

    域模型定义往往包括若干属性(字段)定义。示例:

    participant BikeUser identified by bikeUserId {
         o String bikeUserId
         o Integer age
    }
    asset Bike identified by bikeId { … }

    资源 Assets,Participants,Transactions 可以被实例化为对象并存储在相应 AssetRegistry,ParticipantRegistry,TransactionRegistry 中,作为 Fabric 区块链网络的 World State(世界观)中的一部分。

    Assets,Participants 需要定义 identified by 属性,以表示资源对象的唯一标识字段。但 Transactions、Events 定义中不能包括 identified by 属性,且不允许有 transactionId,eventId,timestamp 字段,因为它们已经在基础类定义 org.hyperledger.composer.system 中被声明。内容如下:

    abstract transaction Transaction identified by transactionId {
         o String transactionId
         o DateTime timestamp
    }
    abstract event Event identified by eventId {
         o String eventId
         o DateTime timestamp
    }

    3. 原生类型

    表 2. Composer 建模语言中的原生类型

    当原生类型被用于定义模型中的某一属性时,以符号 "o" 作为标志,示例:

    o String bikeUserId
    o Integer age

    4. Concept

    Concept 可以理解为一个在多种模型定义间共享的一组属性的组合,一般会被 asset、participant、transaction 等资源"包含"。我们可以通过 getFactory().newConcept() 方法实例化 Concept,得到一个对象,但不能将它单独存储在 Registry 中,也不能被作为 Relationship 引用。它没有 "identified by" 字段。示例:

    concept Address {
         o String street
         o String city
         o String country
    }
    participant BikeUser identified by BikeUserId {
         // …
         o Address adr
             // …
    }

    5. 抽象(abstract)与继承(extends)

    抽象类型不能被实例化,但可被继承。Assets、Participants、Transaction、Concepts、Events 都可以被定义为 abstract,或通过 extends 继承另一个类型定义。示例:

    abstract transaction BikeTransaction { … }
    transaction BikeRentTransaction extends BikeTransaction { … }
    abstract concept Address { … }

    6. Relationship

    在模型定义中,可以通过 Relationship 引用另一个资源对象。用符号"-->"标示。示例:

    transaction BikeTransaction {
         --> Bike bike
         --> BikeUser user
    }

    在实例化这个上层对象时,需要使用完整的 identifier 来标识被引用资源,示例:

    "resource:org.bikesharing.biznet.Bike#bid_1"

    7. Enum

    枚举变量定义及使用示例:

         o AVAILABLE
         o INUSE
         o INREPAIR
    }
     
    asset Bike identified by bikeId {
         // …
         o BikeStatus status
         // …
    }

    8. 数组

    以上所述所有类型都可以用符号"[]"标示为数组,示例:

    o Integer[] counts
    o String[] comments
    --> Bike[] bikes

    9. Optional

    默认情况下,模型中定义的属性是必选项,在实例化时必须指定初始值。但可以将其标示为 optional, 以表示在实例化时可以忽略此属性。示例:

    o Integer age optional

    10. 字段校验

    资源字段可以设定默认值,示例:

    o String bikeName default="MOF Bike"

    Double,Integer,Long 类型字段可以定义 Range,示例:

    o Integer year range=[1900, ]

    此外,还可以定义正则表达式对字段进行校验,示例:

    o String postCode regex=/^[0-9]{6}$/ optional

    11. Import

    我们可以使用 import 从外部引入其他 namespace 中的资源定义,以实现类型定义的共享、重用。示例:

    import org.example.biznet.*
    import org.example.biznet.SampleAsset

    交易处理器(Transaction Processor Functions)

    交易处理器是对在 BND 中定义的交易(transaction)的业务逻辑的具体实现,它定义了对这个区块链网络中的 Assets,Participants,Transaction,Events、区块链世界观(World State)等资源进行交易处理的功能。每当交易被提交时,对应的 Transaction Processor Function 就会被 Composer Runtime 触发执行。我们可以针对每一种交易定义一个 function,以实现其对应的业务逻辑。它使用的编辑语言是 ES6 JavaScript。表现为一组位于 lib 目录下名为 *.js 的文件。

    在这个 JavaScript 程序中,我们可以访问 Composer Runtime API 中的一个类 Api 所提供的一此方法,如:getFactory(),getParticipantRegistry(),getAssetRegistry(),query(),emit() 等,以实现对当前业务网络的访问、操作。

    交易处理器结构

    每个交易处理器方法都必须包括以下修饰器(decorators):

    • @param,随后必须指定对应交易的类型名称,以及参数名称。
    • @transaction,这个修饰器标识下面的方法是一个交易处理器。Composer Runtime 将根据这些 decorators 确定将哪些类型的 transaction 由此 process function 处理。示例:
      /**
        * Processor function for BikeRentTransaction
        * @param {org.bikesharing.biznet.BikeRentTransaction} tx
        * @transaction
        */
      async function processBikeRentTransaction(tx) {
           // …
      }

    错误处理

    交易对区块链业务网络中资源、状态的改变是原子操作(Atomic),或者完全成功,或者完全失败。一旦有错误(异常)抛出,则表示整个交易失败,在交易处理器中对资源的所有改变都会被回滚(Roll back)。示例:

    async function sampleTransaction(tx) {
         // …
         throw new Error('example error');
         // The transaction gets failed, and all changes will be rolled back or discarded.
    }

    异步编程

    在之前版本的 Composer 中,对于异步的处理是通过 Promise,resolve(),then() 这类方式完成的。在当前版本中,对这种旧方式仍然是兼容的。但现在更建议使用 async/await 方式进行应用开发,这样使代码更符合通常的习惯。

    这是在 Composer 框架下开发 Fabric 区块链网络应用的一个重要知识点,如果之前没有接触过,建议查看更详细资料:await operator

    访问控制规则 (Access Control Rules)

    Hyperledger Composer 提供了 ACL(Access Control Language),使我们可以声明式的语言去定义用户、角色对于区块链业务网络、资源、域模型实例的访问权限。一系列规则被包括在 permissions.acl 文件中。

    清单 1. 一个典型的 Rule 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    rule BikeMaintainACL {
         description:    "ACR for bike maintenance, put on, call back, fix…"
         participant(bp):    "org.bikesharing.biznet.BikeProvider"
         operation:      ALL
         resource(b):    "org.bikesharing.biznet.Bike"
         transaction(tx):    "org.bikesharing.biznet.BikeReleaseTransaction"
         condition:      (b.provider.getIdentifier() == bp.getIdentifier())
         action:         ALLOW
    }

    基本语法

    1. Rule 名称。必须内容。

    ACL 文件中每个 Rule(规则)的名字都必须是唯一的。示例:

    rule SystemACL {
         //…
    }
    rule BikeMaintainACL {
         //…
    }

    2. 描述(description)。必须内容。

    3. 成员,即授权对象(participant)。必须内容。

    可为以下形式:

    • 域模型类型,如:org.bikesharing.biznet.BikeProvider
    • 域模型超类类型,如:org.hyperledger.composer.system.Participant
    • 一个具体的带 identifier 的实例:如:org.bikesharing.biznet.BikeProvider#bp_1
    • 一个命名空间,如:org.bikesharing.biznet.*
    • 递归处理的命名空间,如:org.bikesharing.**
    • 任意授权对象:"ANY" 或者 "**"(加双引号)

    此项设置可以绑定一个变量,以便在 Rule 内部被引用,如 BikeMaintainACL 示例中的 participant(bp)。

    4. 资源操作(operation)。必须内容。
    将要进行权限控制的对资源、网络的操作。

    可以为以下四种操作其中的一个或多个,多个时以逗号","分隔:CREATE,READ,UPDATE,DELETE。也可以为 ALL 表示所有操作。(都不加双引号)

    5. 资源(resource)。必须内容。

    可以为以下形式:

    • 域模型类型,如:org.bikesharing.biznet.Bike
    • 域模型超类类型,如:org.hyperledger.composer.system.Asset
    • 一个具体的带 identifier 的实例:如:org.bikesharing.biznet.Bike#B_1
    • 一个命名空间,如:org.bikesharing.biznet.*
    • 递归处理的命名空间,如:org.bikesharing.**
    • 任意资源:"**"(加双引号)

    此项设置可以绑定一个变量,以便在 Rule 内部被引用,如 BikeMaintainACL 示例中的 resource(b)。

    6. 授权操作(action)。必须内容。
    表示此项 Rule 最终的授权结果,可为:ALLOW 或者 DENY。

    7. 交易(transaction)。可选内容。

    如果此项不为空,则 Rule 中定义的对相应资源的操作权限控制会在 participant 提交此项 transaction 时被应用。

    8. 条件(condition)。可选内容。

    Condition 是一个 JavaScript 表达式。当其值为 true 时此 Rule 会被应用。

    权限决策表

    1. 如果 permissions.acl 文件不存在,或为空(Composer Playground 中不允许为空),则所有操作均视为 ALLOW。
    2. 如果此文件存在且不为空,则会按从上到下顺序进行权限评估,一旦 participant、resource、operation、transaction(可选)、condition(可选)都对应成功,则以此项 action 作为此种资源操作的权限评估结果,之后的 Rules 不会再被评估。
      如果没有找到对应的 Rule,则此项操作会被视作 DENY。

    备注

    1. 访问控制主要分为两种:网络访问控制,资源访问控制。

    网络访问控制包括对相关 CLI Command(composer network, composer identity, composer participant)的权限控制。一般而言,对于普通业务网络 participant,需要授予以下类似权限,否则,此 participant 则不能访问业务网络的基础功能。

    rule NormalACL {
         description:  "Normal ACL to permit base access"
         participant: "org.hyperledger.composer.system.Participant"
         operation: ALL
         resource: "org.hyperledger.composer.system.Network"
         action: ALLOW
    }

    在本地测试环境、初步学习状态下,请保持 permissions.acl 文件为空,或者需要以下 Rules:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    rule NetworkAdminUser {
         description: "Grant administrators full access to user resources"
         participant: "org.hyperledger.composer.system.NetworkAdmin"
         operation: ALL
         resource: "**"
         action: ALLOW
    }
     
    rule NetworkAdminSystem {
         description: "Grant administrators full access to system resources"
         participant: "org.hyperledger.composer.system.NetworkAdmin"
         operation: ALL
         resource: "org.hyperledger.composer.system.**"
         action: ALLOW
    }

    2. 访问控制是区块链网络中的一项非常重要的内容。基于 Composer 的权限控制模型直观方便,但仍需要更多的尝试与深刻理解,以保证业务网络的安全。

    建议可以使用 Composer Playground 进行快速简便的测试,而不需要反复部署 BND。

    我们可以在安装好的本地 Fabric 开发环境中启动 Composer Playground,也可以直接访问在线资源:在线 Hyperledger Composer Playground

    请注意:Playground 只可用于模拟,与实际部署的 Local Composer 可能稍有差异。

    查询

    Hyperledger Composer 提供了类似 SQL 的 Query Language,通过查询,我们得到符合一定条件的资源列表。定义查询的文件是 queries.qry。一个典型的 Query 示例:

    query selectBikesByStatus {
       description: "Select all bikes of the given status"
       statement:
           SELECT org.bikesharing.biznet.Bike
               WHERE (status == _$bikeStatus)
    }

    Composer Query Language 支持 SELECT、FROM、WHERE、AND、OR、CONTAINS、ORDER BY、SKIP、LIMIT 等操作。
    查询可以通过 REST Service 或 Composer API 进行访问。

    package.json

    中定义了 BND 的一些元数据(Metadata),它也符合 npm 包文件格式。示例如下:

    清单 2. package.json
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    {
       "name": "bikesharing-network",
       "version": "0.0.1",
       "description": "The bike sharing blockchain network",
       "author": "administrator",
       "email": "administrator@org.bikesharing.biznet",
       "license": "Apache-2.0",
       "devDependencies": {
         "composer-admin": "^0.19.2",
         "composer-cli": "^0.19.2",
         "composer-client": "^0.19.2",
         "composer-common": "^0.19.2",
    //…
       }
    }

    "name" 只能为标准 ASCII 字符及 "-"。"version" 为 Major.Minor.Micro 格式。

    BND 总结

    BND 定义了一个区块链业务网络的资源模型、交易处理器、访问控制规则,和一个包定义文件。它们会一起被打包为一个.bna 文件,并被部署到区块链网络上。
    这个 BND 定义是以 Composer 为基础的。会在 Composer Runtime 中被执行。

    在这一章中,Composer Modeling Language,ACL,Transaction Process Function 等相关开发技术的详细资料,可以参考这里:Reference Material for Hyperledger Composer

    一个最初的 bikesharing-network 实例

    我们在文章一开始,提到会建立一个实际意义上的区块链网络应用 bikesharing network。但随后就花了很多篇幅去学习 BND。这是因为 BND 在 Composer 开发框架占据重要地位,我们需要一个扎实的基础;而且,这一部分的内容先被尽量详细描述了,我们在以后的完整实例中,就可以只关注业务、功能的具体实现,不会再在细节上对 BND 描述过多。

    基础代码

    此部分介绍这个业务网络的基础代码。在本文中,只会实现最简化、直接的功能。主要目的是初始化、部署、启动这个业务网络。

    准备 BND 工作目录 bikesharing

    $ cd ~/fabric-tools/
    $ mkdir bikesharing-network
    $ cd bikesharing-network

    我们以后基本都在这个目录下工作。

    域模型

    新建文件 bikesharing-network/models/org.bikesharing.biznet.cto。其部分内容主要如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    // namespace
    namespace org.bikesharing.biznet
     
    // Enumerated constant values for bike status
    enum BikeStatus { // … }
     
    // A concept of contact information
    concept ContactInformation {
         o String firstName
         o String lastName
         // …
    }
     
    // Basic Participant class, for all actual participants.
    abstract participant BaseParticipant identified by pid{
         o String pid
         o ContactInformation contact
    }
     
    // Participant: bike provider, the company who release/launch bike for public.
    participant BikeProvider extends BaseParticipant {
         o String orgName
    }
     
    // Participant: bike user, the customer who will rent bike.
    participant BikeUser extends BaseParticipant {
    }
     
    // Bike asset class.
    asset Bike extends BaseAsset {
         o BikeStatus status
         --> BikeProvider provider
         o String remark optional
         --> BikeUser activeUser optional
    }
     
    // For BikeProvider, release a bike for public.
    transaction BikeReleaseTransaction extends BikeTransaction{
         --> BikeProvider provider
    }
     
    // For BikeUser, rent a bike.
    transaction BikeRentTransaction extends BikeTransaction {
         --> BikeUser user
    }

    通过 model file,我们定义了 enum BikeStatus,abstract participant,participant BikeProvider,Participant BikeUser,abstract asset,asset Bike,transaction BikeReleaseTransation,transaction BikeRentTransaction,以及一些其他的 abstract classes,concepts,transactions。

    此文件详细内容请参考:models/org.bikesharing.biznet.cto

    交易处理器

    新建文件 。其部分内容主要如下:

    清单 3. bikesharing-network/lib/logic.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /**
      * Processor function for BikeReleaseTransaction
      * @param {org.bikesharing.biznet.BikeReleaseTransaction} tx
      * @transaction
      */
    async function processBikeReleaseTransaction(tx) {
         tx.bike.status = BikeStatus.AVAILABLE;
    await updateBike(tx.bike);
    }
     
    /**
      * Processor function for BikeRentTransaction
      * @param {org.bikesharing.biznet.BikeRentTransaction} tx
      * @transaction
      */
    async function processBikeRentTransaction(tx) {
         tx.bike.status = BikeStatus.INUSE;
    await updateBike(tx.bike);
    }

    通过 processor function file,我们定义了对于所有交易的业务处理逻辑。

    此文件详细内容请参考:lib/logic.cs

    访问控制规则

    我们暂时忽略权限控制问题,以允许任何用户对任何资源的操作。

    可以不新建 ACL 文件;也可以新建 permissions.acl,但先保持其为空。权限控制处理问题会在以后章节讲解。

    package.json

    新建文件。定义这个 BND 的名称、版本号等信息。部分内容如下:

    清单 4. bikesharing-network/package.json
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    {
         "name": "bikesharing-network",
         "version": "0.0.1",
         "description": "A Fabric-Composer blockchain business network for bike sharing.",
         "author": "administrator",
         "email": "administrator@org.bikesharing.biznet",
         "license": "Apache-2.0",
         "devDependencies": {
             "composer-admin": "^0.19.2",
             "composer-cli": "^0.19.2",
             "composer-client": "^0.19.2",
             "composer-common": "^0.19.2",
             "composer-connector-embedded": "^0.19.2",
             "composer-cucumber-steps": "^0.19.2"
         }
    }

    其中,最重要的是 "name","version",它们的组合在当前业务网络中应具有唯一性。"composer archive create" 命令会自动生成类似 <name>@<version>.bna 文件。
    此文件详细内容请参考:package.json

    此部分基础代码作为一个单独的 branch,可在 GitHub bikesharing Branch step1 中找到。

    部署、启动

    在本文中,我们已经详细讲解了如何通过 Composer CLI 部署、启动 tutorial-network,我们可以用类似方法部署 bikesharing-network。

    部署 bikesharing-network

    $ composer archive create --sourceType dir --sourceName .

    运行成功后会按 package.json 中定义的 version 生成 bikesharing-network@0.0.1.bna 文件。

    $ composer network install --card PeerAdmin@hlfv1 --archiveFile bikesharing-
    network@0.0.1.bna
    $ composer network start --networkName bikesharing-network --networkVersion 0.0.1 --
    networkAdmin admin --networkAdminEnrollSecret adminpw --card PeerAdmin@hlfv1 --file
    admin.card
    $ composer card import --file admin.card
    $ composer network ping -c admin@bikesharing-network

    启动 REST Server

    $ composer-rest-server --card admin@bikesharing-network --namespaces "never" --port 3100

    将端口设置为 3100,以与默认的 3000 端口区别。

    访问与使用

    通过浏览器访问

    在浏览器中访问 http://<rest_server_host>:3100/explorer。请将 <rest_server_host> 替换 REST Server 所在机器的 IP 地址或可被解析的域名。成功页面如下:

    我们可以按第 1 部分中的的方法,添加一系列 Bike、BikeUser、BikeProvider,并可尝试提交一些 transaction。

    • 添加一个 BikeProvider participant(POST /BikeProvider):
    {
       "$class": "org.bikesharing.biznet.BikeProvider",
       "orgName": "MUB Bike Sharing Company",
       "pid": "bp_1",
       "contact": {
         "$class": "org.bikesharing.biznet.ContactInformation",
         "firstName": "Alice",
         "lastName": "MB",
         "phoneNumber": "1233456789",
         "email": "alice@mb"
       }
    }
    • 添加一个 BikeUser participant(POST /BikeUser):
    {
       "$class": "org.bikesharing.biznet.BikeUser",
       "pid": "bu_1",
       "contact": {
         "$class": "org.bikesharing.biznet.ContactInformation",
         "firstName": "Bob",
         "lastName": "Fabric",
         "phoneNumber": "987654321",
         "email": "bob@fabric"
       }
    }
    • 添加一个 Bike asset(POST /Bike):
    {
       "$class": "org.bikesharing.biznet.Bike",
       "status": "AVAILABLE",
       "provider": "resource:org.bikesharing.biznet.BikeProvider#bp_1",
       "remark": "",
       "aid": "b_1"
    }
    • 提交一个 Rent transaction(POST /BikeRentTransaction):
    {
       "$class": "org.bikesharing.biznet.BikeRentTransaction",
       "user": "resource:org.bikesharing.biznet.BikeUser#bu_1",
       "bike": "resource:org.bikesharing.biznet.Bike#b_1",
       "time": "2018-04-20T18:00:01+08:00"
    }

    提交成功后可以发现 Bike#b_1 的状态已经更改为:INUSE。我们正是通过 logic.js 里的方法 processBikeRentTransaction(tx) 实现这个业务逻辑的。
    同样道理,我们可以通过提交 Return transaction 更改自行车为 AVAILABLE,以实现"归还"自行车的业务逻辑。

    • 提交一个 Return transaction(POST /BikeReturnTransaction):
    {
       "$class": "org.bikesharing.biznet.BikeReturnTransaction",
       "user": "resource:org.bikesharing.biznet.BikeUser#bu_1",
       "bike": "resource:org.bikesharing.biznet.Bike#b_1",
       "time": "2018-04-20T18:30:11+08:00"
    }

    通过 Composer CLI、curl 等方式访问业务网络

    我们也可以通过以下方式访问 bikesharing-network:

    $ composer card list
    $ composer network list -c admin@bikesharing-network
    $ curl -X GET --header 'Accept: application/json' 'http://fabric11dev1:3100/api/Bike'

    扩展 bikesharing-network

    下面我们要对 BND 进行扩展,加入更多的功能,并升级部署这个业务网络。

    更新 BND

    我们可以通过 Composer upgrade 命令修改并升级部署 BND。因为区块链网络的共享、分布式、不可篡改等特性,我们在更新时,需要特别注意资源定义、交易处理的向前、向后兼容性。以减少对现有资源的影响,并为将来的业务发展提供合适的可扩展性、灵活性。

    上一章我们部署了一个初始的 bikesharing network,现在我们有了新的需求:添加查询功能、及使交易处理更新合理。

    添加查询

    新建文件 queries.qry,部分内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    query selectBikes {
       description: "Select all bikes"
       statement:
           SELECT org.bikesharing.biznet.Bike
    }
     
    query selectBikeRentTransaction {
       description: "Select bike rent transactions submitted by the user"
       statement:
           SELECT org.bikesharing.biznet.BikeRentTransaction
               WHERE (user == _$bikeUser)
    }

    文件详细内容请参考:queries.qry

    修改域模型

    在 BikeUser 中添加属性 activeBikeIds:

    participant BikeUser extends BaseParticipant {
         o String[] activeBikeIds optional
    }

    文件详细内容请参考:models/org.bikesharing.biznet.cto

    修改交易处理器

    修改 logic.js:

    只有状态为 "AVAILABLE" 的自行车才可以被租借,执行 BikeRentTransaction;

    只有状态为 "INUSE" 的自行车才可以被归还,执行 BikeReturnTransaction;

    当提交 BikeReleaseTransaction 与 BikeCallbackTransaction 时,provider 字段(位于 abstract BikeTransaction)必须与 bike.provider 相同,即自行车供应商只能对自己的自行车进行 release、callback 操作; 同理,BikeReturnTransaction 要求当前的 bike user 必须与 bike.activeUser 一致,即用户只能归还自己已经租借的自行车;

    租借自己车时,会设置 bike.activeUser 为当前用户;并会将此 bike id 加入 user.activeBikeIds 列表。

    部分程序如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    /**
      * Processor function for BikeCallbackTransaction
      * @param {org.bikesharing.biznet.BikeCallbackTransaction} tx
      * @transaction
      */
    async function processBikeCallbackTransaction(tx) {
         checkCurrentParticipant(tx.provider, tx.bike.provider);
         // We can callback bikes of all status.
         tx.bike.status = BikeStatus.CALLBACK;
         await updateBike(tx.bike);
    }
     
    /**
      * Processor function for BikeRentTransaction
      * @param {org.bikesharing.biznet.BikeRentTransaction} tx
      * @transaction
      */
    async function processBikeRentTransaction(tx) {
         if (tx.bike.status !== BikeStatus.AVAILABLE) {
             throw new Error('You cannot rent a bike which is not "AVAILABLE"');
         }
     
         // Change bike status and active user accordingly.
         tx.bike.status = BikeStatus.INUSE;
         tx.bike.activeUser = tx.user;
     
         // Add bike to user's active bikes list.
         if (tx.user.activeBikeIds === undefined) {
             tx.user.activeBikeIds = [];
         }
         tx.user.activeBikeIds.push(tx.bike.getFullyQualifiedIdentifier());
     
         await updateBike(tx.bike);
         await updateBikeUser(tx.user);
    }

    更新后的 js 文件详细内容请参考:lib/logic.js

    升级版本号

    修改 package.json 中的 version 属性,如:从 0.0.1 改为 0.0.2(即本文中的示例),使版本号顺序增加。也可以改成你所期望的其他版本号。"composer archive create" 命令会根据 version 生成 bikesharing-network@0.0.2.bna。如果不是 0.0.2,请在之后的操作中注意使用对应的版本号。

    package.json 文件详细内容请参考:package.json

    如果多次修改、部署 BNA,需要注意每次都要升级 version。

    此部分基础代码作为一个单独的 branch,可在 GitHub bikesharing Branch step2 中找到。

    部署新 BND

    在之前学习、部署的 bikesharing-network 基础之上,我们根据新的代码升级这个业务网络。可以将 Step2 代码覆盖 Step1 代码,也可以新建 Step2 目录。

    部署

    $ composer archive create --sourceType dir --sourceName .
    $ composer network install --card PeerAdmin@hlfv1 --archiveFile bikesharing-
    network@0.0.2.bna
    $ composer network upgrade --networkName bikesharing-network --networkVersion 0.0.2 --card
    PeerAdmin@hlfv1

    如果遇到执行错误,可尝试重启 Fabric,请参考上文"重启 Fabric" 及"重启 BND" 相关内容。

    如果重启了 Fabric,请注意在这里需要使用 composer network start 命令而不是 upgrade。

    重启 REST Server

    BND 更新后,需要重新启动 REST Server,请参考上文中的"启动 REST Server"。

    使用新的 Transaction Processor Functions

    下面介绍在新的业务网络中一些业务逻辑的实现方式。以下示例均通过浏览器访问 REST Server 完成。

    • 租借自行车,提交 BikeRentTransaction:
    {
       "$class": "org.bikesharing.biznet.BikeRentTransaction",
       "bike": "resource:org.bikesharing.biznet.Bike#b_1",
       "user": "resource:org.bikesharing.biznet.BikeUser#bu_1",
       "time": "2018-04-25T00:11:45.299Z"
    }

    如果执行成功,执行 Bike/GET,会发现 bike.activeUser 会被更新:

    {
         "$class": "org.bikesharing.biznet.Bike",
         "status": "INUSE",
         "provider": "resource:org.bikesharing.biznet.BikeProvider#bp_1",
         "remark": "",
         "activeUser": "resource:org.bikesharing.biznet.BikeUser#bu_1",
         "aid": "b_1"
    }

    执行 BikeUser/GET,会发现 user.activeBikeIds 会被更新:

    {
         "$class": "org.bikesharing.biznet.BikeUser",
         "activeBikeIds": [
           "org.bikesharing.biznet.Bike#b_1"
    ],
    "pid": "bu_1",
         "contact": {
           //…
         }
    }
    • 则将上述 Rent transaction 再提交一次,以触发 bike status error。系统会返回 Error Message 如下:
    {
       "error": {
         "statusCode": 500,
         "name": "Error",
    "message": "… Error: You cannot rent a bike which is not \"AVAILABLE\""
       }
    }
    • 新建另一个用户 bu_2:
    {
       "$class": "org.bikesharing.biznet.BikeUser",
       "pid": "bu_2",
       "contact": {
         "$class": "org.bikesharing.biznet.ContactInformation",
         "firstName": "Carnol",
         "lastName": "FF",
         "phoneNumber": "25485252",
         "email": "carnol@ff"
       }
    }
    • 尝试使用 bu_2 用户归还自行车,提交 BikeReturnTransaction:
    {
       "$class": "org.bikesharing.biznet.BikeReturnTransaction",
       "bike": "resource:org.bikesharing.biznet.Bike#b_1",
       "user": "resource:org.bikesharing.biznet.BikeUser#bu_2",
       "time": "2018-04-25T00:11:45.314Z"
    }

    系统会返回 Error Message,指明当前交易中指定的 participant 与租用自行车的 participant 不一致:

    {
       "error": {
         "statusCode": 500,
         "name": "Error",
         "message":  " … Error: The participants org.bikesharing.biznet.BikeUser#bu_2 - org.bikesharing.biznet.BikeUser#bu_1 are not matched"
       }
    }
    • 我们可以尝试其他交易,如:BikeReleaseTransaction,BikeCallTransaction 等,并与 Processor Functions 对应,查看其执行后果。

    使用查询

    在新的 REST Server 页面中,我们会发现新添加的查询已经被自动加载到页面,位于 Query 栏目下,展开此栏目,可以进行以下定义的查询操作。

    • GET /queries/selectBikes

    点击 Try it out! 即可得到所有的 Bikes 实例。

    • GET /queries/selectBikeRentTransaction

    在参数输入框 bikeUser 中输入"resource:org.bikesharing.biznet.BikeUser#bu_1",点击 Try it out!即可得到此用户 bu_1 提交的所有的 BikeRentTransaction 交易历史。

    结语

    我们设计了一个具有现实意义的 bikesharing network user story,以此为线索,一起学习了 BND 模型语言,并实现了 bikesharing network 的最基础代码,部署并使用了这个区块链业务网络。我们逐渐开始了区块链网络的应用开发,但还没有涉及权限、存储、节点管理等更深层次的内容,我们会在以后的学习中继续前进。


    展开全文
  • 《基于java+ssh+mysql实现的共享自行车租赁管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 使用技术: 前端使用技术:JSP,HTML5,CSS3、JavaScript等 后台使用技术:Spring、...
  • 海湾地区共享自行车临时使用者研究报告-2015.-美国加利福尼亚大学,伯克利可持续交通研究中心-外文-报告资料.pdf
  • 共享单车java源码路径 JsonPath 是 JSONPath 规范的 Java 实现。 有关规范的详细信息,请参见 。 此实现旨在模拟 和它的生命周期。 指定为字符串的 JsonPath 表达式必须首先编译为JsonPath的实例。 然后可以使用生成...
  • 本项目是一套基于SSM的共享单车管理系统,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本、软件工具、项目说明等,该项目可以直接作为毕设使用。 项目都...
  • 2021年中国主要城市共享单车、电单车骑行报告.pdf
  • 随着环保意识的增加,人们的出行越来越简单便捷,其中共享自行车是现在很多年轻人最热衷的出行方式之一,本系统主要是对共享自行车的信息进行管理。该系统的基本功能包括用户登录,区域信息管理,用户信息管理,用户...
  • 随着环保意识的增加,人们的出行越来越简单便捷,其中共享自行车是现在很多年轻人最热衷的出行方式之一,本系统主要是对共享自行车的信息进行管理。该系统的基本功能包括用户登录,区域信息管理,用户信息管理,用户...
  • 自行车共享系统是一种租用自行车的方式,通过遍布整个城市的售货亭位置网络,获得会员资格、租赁和自行车归还的过程是自动化的。 使用这些系统,人们可以从一个地方租一辆自行车,并根据需要将其归还到不同的地方。 ...
  • 2017-2025年中国共享电单车投放规模及预测.xls
  • 问题定义:无基座共享自行车的用户使用移动应用程序租用了遍布整个城市的自行车,将自行车锁定在目的地,然后将其提供给其他用户。 我们研究了无码头自行车共享系统是否可以通过提供经济高效且可持续的替代交通方式...
  • Python数据分析实战项目-共享单车有效的解决了“走路累,公交挤,开车堵,打车贵”的苦恼。一夜之间,北上广深、甚至部分二线城市,共享单车大街小巷随处可见。
  • vue-cli框架,反向代理解决跨域问题,使用百度地图api显示地图,定位和添加图标,mint-ui美化界面
  • 加载共享自行车租赁数据集 BikeSharing.csv。 按以下要求处理数据集 (1)分离出仅含特征列的部分作为 X 和仅含目标列的部分作为 Y。 (2)将数据集拆分成训练集和测试集(70%和 30%)。 (3)对数据进行标准化处理...
  • 预测城市单车共享系统的使用 这是一场花花公子的比赛,其中要求参与者将历史使用模式与天气数据结合起来,以便在华盛顿特区的Capital Bikeshare计划中预测自行车的租赁需求。 code文件夹包含用于“随机森林”,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,450
精华内容 3,380
关键字:

共享自行车