2.装饰模式&lt,本节的流失规则预测基于决策树算

日期:2019-10-07编辑作者:摄影

原图

1)连续变量离散化处理

js55658com金沙 1

4)决策树

js55658com金沙 2

使用:

分别对 A、B、明度通道进行调节,参数设置如下图。

4)决策树

js55658com金沙 3

4)流失率计算

将这7个群组按照是否流失进行汇总,求出各群组的流失率

js55658com金沙 4

对以上的汇总结果进行变量排序和变量重命名后输出到表格中展示,如下:

 js55658com金沙 5

//从打印结果可以得出,韩梅梅我们只要克隆李雷,然后修改他的名字就可以了,无需重新创建let a = Programmer(age: 18, sex: "M", language: "swift")a.name = "李雷"print/*▿ Prototype.Programmer #0▿ name: Optional- some: "李雷"- age: 18- sex: "M"- language: "swift"Prototype.Programmer*/let b = a.clone()b.name = "韩梅梅"print/*▿ Prototype.Programmer #0▿ name: Optional- some: "韩梅梅"- age: 18- sex: "M"- language: "swift"Prototype.Programmer*/

效果图

1、离散型变量

五、、建立模型

使用:

js55658com金沙 6

3)连续变量与连续变量

可以通过散点图直观展示,也可通过计算相关系数来展示:

2)有序性离散变量

话务量级别:

 js55658com金沙 7

js55658com金沙 8

let result: Int = IntInterpreter.interpreter(input: "14 14")print//28let result2: String = StringInterpreter.interpreter(input: "14 14")print//1414

1、打开素材图片,选择菜单:图像 > 模式 > Lab模式,创建曲线调整图层,

3)随机抽取训练集和测试集

 js55658com金沙 9

4)建立神经网络模型

 js55658com金沙 10

js55658com金沙 11

js55658com金沙 12

5)模型分析和评估

js55658com金沙 13

js55658com金沙 14

js55658com金沙 15

js55658com金沙 16

js55658com金沙 17

js55658com金沙 18

 

import Foundationenum NoticeType { case Lev1 //老板到公司门口了 case Lev2 //老板进来办公室了}protocol ObserverProtocol {//定义了一个协议,实现 func notice(type: NoticeType)}//公司前台小妹final class Reception { var observers: [ObserverProtocol]? func noticeLev1() { noticeEveryOne(lev: .Lev1) } func noticeLev2() { noticeEveryOne(lev: .Lev2) } private func noticeEveryOne(lev: NoticeType) { for obj in observers! { obj.notice(type: lev) } }}//好员工class Staff: ObserverProtocol { func notice(type: NoticeType) { print("员工(String(describing: self))说:老板来了就来了呗,一直在专心工作") }}//员工afinal class StaffA: Staff { override func notice(type: NoticeType) { switch type { case .Lev1: print("员工(String(describing: self))说:不怕,继续看动画。") default: print("员工(String(describing: self))说:不怕,我是老板侄儿,他不会骂我的。") } }}//员工Bfinal class StaffB: Staff { override func notice(type: NoticeType) { switch type { case .Lev1: print("员工(String(describing: self))说:赶紧关了,打开Xcode。") default: print("员工(String(describing: self))说:恩,这破电脑,现在才打开Xcode,还好老板一进来已经打开了。") } }}

js55658com金沙 19

本节的内容是衔接上节数据挖掘宽表处理的部分,上节分析了电信业客户流失问题分析预测的准备工作,这节继续进行探索性分析和建模分析及模型评估,客户流失预测分为流失规则的预测以及流失评分预测。本节的流失规则预测基于决策树算法,流失评分预测基于神经网络算法实现。

2、流失规则预测模型

js55658com金沙 20

实现:

js55658com金沙 21

3)使用模型查看器查看决策树分类规则 

Tariff_OK in [ "High CAT 100" "High CAT 50" "High Play 100" ] [ 模式:1 ] => 1 

Tariff_OK in [ "OK" ] [ 模式:0 ] 

    Handset in [ "ASAD170" "BS210" "CAS60" "S80" "WC95" ] [ 模式:0 ] => 0 

    Handset in [ "ASAD90" ] [ 模式:1 ] 

       Usage_Band = 中使用率 [ 模式:1 ] => 1 

       Usage_Band = 低使用率 [ 模式:0 ] => 0 

       Usage_Band = 极高使用率 [ 模式:1 ] 

           Gender = 女 [ 模式:1 ] 

              Peak_mins_Ratio <= 0.830 [ 模式:1 ] => 1 

              Peak_mins_Ratio > 0.830 [ 模式:0 ] 

                  Peak_mins_Trend <= 7.424 [ 模式:1 ] => 1 

                  Peak_mins_Trend > 7.424 [ 模式:0 ] => 0 

           Gender = 男 [ 模式:0 ] => 0 

       Usage_Band = 高使用率 [ 模式:1 ] 

           Age <= 51 [ 模式:1 ] => 1 

           Age > 51 [ 模式:0 ] => 0 

    Handset in [ "BS110" ] [ 模式:0 ] 

       Peak_mins_Ratio <= 0.491 [ 模式:0 ] 

           National_calls <= 88 [ 模式:0 ] 

              Gender = 女 [ 模式:0 ] => 0 

              Gender = 男 [ 模式:1 ] => 1 

           National_calls > 88 [ 模式:1 ] 

              AveOffPeak <= 13.254 [ 模式:1 ] => 1 

              AveOffPeak > 13.254 [ 模式:0 ] => 0 

       Peak_mins_Ratio > 0.491 [ 模式:0 ] 

           International_mins <= 178.474 [ 模式:0 ] 

              AveNational <= 10.161 [ 模式:0 ] => 0 

              AveNational > 10.161 [ 模式:0 ] 

                  Gender = 女 [ 模式:0 ] => 0 

                  Gender = 男 [ 模式:1 ] => 1 

           International_mins > 178.474 [ 模式:0 ] 

              International_mins_Ratio <= 0.183 [ 模式:0 ] => 0 

              International_mins_Ratio > 0.183 [ 模式:1 ] => 1 

    Handset in [ "CAS30" ] [ 模式:1 ] 

       call_cost_per_min <= 7.915 [ 模式:0 ] => 0 

       call_cost_per_min > 7.915 [ 模式:1 ] 

           Usage_Band in [ "中使用率" "极高使用率" "高使用率" ] [ 模式:1 ] => 1 

           Usage_Band in [ "低使用率" ] [ 模式:1 ] 

              Peak_calls <= 176 [ 模式:1 ] 

                  AveOffPeak <= 1.591 [ 模式:0 ] => 0 

                  AveOffPeak > 1.591 [ 模式:1 ] => 1 

              Peak_calls > 176 [ 模式:0 ] => 0 

    Handset in [ "S50" ] [ 模式:0 ] 

js55658com金沙,       Total_Cost <= 99.515 [ 模式:0 ] 

           Tariff in [ "CAT 100" "CAT 200" ] [ 模式:0 ] => 0 

           Tariff in [ "CAT 50" "Play 300" ] [ 模式:0 ] => 0 

           Tariff in [ "Play 100" ] [ 模式:1 ] => 1 

       Total_Cost > 99.515 [ 模式:0 ] 

           Age <= 25 [ 模式:0 ] 

              International_mins <= 181.009 [ 模式:0 ] 

                  Gender = 女 [ 模式:1 ] => 1 

                  Gender = 男 [ 模式:0 ] => 0 

              International_mins > 181.009 [ 模式:1 ] 

                  average cost min <= 0.145 [ 模式:0 ] => 0 

                  average cost min > 0.145 [ 模式:1 ] => 1 

           Age > 25 [ 模式:0 ] 

              International_mins <= 178.126 [ 模式:0 ] 

                  Gender = 女 [ 模式:1 ] => 1 

                  Gender = 男 [ 模式:0 ] => 0 

              International_mins > 178.126 [ 模式:0 ] => 0 

    Handset in [ "SOP10" "SOP20" ] [ 模式:1 ] => 1 

四、探索性数据分析

import Foundation//假设一个人要去访问朋友ABCD//访客协议protocol VisitorProtocol { func visit(planet: FriendA) func visit(planet: FriendB) func visit(planet: FriendC) func visit(planet: FriendD)}//朋友的协议protocol FriendProtocol { func accept(vistor: VisitorProtocol)}//Aclass FriendA: FriendProtocol { func accept(vistor: VisitorProtocol) { vistor.visit(planet: self) }}//Bclass FriendB: FriendProtocol { func accept(vistor: VisitorProtocol) { vistor.visit(planet: self) }}//Cclass FriendC: FriendProtocol { func accept(vistor: VisitorProtocol) { vistor.visit(planet: self) }}//Dclass FriendD: FriendProtocol { func accept(vistor: VisitorProtocol) { vistor.visit(planet: self) }}//访客class Visitor: VisitorProtocol { var address = "" func visit(planet: FriendA) { address = "访问了朋友A" } func visit(planet: FriendB) { address = "访问了朋友B" } func visit(planet: FriendC) { address = "访问了朋友C" } func visit(planet: FriendD) { address = "访问了朋友D" }}

;

2)离散变量与连续变量

高峰期通话时长与流失之间的关系:

js55658com金沙 22

js55658com金沙 23

在0.05的显著性水平下,由F值可以看出流失客户与不流失客户的高峰期通话时长有着显著差异。

3、变量之间关系的探索性分析

回到顶部

1)名义型离散变量

使用描述图形进行探索性分析:

eg: 手机品牌的分布:

s<-summary(churn_analysis$Handset)

pie(s)    #手机品牌分布

 js55658com金沙 24

js55658com金沙 25

js55658com金沙 26

js55658com金沙 27

5)特征分析

取流失率较高的两个群组(高流失客户群体),分析他们的特征,找出可能的流失原因。取聚类-1和聚类5两个群组,进行特征分析

js55658com金沙 28

js55658com金沙 29

流失率较高的群组特征概括:

群组编号

群组占比

流失率

客户主要特征

特征概括

聚类-1

13.6%

0.148

总花费较低
平均每分钟花费高
处免费时长外计费时长少
高峰与非高峰通话时长少
周末通话时长较长
使用的资费方案为play

低价值客户
周末电话为主
资费方案有待优化

聚类-5

10.3%

0.083

总花费较高
高峰通话时间长,非高峰短
周末电话占比低
周末通话次数少,但通话时间较长

较高价值客户
上班族,以工作电话为主
周末亲情电话

以上为流失率较高的两类客户的特征概括,可以将这种模型提供给运营和营销人员,方便他们根据客户特征制定相关的营销策略,有效率地提高流失召回效率。

回到顶部<h1 >3.代理模式</h1>代理模式,为其他对象提供一种代理以控制对这个对象的访问。

2)类型节点处理

js55658com金沙 30

3)随机抽取训练集和测试集

 js55658com金沙 31

let algorithm = Algorithm(index: 10)var iterator = algorithm.makeIterator()for _ in 1...10 {print((iterator.next!)}/*打印结果:102030405060708090100*/

4)流失率计算

将这7个群组按照是否流失进行汇总,求出各群组的流失率

js55658com金沙 32

对以上的汇总结果进行变量排序和变量重命名后输出到表格中展示,如下:

 js55658com金沙 33

1)分区

按照7:3分配训练集和测试集,也可改变该分配比例来比较分类预测的效果

 js55658com金沙 34

let builder = LabelBuilder(text: "按钮", color: .orange, rect: CGRect(x: 100, y: 100, width: view.frame.width-200, height: 30))//通过自定义标签的表示,用同一个构造方法构建标签let label = LabelDirector.creatLableWithBuilder(builder: builder)view.addSubview

8)模型分析

 js55658com金沙 35

js55658com金沙 36

 结果显示模型的整体预测准去率达到了94.61%,而且模型的命中率为61.82%,模型的查全率为75.78%。

3)K-均值聚类

当k=7时,得到的聚类成果如下:

js55658com金沙 37

回到顶部<h1 >11.状态模式</h1>状态模式,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

6)生成SQL脚本

a) 生成模型后选择生成SQL脚本  

*注:boosting默认不能生成SQL脚本

js55658com金沙 38

b) 接下来,将SQL脚本导入PL/SQL中:

文件—>打开—>SQL脚本

c) 将数据EXCEL表导入PL/SQL中:

对于数据集较小的表:

可以先在数据库中建立一个表(CLASS)

js55658com金沙 39

最终显示的结果为C0和C1两列值,C0表示的是预测值,C1表示预测的准确率。

3)使用模型查看器查看决策树分类规则 

Tariff_OK in [ "High CAT 100" "High CAT 50" "High Play 100" ] [ 模式:1 ] => 1 

Tariff_OK in [ "OK" ] [ 模式:0 ] 

    Handset in [ "ASAD170" "BS210" "CAS60" "S80" "WC95" ] [ 模式:0 ] => 0 

    Handset in [ "ASAD90" ] [ 模式:1 ] 

       Usage_Band = 中使用率 [ 模式:1 ] => 1 

       Usage_Band = 低使用率 [ 模式:0 ] => 0 

       Usage_Band = 极高使用率 [ 模式:1 ] 

           Gender = 女 [ 模式:1 ] 

              Peak_mins_Ratio <= 0.830 [ 模式:1 ] => 1 

              Peak_mins_Ratio > 0.830 [ 模式:0 ] 

                  Peak_mins_Trend <= 7.424 [ 模式:1 ] => 1 

                  Peak_mins_Trend > 7.424 [ 模式:0 ] => 0 

           Gender = 男 [ 模式:0 ] => 0 

       Usage_Band = 高使用率 [ 模式:1 ] 

           Age <= 51 [ 模式:1 ] => 1 

           Age > 51 [ 模式:0 ] => 0 

    Handset in [ "BS110" ] [ 模式:0 ] 

       Peak_mins_Ratio <= 0.491 [ 模式:0 ] 

           National_calls <= 88 [ 模式:0 ] 

              Gender = 女 [ 模式:0 ] => 0 

              Gender = 男 [ 模式:1 ] => 1 

           National_calls > 88 [ 模式:1 ] 

              AveOffPeak <= 13.254 [ 模式:1 ] => 1 

              AveOffPeak > 13.254 [ 模式:0 ] => 0 

       Peak_mins_Ratio > 0.491 [ 模式:0 ] 

           International_mins <= 178.474 [ 模式:0 ] 

              AveNational <= 10.161 [ 模式:0 ] => 0 

              AveNational > 10.161 [ 模式:0 ] 

                  Gender = 女 [ 模式:0 ] => 0 

                  Gender = 男 [ 模式:1 ] => 1 

           International_mins > 178.474 [ 模式:0 ] 

              International_mins_Ratio <= 0.183 [ 模式:0 ] => 0 

              International_mins_Ratio > 0.183 [ 模式:1 ] => 1 

    Handset in [ "CAS30" ] [ 模式:1 ] 

       call_cost_per_min <= 7.915 [ 模式:0 ] => 0 

       call_cost_per_min > 7.915 [ 模式:1 ] 

           Usage_Band in [ "中使用率" "极高使用率" "高使用率" ] [ 模式:1 ] => 1 

           Usage_Band in [ "低使用率" ] [ 模式:1 ] 

              Peak_calls <= 176 [ 模式:1 ] 

                  AveOffPeak <= 1.591 [ 模式:0 ] => 0 

                  AveOffPeak > 1.591 [ 模式:1 ] => 1 

              Peak_calls > 176 [ 模式:0 ] => 0 

    Handset in [ "S50" ] [ 模式:0 ] 

       Total_Cost <= 99.515 [ 模式:0 ] 

           Tariff in [ "CAT 100" "CAT 200" ] [ 模式:0 ] => 0 

           Tariff in [ "CAT 50" "Play 300" ] [ 模式:0 ] => 0 

           Tariff in [ "Play 100" ] [ 模式:1 ] => 1 

       Total_Cost > 99.515 [ 模式:0 ] 

           Age <= 25 [ 模式:0 ] 

              International_mins <= 181.009 [ 模式:0 ] 

                  Gender = 女 [ 模式:1 ] => 1 

                  Gender = 男 [ 模式:0 ] => 0 

              International_mins > 181.009 [ 模式:1 ] 

                  average cost min <= 0.145 [ 模式:0 ] => 0 

                  average cost min > 0.145 [ 模式:1 ] => 1 

           Age > 25 [ 模式:0 ] 

              International_mins <= 178.126 [ 模式:0 ] 

                  Gender = 女 [ 模式:1 ] => 1 

                  Gender = 男 [ 模式:0 ] => 0 

              International_mins > 178.126 [ 模式:0 ] => 0 

    Handset in [ "SOP10" "SOP20" ] [ 模式:1 ] => 1 

回到顶部<h1 >12.适配器模式</h1>适配器模式,将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

3、变量之间关系的探索性分析

 2)建立决策树模型

 js55658com金沙 40

回到顶部<h1 >9.观察者模式</h1>观察者模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

2)离散目标变量(churn)更改为连续目标变量(churncore)

将1取值为100

0取值为0

js55658com金沙 41

5)查看分类训练和预测结果

js55658com金沙 42

使用:

 1)缺失值处理

将空值取值为0

js55658com金沙 43

1)离散变量与离散变量

使用网络图分析:

js55658com金沙 44

交叉列联表和卡方检验:SPSS Moderler输出节点“矩阵”,进行列联表分析:

js55658com金沙 45

import Foundation//假设有一家杂货店,一开始老板不知道卖什么,有人来买,马上就制造,进货后就会不会缺货,我们就可以使用享元模式,将有人买过的东西保存起来共享,再有人买直接拿出来就可以,不用再去进新的货。//商品struct Commodity: CustomStringConvertible {//CustomStringConvertible该协议能够使自定义输出实例的description var commodity: String var description: String { get { return "商品名称:" commodity } }}//杂货店class GroceryStore {//商品列表 private var list = [String: Commodity]()//mutating关键字作用:在方法中修改struct和enum变量,如果不加,会提示无法修改结构体成员 func buyCommodity(name: String) -> Commodity {//无货,制造,制造好后,放到list中共享 if !list.keys.contains { print("没有这个货,给你制造!") list[name] = Commodity(commodity: name) }else { print("有货,直接给你拿!") } return list[name]! }}

5)特征分析

取流失率较高的两个群组(高流失客户群体),分析他们的特征,找出可能的流失原因。取聚类-1和聚类5两个群组,进行特征分析

js55658com金沙 46

js55658com金沙 47

流失率较高的群组特征概括:

群组编号

群组占比

流失率

客户主要特征

特征概括

聚类-1

13.6%

0.148

总花费较低
平均每分钟花费高
处免费时长外计费时长少
高峰与非高峰通话时长少
周末通话时长较长
使用的资费方案为play

低价值客户
周末电话为主
资费方案有待优化

聚类-5

10.3%

0.083

总花费较高
高峰通话时间长,非高峰短
周末电话占比低
周末通话次数少,但通话时间较长

较高价值客户
上班族,以工作电话为主
周末亲情电话

以上为流失率较高的两类客户的特征概括,可以将这种模型提供给运营和营销人员,方便他们根据客户特征制定相关的营销策略,有效率地提高流失召回效率。

1、细分类模型——聚类

适用于:客户价值较低的客户群

思路:使用客户的属性变量和行为变量(不包括是否流失)对客户进行聚类分析,分析各个群组的流失率情况,找出流失率较高的群组,并分析刻画他们的特征,以便业务人员有针对性的制订营销策略。

js55658com金沙 48

回到顶部<h1 >8.建造者模式</h1>建造者模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

2)有序性离散变量

话务量级别:

 js55658com金沙 49

js55658com金沙 50

1)名义型离散变量

使用描述图形进行探索性分析:

eg: 手机品牌的分布:

s<-summary(churn_analysis$Handset)

pie(s)    #手机品牌分布

 js55658com金沙 51

js55658com金沙 52

js55658com金沙 53

js55658com金沙 54

定义:

 2)建立决策树模型

 js55658com金沙 55

3)连续变量与连续变量

可以通过散点图直观展示,也可通过计算相关系数来展示:

实现:

四、探索性数据分析

6)生成SQL脚本

a) 生成模型后选择生成SQL脚本  

*注:boosting默认不能生成SQL脚本

js55658com金沙 56

b) 接下来,将SQL脚本导入PL/SQL中:

文件—>打开—>SQL脚本

c) 将数据EXCEL表导入PL/SQL中:

对于数据集较小的表:

可以先在数据库中建立一个表(CLASS)

js55658com金沙 57

最终显示的结果为C0和C1两列值,C0表示的是预测值,C1表示预测的准确率。

实现:

五、、建立模型

2、连续型变量

绘图:直方图、箱线图

在网时长和总通话费用的图形展现:

 js55658com金沙 58

js55658com金沙 59

使用:

4)建立神经网络模型

 js55658com金沙 60

js55658com金沙 61

js55658com金沙 62

5)模型分析和评估

js55658com金沙 63

js55658com金沙 64

js55658com金沙 65

js55658com金沙 66

js55658com金沙 67

js55658com金沙 68

 

7)模型评估

提升图:

 js55658com金沙 69

js55658com金沙 70

图形结果显示,提升度随RPP(正类预测比例)的提高呈降序分布,且提升度较高,说明模型的预测准确率较高,比随机预测提升了较高的水平。

ROC曲线:

js55658com金沙 71

ROC曲线显示预测模型对1的敏感度很高,说明模型的预测效果很好。

回到顶部<h1 >7.外观模式</h1>外观模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

1、细分类模型——聚类

适用于:客户价值较低的客户群

思路:使用客户的属性变量和行为变量(不包括是否流失)对客户进行聚类分析,分析各个群组的流失率情况,找出流失率较高的群组,并分析刻画他们的特征,以便业务人员有针对性的制订营销策略。

js55658com金沙 72

1)连续变量离散化处理

js55658com金沙 73

回到顶部

1)分区

按照7:3分配训练集和测试集,也可改变该分配比例来比较分类预测的效果

 js55658com金沙 74

本节的内容是衔接上节数据挖掘宽表处理的部分,上节分析了电信业客户流失问题分析预测的准备工作,这节继续进行探索性分析和建模分析及模型评估,客户流失预测分为流失规则的预测以及流失评分预测。本节的流失规则预测基于决策树算法,流失评分预测基于神经网络算法实现。

使用

2、流失规则预测模型

js55658com金沙 75

 1)缺失值处理

将空值取值为0

js55658com金沙 76

import Foundation//定义了一套问题模板class Question { final func question() { print("如果有一天,不写程序了,你会去做什么?") print("我会去:") }//默认是养猪 func answer() -> String { return "养猪" }}//子类修改answer方法来修改结果class PersonA: Question { override func answer() -> String { return "下海经商" }}class PersonB: Question { override func answer() -> String { return "自己开公司" }}

7)模型评估

提升图:

 js55658com金沙 77

js55658com金沙 78

图形结果显示,提升度随RPP(正类预测比例)的提高呈降序分布,且提升度较高,说明模型的预测准确率较高,比随机预测提升了较高的水平。

ROC曲线:

js55658com金沙 79

ROC曲线显示预测模型对1的敏感度很高,说明模型的预测效果很好。

2)离散变量与连续变量

高峰期通话时长与流失之间的关系:

js55658com金沙 80

js55658com金沙 81

在0.05的显著性水平下,由F值可以看出流失客户与不流失客户的高峰期通话时长有着显著差异。

使用:

1)离散变量与离散变量

使用网络图分析:

js55658com金沙 82

交叉列联表和卡方检验:SPSS Moderler输出节点“矩阵”,进行列联表分析:

js55658com金沙 83

2)类型节点处理

js55658com金沙 84

使用:

5)查看分类训练和预测结果

js55658com金沙 85

2)离散目标变量(churn)更改为连续目标变量(churncore)

将1取值为100

0取值为0

js55658com金沙 86

import Foundationclass Singleton { var index = 0 static let share = Singleton() private init() {}}

3、流失评分预测模型(神经网络算法实现)

 js55658com金沙 87

1、离散型变量

import Foundation//定义了一个算法,利用迭代器后,会依次输出结果struct Algorithm { var index: Int}//定义了该算法的迭代器struct AlgorithmIterator: IteratorProtocol { private var current = 1 var begin: Int init(begin: Int) { self.begin = begin } mutating func next() -> Algorithm? { defer { current  = 1 } return Algorithm(index: current * begin) }}//扩展了该算法,增加一个迭代器方法extension Algorithm: Sequence { func makeIterator() -> AlgorithmIterator { return AlgorithmIterator(begin: index) }}

2、连续型变量

绘图:直方图、箱线图

在网时长和总通话费用的图形展现:

 js55658com金沙 88

js55658com金沙 89

8)模型分析

 js55658com金沙 90

js55658com金沙 91

 结果显示模型的整体预测准去率达到了94.61%,而且模型的命中率为61.82%,模型的查全率为75.78%。

import Foundation//定义一个总的工厂类,让其子类决定创建出什么样的对象class Factory { func createProduct() -> String { return "电视" }}//长虹子类决定只创建长虹电视class ChangHoneFactory: Factory { override func createProduct() -> String { return "长虹电视" }}//海尔子类只创建海尔电视class HaierFactory: Factory { override func createProduct() -> String { return "海尔电视" }}

3)K-均值聚类

当k=7时,得到的聚类成果如下:

js55658com金沙 92

3、流失评分预测模型(神经网络算法实现)

 js55658com金沙 93

定义:

回到顶部<h1 >20.中介者模式</h1>中介者模式,用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

let phone = iPhone()//装饰器增加了功能var decorator = PhoneDecorator(phone: phone)print(decorator.call//苹果打电话print(decorator.video//苹果看电影decorator = PhoneDecoratorNet(phone: phone)print(decorator.call//流量-苹果打电话print(decorator.video//流量-苹果看电影decorator = PhoneDecoratorWifi(phone: phone)print(decorator.call//WIFI-苹果打电话print(decorator.video//WIFI-苹果看电影

实现:

let map = Map()let camera = Camera()//把对应app给控制类,运行控制类的抽象接口,则会运行app的接口实现let control = Controlcontrol.open()//打开地图,开始定位!control.app = cameracontrol.open()//打开摄像头,开始拍照!

回到顶部<h1 >6.模板方法模式</h1>模板方法模式(Template Method),定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

let staff1 = Staff()let staff2 = StaffA()let staff3 = StaffB()let reception = Reception()reception.observers = [staff1, staff2, staff3]//公司员工123都关注前台小妹的通知,当老板快要进办公室时,小妹会通知所有人reception.noticeLev1()//老板到公司门口了,小妹发通知/*员工Observer.Staff说:老板来了就来了呗,一直在专心工作员工Observer.StaffA说:不怕,继续看动画。员工Observer.StaffB说:赶紧关了,打开Xcode。*/reception.noticeLev2()//老板进办公室了,小妹发通知/*员工Observer.Staff说:老板来了就来了呗,一直在专心工作员工Observer.StaffA说:不怕,我是老板侄儿,他不会骂我的。员工Observer.StaffB说:恩,这破电脑,现在才打开Xcode,还好老板一进来已经打开了。*/

实现:

import Foundation//画图案的协议protocol DrawProtocol { func draw()}class Circle: DrawProtocol { func draw() { print }}class Square: DrawProtocol { func draw() { print }}class Triangle: DrawProtocol { func draw() { print("我负责画三角形") }}class Print: DrawProtocol { var drawer = [DrawProtocol]() func addDrawer(_ drawer: DrawProtocol...) { self.drawer.append(contentsOf: drawer) } func draw() { _ = drawer.map{$0.draw()} }}

使用:

import Foundationprotocol Phone { func call() -> String func video() -> String}class iPhone: Phone { func call() -> String { return "苹果打电话" } func video() -> String { return "苹果看电影" }}//父装饰器class PhoneDecorator: Phone { var phone: Phone init(phone: Phone) { self.phone = phone } func call() -> String { return phone.call() } func video() -> String { return phone.video() }}//增加流量功能final class PhoneDecoratorNet: PhoneDecorator { override func call() -> String { return "流量-(phone.call" } override func video() -> String { return "流量-(phone.video" }}//增加wifi功能class PhoneDecoratorWifi: PhoneDecorator { override func call() -> String { return "WIFI-(phone.call" } override func video() -> String { return "WIFI-(phone.video" }}
//修改programmer的state状态,即修改了programmer的programming()的行为let happy = State(mood: .happy)let programmer = Programmer(state: happy)programmer.programming()//心情不错,开开心心的写程序let sad = State(mood: .sad)programmer.state = sadprogrammer.programming()//心情糟糕,不想写程序let normal = State(mood: .normal)programmer.state = normalprogrammer.programming()//心情正常,慢慢悠悠的写程序

使用:

回到顶部<h1 >22.解释器模式</h1>解释器模式(Interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

import Foundation//问题协议protocol QuestionProtocol {//指定自己回答不出来,下一个回答的人 var next: QuestionProtocol? {get set}//该方法用于问问题 func answerQuestion(question: String)}struct Student: QuestionProtocol { var name: String var canAnswerQuestion: String var next: QuestionProtocol? func answerQuestion(question: String) { switch question { case canAnswerQuestion: print回答:1 1=2") case canAnswerQuestion: print回答:1*2=2") case canAnswerQuestion: print回答:2*2=4") case canAnswerQuestion: print回答:3*2=6") default: if let next = next { next.answerQuestion(question: question) }else { print("这个问题没人知道答案!") } } }}

定义:

<h1 >14.组合模式</h1>组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

  • 1.策略模式
  • 2.装饰模式
  • 3.代理模式
  • 4.工厂方法模式
  • 5.原型模式
  • 6.模板方法模式
  • 7.外观模式
  • 8.建造者模式
  • 9.观察者模式
  • 10.抽象工厂模式
  • 11.状态模式
  • 12.适配器模式
  • 13.备忘录模式
  • 14.组合模式
  • 15.迭代器模式
  • 16.单例模式
  • 17.桥接模式
  • 18.命令模式
  • 19.职责链模式
  • 20.中介者模式
  • 21.享元模式
  • 22.解释器模式
  • 23.访问者模式<h1 >1.策略模式</h1>策略模式,它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
import Foundationenum MoodState { case happy, sad, normal}//状态struct State { var mood: MoodState}//一个程序员class Programmer { var state: State init(state: State) { self.state = state } func programming() { switch state.mood { case .happy: print("心情不错,开开心心的写程序") case .sad: print("心情糟糕,不想写程序") case .normal: print("心情正常,慢慢悠悠的写程序") } }}
//虚拟代理,youth控制了child的行为let virtual = Youth()virtual.run()//孩子跑了virtual.cry()//孩子哭了//保护代理,对于控制孩子开门这个行为,增加了一个保护,如果没有孩子这个实例,则自己去开门let parent = Parent()parent.open()//没有孩子,我自己来开门parent.haveChild(have: true)parent.open()//好的,马上来开门

实现:

使用:

回到顶部<h1 >18.命令模式</h1>命令模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

//定义了一个程序员原型,假设有一大群程序员,他们之间的区别就是姓名不同,其余都相同class Programmer { var name: String? var age: Int var sex: String var language: String init(age: Int, sex: String, language: String) { self.language = language self.age = age self.sex = sex }//可以克隆自己 func clone() -> Programmer { return Programmer(age: age, sex: sex, language: language) }}
let factory = SteelFactory(name: "成都钢铁厂")let factoryLow = SteelFactoryLow(name: "劣质钢铁厂")let mediator = Mediator(stellFactory: factory)let company = RobotCompany(mediator: mediator, name: "成都机器人公司")//开始制造let robot = company.create() as! Robotprint(robot.createFrom "制造的机器人(robot.name),采用的是" robot.steel.createFrom "生产的" robot.steel.name "!")//成都机器人公司制造的机器人阿狸机器人,采用的是成都钢铁厂生产的优质钢材!//中介者更换了钢铁厂,钢铁厂和机器人公司是没有引用的mediator.steelFactory = factoryLowlet robot1 = company.create() as! Robotprint(robot1.createFrom "制造的机器人(robot1.name),采用的是" robot1.steel.createFrom "生产的" robot1.steel.name "!")//成都机器人公司制造的机器人阿狸机器人,采用的是劣质钢铁厂生产的劣质钢材!

回到顶部<h1 >17.桥接模式</h1>桥接模式,将抽象部分与它的实现部分分离,使它们都可以独立地变化。

定义:

//不同的工厂子类决定了要生成的实例var factory: Factory = ChangHoneFactory()print("创建出了:(factory.createProduct//创建出了:长虹电视factory = HaierFactory()print("创建出了:(factory.createProduct//创建出了:海尔电视

回到顶部<h1 >2.装饰模式</h1>装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

let stu1 = Student(name: "小明", canAnswerQuestion: "1 1", next: nil)let stu2 = Student(name: "小黄", canAnswerQuestion: "1*2", next: stu1)let stu3 = Student(name: "小芳", canAnswerQuestion: "2*2", next: stu2)let stu4 = Student(name: "小辉", canAnswerQuestion: "3*2", next: stu3)//从4开始,自动依次调用,直到有人回答或者都没人回答结束stu4.answerQuestion(question: "3*2")//小辉回答:1 1=2stu4.answerQuestion(question: "2*2")//小芳回答:1 1=2stu4.answerQuestion(question: "1*2")//小黄回答:1 1=2stu4.answerQuestion(question: "1 1")//小明回答:1 1=2stu4.answerQuestion(question: "3*3")//这个问题没人知道答案!
//定义出游戏ab,分别指定适配器let gameA = GameA()let gameB = GameB()let adapterA = AdapterGameA(game: gameA)let adapterB = AdapterGameB(game: gameB)//游戏开始了,分别按下asdw按键adapterA.a()//Adapter.GameA左移动游戏角色adapterA.s()//Adapter.GameA下移动游戏角色adapterA.d()//Adapter.GameA右移动游戏角色adapterA.w()//Adapter.GameA上移动游戏角色adapterB.a()//Adapter.GameB左移动游戏角色adapterB.s()//Adapter.GameB蹲下游戏角色adapterB.d()//Adapter.GameB右移动游戏角色adapterB.w()//Adapter.GameB跳起游戏角色

使用:

//实例化了一个门,定义了门的动作let door = Door(name: "客厅门")let open = DoorAction(type: .open, door: door)let close = DoorAction(type: .close, door: door)let lock = DoorAction(type: .lock, door: door)let unlock = DoorAction(type: .unlock, door: door)//实例化了门管理者let manager = DoorManager()//添加门的动作manager.add(open, close, lock, unlock)//执行添加了的命令manager.execute()/*客厅门执行开门命令!客厅门执行关门命令!客厅门执行上锁命令!客厅门执行解锁命令!*/

使用:

import Foundationimport UIKit//定义了金钱的算法acceptcash,分别实现protocol CashBase { //所有计算都要遵循该协议,实现该方法 func acceptCash(cash: CGFloat) -> CGFloat}//正常class CashNormal: CashBase { func acceptCash(cash: CGFloat) -> CGFloat { return cash }}//打折class CashRobate: CashBase { var moneyRebate: CGFloat init(rebate: CGFloat) { moneyRebate = rebate } func acceptCash(cash: CGFloat) -> CGFloat { return moneyRebate * cash }}//减免class CashReturn: CashBase { var moneyReturn: CGFloat init(retur: CGFloat) { moneyReturn = retur } func acceptCash(cash: CGFloat) -> CGFloat { return cash - moneyReturn }}enum CashType { case Normal case Robate case Return}class CashContext { var cashBase: CashBase init(type: CashType) { switch type { case .Normal: cashBase = CashNormal() case .Robate: cashBase = CashRobate(rebate: 0.5) case .Return: cashBase = CashReturn(retur: 10) } } func getResult(money: CGFloat) -> CGFloat { return cashBase.acceptCash(cash: money) }}

回到顶部<h1 >5.原型模式</h1>原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

//创建对象需要的表示,需要用户自己定制struct LabelBuilder { var text: String var color: UIColor var rect: CGRect}class LabelDirector {//对象的构建,需要传入表示 static func creatLableWithBuilder(builder: LabelBuilder) -> UILabel { let label = UILabel(frame: builder.rect) label.text = builder.text label.textColor = builder.color label.font = UIFont.systemFont(ofSize: 20) label.textAlignment = .center return label }}
import Foundation//定义一种新的语法,用字符表示,解释"1 2"这个字符串的含义protocol Interpreter {//返回一个泛型Result static func interpreter<Result>(input: String) -> Result}//整型解释器struct IntInterpreter: Interpreter { internal static func interpreter<Result>(input: String) -> Result { let arr = input.components(separatedBy: " ") return (Int(arr.first!)!   Int(arr.last!)!) as! Result }}//字符解析器struct StringInterpreter: Interpreter { internal static func interpreter<Result>(input: String) -> Result { let arr = input.components(separatedBy: " ") return (arr.first!   arr.last!) as! Result }}

定义:

实现:

<h1 >23种常用设计模式</h1>

回到顶部<h1 >10.抽象工厂模式</h1>抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

实现:

import Foundation//产品protocol ProductProtocol { var factory: String { get set } func showYouself()}struct Television: ProductProtocol { var factory: String func showYouself() { print("生产的电视") }}struct Refrigerator: ProductProtocol { var factory: String func showYouself() { print("生产的冰箱") }}//工厂enum ProductType { case Television, Refrigerator}class Factory { static func createProduct(type: ProductType) -> ProductProtocol { switch type { case .Television: return Television(factory: "工厂") default: return Refrigerator(factory: "工厂") } }}
import Foundationenum DoorActionType { case open, close, lock, unlock}//命令协议,命令需要实现execute方法protocol CommandProtocol { func execute()}//门struct Door { var name: String}//门可以执行的操作:开门,关门,上锁,解锁class DoorAction: CommandProtocol { var actionType: DoorActionType var door: Door init(type: DoorActionType ,door: Door) { actionType = type self.door = door } func execute() { switch actionType { case .open: print("(door.name)执行开门命令!") case .close: print("(door.name)执行关门命令!") case .lock: print("(door.name)执行上锁命令!") case .unlock: print("(door.name)执行解锁命令!") } }}//命令管理者class DoorManager { var actions = [CommandProtocol]()//添加命令 func add(_ actions: CommandProtocol...) { self.actions  = actions }//执行命令 func execute() { _ = actions.map{$0.execute()} }}

回到顶部<h1 >23.访问者模式</h1>访问者模式,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

回到顶部<h1 >16.单例模式</h1>单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。

//工厂类提供了生产所有产品的接口,使用者无需知道要生产的具体类,只需要告诉工厂要的产品类型即可let tv = Factory.createProduct(type: .Television)let bx = Factory.createProduct(type: .Refrigerator)tv.showYouself()//工厂生产的电视bx.showYouself()//工厂生产的冰箱
import Foundationclass Robot {//只需要调用该接口即可,内部的子系统无需使用者依次调用 static func creatRobot() { Head.createHead() Body.createBody() Arm.createArm() Leg.createLeg() }}class Head { static func createHead() { print }}class Body { static func createBody() { print }}class Arm { static func createArm() { print }}class Leg { static func createLeg() { print }}
//使用不同的算法,获得不同的结果let context = CashContext(type: .Normal)print("Normal结果:(context.getResult(money: 100))")//Normal结果:100let retur = CashContext(type: .Return)print("Retrun结果:(retur.getResult(money: 100))")//Retrun结果:90let robate = CashContext(type: .Robate)print("Robate结果:(robate.getResult(money: 100))")//Robate结果:50

实现:

使用:

实现:

定义:

使用:

//分别创建出朋友let friends: [FriendProtocol] = [FriendA(), FriendB(), FriendC(), FriendD()]//每个朋友都去访问let visitors = friends.map{ (friend: FriendProtocol) -> Visitor inlet visitor = Visitor()//访问过后,自己的数据就变了friend.accept(vistor: visitor)return visitor}print(dump)/*▿ 4 elements▿ Visitor.Visitor #0- address: "访问了朋友A"▿ Visitor.Visitor #1- address: "访问了朋友B"▿ Visitor.Visitor #2- address: "访问了朋友C"▿ Visitor.Visitor #3- address: "访问了朋友D"[Visitor.Visitor, Visitor.Visitor, Visitor.Visitor, Visitor.Visitor]*/

回到顶部<h1 >13.备忘录模式</h1>备忘录模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

Robot.creatRobot()/*制造头制造身体制造手臂制造腿*/

回到顶部<h1 >15.迭代器模式</h1>迭代器模式,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。

回到顶部<h1 >19.职责链模式</h1>职责链模式(Chain of Responsibility),使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

//单个对象可以单独使用draw函数,也可以组合到一起,使用组合后的drawlet a = Circle()let b = Square()let c = Triangle//我负责画圆b.draw()//我负责画方形c.draw()//我负责画三角形let p = Print()p.addDrawerp.draw()/*我负责画圆我负责画方形我负责画三角形*/
//假如说游戏a中,asdw按钮分别代表游戏角色 左 下 右 上 移动,但是在游戏b中,asdw分别代表 左 蹲下 跳跃 右 的动作,此时,适配器模式就体现出用途了,游戏b写一个适配器即可使用asdw按键//游戏协议,分别定义出asdw四个键按下后需要实现的方法protocol AdapterProtocol { func a() func s() func d() func w()}//游戏对应的适配器class AdapterGameA: AdapterProtocol { var game: GameA init(game: GameA) { self.game = game } func a() { game.left() } func s() { game.down() } func d() { game.right() } func w() { game.up() }}class AdapterGameB: AdapterProtocol { var game: GameB init(game: GameB) { self.game = game } func a() { game.left() } func s() { game.squat() } func d() { game.right() } func w() { game.jump() }}//两款游戏class GameA { func left() { print("(String(describing: self))左移动游戏角色") } func down() { print("(String(describing: self))下移动游戏角色") } func right() { print("(String(describing: self))右移动游戏角色") } func up() { print("(String(describing: self))上移动游戏角色") }}class GameB { func left() { print("(String(describing: self))左移动游戏角色") } func squat() { print("(String(describing: self))蹲下游戏角色") } func right() { print("(String(describing: self))右移动游戏角色") } func jump() { print("(String(describing: self))跳起游戏角色") }}
import Foundation//虚拟代理protocol Action { func run() func cry()}class Children: Action { func run() { print } func cry() { print }}class Youth: Action { lazy private var children: Children = Children() func run() { children.run() } func cry() { children.cry() }}//保护代理protocol Door { func open()}class Child: Door { func open() { print("好的,马上来开门!") }}class Parent: Door { private var child: Child! func haveChild(have: Bool) { guard have else { return } child = Child() } func open() { guard child != nil else { print("没有孩子,我自己来开门") return } child.open() }}
import Foundation//假设一款游戏里,一个角色有生命,蓝量两个状态,当用户要打boss前,可以先备份一下,打之前状态,发现打不过时,可以重新开始,从头打BOSSstruct RollState { var life: Int var blue: Int}class Roll { var state: RollState init(state: RollState) { self.state = state } func saveState() -> RollState { return state } func restoreState(state: RollState) { self.state = state } func kill() { state.life = 0 state.blue = 0 }}

使用:

使用:

import Foundation//接口协议protocol InterfaceProtocol { var app: RealizeProtocol {get set} func open()}//实现协议protocol RealizeProtocol { func appOpen()}//操作类class Control: InterfaceProtocol { var app: RealizeProtocol init(app: RealizeProtocol) { self.app = app } func open() { app.appOpen() }}//地图class Map: RealizeProtocol { func appOpen() { print("打开地图,开始定位!") }}//相机class Camera: RealizeProtocol { func appOpen() { print("打开摄像头,开始拍照!") }}

使用:

使用:

使用:

回到顶部<h1 >21.享元模式</h1>享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。

let state = RollState(life: 100, blue: 100)//初始化角色let roll = Roll(state: state)let mementoState = roll.saveState()print(dump/*打印角色初始状态▿ Memento.Roll #0▿ state: Memento.RollState- life: 100- blue: 100Memento.Roll*/roll.kill()print(dump/*角色死亡状态▿ Memento.Roll #0▿ state: Memento.RollState- life: 0- blue: 0Memento.Roll*/roll.restoreState(state: mementoState)print(dump/*角色恢复后状态▿ Memento.Roll #0▿ state: Memento.RollState- life: 100- blue: 100Memento.Roll*/

使用:

回到顶部<h1 >4.工厂方法模式</h1>工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

let shop = GroceryStore()let commodity1 = shop.buyCommodity(name: "电视")//没有电视,会去创建新的对象print(commodity1)/*没有这个货,给你制造!商品名称:电视*/let commodity2 = shop.buyCommodity(name: "电视")//已经有电视了,去共享的list中取print(commodity2)/*有货,直接给你拿!商品名称:电视*/

实现:

实现:

使用:

使用:

定义:

实现:

定义:

使用:

import Foundation//制造协议protocol CreateProtocol { var name: String {get set} func create() -> Any}//钢铁struct Steel { var name: String var createFrom: String}//机器人结构体struct Robot { var name: String var steel: Steel var createFrom: String}//优质造铁厂class SteelFactory: CreateProtocol { var name: String init(name: String) { self.name = name } func create() -> Any { return Steel(name: "优质钢材", createFrom: name) }}//劣质造铁厂class SteelFactoryLow: CreateProtocol { var name: String init(name: String) { self.name = name } func create() -> Any { return Steel(name: "劣质钢材", createFrom: name) }}//制造机器人的公司class RobotCompany: CreateProtocol { var mediator: Mediator var name: String init(mediator: Mediator, name: String) { self.name = name self.mediator = mediator }//机器人制造公司需要钢材,然后向中介者要钢材,中介者去向工厂要。中介者和工厂没有相互引用,工厂可以被替换。 func create() -> Any { return Robot(name: "阿狸机器人", steel: mediator.needSteel(), createFrom: name) }}//中介者class Mediator { var steelFactory: CreateProtocol init(stellFactory: SteelFactory) { self.steelFactory = stellFactory }//向中介者要钢材 func needSteel() -> Steel { return steelFactory.create() as! Steel }}
//single是单例let single = Singleton.shareprint(single.index)//0single.index = 100print(single.index)//100//无论获取多少次,都是同一个实例print(Singleton.share.index)//100

实现:

定义:

设计模式在Swift中的应用,使用的是Swift3.0。本文项目Github地址:

let s = Question()s.question()//如果有一天,不写程序了,你会去做什么?//我会去:养猪let a = PersonA()a.question()//如果有一天,不写程序了,你会去做什么?//我会去:下海经商let b = PersonB()b.question()//如果有一天,不写程序了,你会去做什么?//我会去:自己开公司

本文由js55658com金沙发布于摄影,转载请注明出处:2.装饰模式&lt,本节的流失规则预测基于决策树算

关键词: js55658com金沙

增加霞光的过程分为两大步,点小图查看大图&

Photoshop给河边婚片加上唯美的霞光 (载入中...) 来源:PS结盟 作者:Sener素材图片为晴到高多云摄像,全体有一点点...

详细>>

效果如图3,凯史科技世界(www.kfchina.org)

; 如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如图如...

详细>>

图片增加霞光会经常用到,再在合适的位置渲染

Photoshop给树林草地中的人物加上暖色霞光 (载入中...) 来源:PS联盟作者:Sener素材图片天空部分是白色的,画面层...

详细>>

Photoshop调出仿刘芳视觉效果

Photoshop调出仿刘芳视觉效果。效果图 ; 步骤: 原图...

详细>>