傳統(tǒng)機(jī)器學(xué)習(xí)預(yù)測(cè)客戶流失

image.png

一、機(jī)器學(xué)習(xí)預(yù)測(cè)客戶流失


Action,直接進(jìn)入主題,嘗試使用機(jī)器學(xué)習(xí),預(yù)測(cè)客戶流失。那么先把問(wèn)題定義好。

什么是客戶流失:就是客戶T月在網(wǎng)使用,但是T+2月離網(wǎng)了,使用到的數(shù)據(jù)都是T月或者之前的客戶數(shù)據(jù)。

整個(gè)項(xiàng)目主要分為:

  • 數(shù)據(jù)收集
  • 特征工程
  • 模型訓(xùn)練
  • 模型使用

二、數(shù)據(jù)收集與預(yù)處理


1、讀取收集數(shù)據(jù)

對(duì)客戶數(shù)據(jù)進(jìn)行收集,根據(jù)業(yè)務(wù)理解,提取盡量多的字段,數(shù)據(jù)保存在CSV文件,需要注意,要把表頭變成英文字符,不能有中文字符,內(nèi)容可以有中文,然后讀取并預(yù)處理,來(lái)段代碼:

# import各種庫(kù)
import pandas as pd   
import matplotlib.pyplot as plt
import numpy as np

#數(shù)據(jù)保存在number.csv文件中,讀取時(shí)注意,如果文件中有中文的內(nèi)容,需要加上encoding="gbk"
data = pd.read_csv("number.csv",encoding="gbk") 
data.shape   # (668946, 55),共有66萬(wàn)行,55個(gè)字段

2、預(yù)處理

1. 瀏覽數(shù)據(jù)

data.head(10)
image.png

2. 重點(diǎn)看number特征

data['number2'] = (data['number'].apply(str).str[:3]).apply(int)   #先轉(zhuǎn)化成string類型,再提取前三位,再轉(zhuǎn)化成int
print("缺失值::",data['number2'].isnull().sum())   #缺失值統(tǒng)計(jì)
print("數(shù)據(jù)shape:",data.shape)  #看數(shù)據(jù)量
print(data['number2'].value_counts())  #看統(tǒng)計(jì)
圖片.png

可以看出number列,沒(méi)有缺失值,但前三位有很多異常情況(比如208開頭的number),要洗掉。

# 號(hào)段信息,來(lái)源百度,未必十分準(zhǔn)確。
# 電信號(hào)段:133/153/180/181/189/177;
# 聯(lián)通號(hào)段:130/131/132/155/156/185/186/145/176;
# 移動(dòng)號(hào)段:134/135/136/137/138/139/150/151/152/157/158/159/182/183/184/187/188/147/178。

# drop掉前三位不對(duì)的信息
data2=copy.copy(data[(data.number2>130)&(data.number2<200)])
print("原數(shù)據(jù)行列結(jié)構(gòu):",data.shape)
print("新數(shù)據(jù)行列結(jié)構(gòu):",data2.shape)

補(bǔ)充說(shuō)明:這里刪掉了24萬(wàn)的數(shù)據(jù),都是不正常的號(hào)段,比如2開頭,3開頭等一些不是電話號(hào)碼的信息,可能是一些其他的賬戶信息,比如寬帶、行業(yè)卡等等。

image.png

洗掉后,原有行數(shù)由668946減少到423218了。

3. 定義標(biāo)簽

什么是客戶流失:就是客戶T月在網(wǎng)使用,但是T+2月離網(wǎng)了,使用到的數(shù)據(jù)都是T月或者之前的客戶數(shù)據(jù)。 從定義出發(fā):

1)T月在網(wǎng)使用客戶,只保留T月在使用的客戶。

data2 = copy.copy(data[(data.yonghuzhuangtai_201711=="正使用")|
                 (data.yonghuzhuangtai_201711=="停機(jī)")|
                 (data.yonghuzhuangtai_201711=="已轉(zhuǎn)換品牌")])

data2.shape

2)標(biāo)簽就是標(biāo)記T+2月離網(wǎng)的客戶

# 標(biāo)記為1的是離網(wǎng)客戶,0為在網(wǎng)客戶。
data2["yonghuzhuangtai"] = data2['yonghuzhuangtai_201801'].map({
'正使用':0,'停機(jī)':0,'已轉(zhuǎn)換品牌':0,
'欠費(fèi)銷戶':1,'正式銷戶':1,'預(yù)約銷戶':1,'null':1})

data2.shape
image.png

最后行數(shù)減少到417039行。

小結(jié):

經(jīng)過(guò)對(duì)number的清洗和標(biāo)簽的定義,行數(shù)由原來(lái)的668945行減少到417039行。預(yù)處理是一種比較粗的處理,特征工程則會(huì)更加的細(xì)致。


三、特征工程


經(jīng)過(guò)預(yù)處理后,數(shù)據(jù)基本可用,就進(jìn)入最重要的兩大部分,第一是特征工程,第二部分是模型訓(xùn)練,網(wǎng)上流傳:“有這么一句話在業(yè)界廣泛流傳:數(shù)據(jù)和特征決定了機(jī)器學(xué)習(xí)的上限,而模型和算法只是逼近這個(gè)上限而已。那特征工程到底是什么呢?顧名思義,其本質(zhì)是一項(xiàng)工程活動(dòng),目的是最大限度地從原始數(shù)據(jù)中提取特征以供算法和模型使用。”個(gè)人理解,落到項(xiàng)目上,就是數(shù)據(jù)有各種亂七八糟的情況,比如字符(中文或英文)、數(shù)值缺失等等,一般不能直接被模型使用,而特征工程就是對(duì)數(shù)據(jù)進(jìn)行處理,令其可以被模型讀取使用,而更好的特征工程,你可以根據(jù)原有特征生成新特征或者篩選重要特征等等,從而提升模型的效果。本項(xiàng)目現(xiàn)階段特征工程的腦圖如下:

圖片.png

1.object特征處理

數(shù)據(jù)類型(dtypes)為object的特征,就是字符(中文或英文)特征

#提取object及其對(duì)應(yīng)的數(shù)據(jù)
object_columns_df = data.select_dtypes(include=["object"])

#object羅列出來(lái)了。
print(object_columns_df.iloc[1])
print(object_columns_df.columns)

#深入了解object的內(nèi)容是什么
cols = object_columns_df.columns
for object_feature in cols:
    print('-------------------------------object_feature:',object_feature,'-------------------------------')
    print(data[object_feature].value_counts())   #value_counts()各種取值的統(tǒng)計(jì)量

圖中是其中一個(gè)特征的各種取值的統(tǒng)計(jì)量,可以看出,里面有三類中文取值,分別是“正使用”、“停機(jī)”、“已轉(zhuǎn)換品牌”。

image.png

這種特征叫做定性特征(相對(duì)定量特征),現(xiàn)在學(xué)到的機(jī)器學(xué)習(xí)算法是不能直接對(duì)定性特征進(jìn)行計(jì)算建模的,那就需要用get_dummies對(duì)定性特征啞編碼,這里要插入簡(jiǎn)單介紹一下啞編碼,就是每類取值變成單獨(dú)一個(gè)特征,然后用0、1標(biāo)識(shí)對(duì)應(yīng)行是否具備該特征,如下圖:

image.png

啞編碼

# 1、將中文換成英文字符
data['yonghuzhuangtai_201711']=data['yonghuzhuangtai_201711'].map({'停機(jī)':'stop_using','已轉(zhuǎn)換品牌':'change_brand','正使用':'using',})

# 2、將缺失值用null補(bǔ)上
data['yonghuzhuangtai_201711'].fillna(value = 'null', inplace = True)

# 3、get_dummies,那data_yonghuzhuangtai_201711就有啞編碼后的三列,分別是
# 'yonghuzhuangtai_201711_change_brand', 'yonghuzhuangtai_201711_stop_using', 'yonghuzhuangtai_201711_using'
data_yonghuzhuangtai_201711 = pd.get_dummies(data['yonghuzhuangtai_201711'], prefix= 'yonghuzhuangtai_201711')

# 4、跟原來(lái)的數(shù)據(jù)合并concat
data_concat = pd.concat([data, data_yonghuzhuangtai_201711], axis=1)

# 5、刪除被啞編碼的特征
data_concat = data_concat.drop(['yonghuzhuangtai_201711'],axis=1)

data = copy.copy(data_concat)
data.shape   #(417039, 71)

啞編碼后,數(shù)據(jù)的行數(shù)保持417039行,但是字段由57變成71列(1個(gè)標(biāo)簽,70個(gè)特征),最主要的變化是,每個(gè)特征里面都是int或者float的數(shù)字了,可以被模型讀取。

2.缺失值處理

首先,數(shù)據(jù)經(jīng)常會(huì)出現(xiàn)缺失值,這里采用最簡(jiǎn)單的處理原則,對(duì)于缺失值過(guò)多的,比如缺失90%的特征,直接刪除,幸好,基本最多缺失占比只有15%,采用最簡(jiǎn)單的處理方式,填0。

data.fillna(value = 0, axis = 1, inplace = True)

3.特征選擇

大白話點(diǎn)說(shuō),就是從原有的一堆特征中,選擇出那些離散的、相關(guān)的特征,從而簡(jiǎn)化模型和提高效率。明明25個(gè)特征可以搞定的,為什么一定要用70個(gè)呢。

  1. 看看有多少特征
data = data.drop(['number'],axis=1)   #number是各個(gè)客戶的ID,不屬于特征,刪掉。
print(data.shape)   #(417039, 70),有41萬(wàn)條記錄,70個(gè)字段(69個(gè)特征,1個(gè)標(biāo)簽)
  1. 離散程度,使用到方差(就是每個(gè)數(shù)據(jù)點(diǎn)距離平均值的差的平方和),如果方差是0,也就是整個(gè)特征都是一個(gè)取值,要來(lái)也沒(méi)意義,刪掉。另外,如果小于一定的值,也可以不要,但是這里需要注意,特征還沒(méi)經(jīng)過(guò)無(wú)量綱化,特征之間的方差大小不能對(duì)比的。
#計(jì)算顯示特征的方差
print(data.var())

#使用VarianceThreshold類進(jìn)行方差過(guò)濾
from sklearn.feature_selection import VarianceThreshold

#要生成這個(gè)類的對(duì)象,就需要一個(gè)參數(shù),就是最小方差的閾值,我們先設(shè)置為0.001,然后調(diào)用它的transform方法進(jìn)行特征值的過(guò)濾
variancethreshold=VarianceThreshold(threshold = 0.001)
variancethreshold.fit_transform(data)

#使用get_support方法,可以得到選擇特征列的序號(hào),然后根據(jù)這個(gè)序號(hào)在原始數(shù)據(jù)中把對(duì)應(yīng)的列名選擇出來(lái)即可
variancethreshold.get_support()

print('----------------------------------------')
print('原數(shù)據(jù)的shape:',data.shape)
print('滿足方差大于threshold的特征個(gè)數(shù):',data.columns[variancethreshold.get_support()].shape)
print('不滿足方差大于threshold的特征:',data.columns[variancethreshold.get_support()==False])

#再次強(qiáng)調(diào),這里只是好奇看看哪些方差這么小,并沒(méi)有刪除方差比0的特征

原有70個(gè)字段(其中一個(gè)是標(biāo)簽?。。?,方差小于0.001的有三個(gè),分別是:'shifoujiatingkuandaiyonghu', 'ruwangqudaoleixing_kefuqudao','ruwangqudaoleixing_null'。


image.png
  1. 基于樹模型的特征選擇法
    直接使用隨機(jī)森林,對(duì)數(shù)據(jù)進(jìn)行建模,提取模型中對(duì)每個(gè)特征的importance系數(shù)。
from sklearn.ensemble import RandomForestClassifier

#訓(xùn)練模型,不管任何參數(shù),都用默認(rèn)的
random_forest = RandomForestClassifier(oob_score=True, random_state=10)
random_forest.fit(X_train,y_train.values.ravel())

#提取模型結(jié)果對(duì)各個(gè)特征的importance----feature_importances_
feature_importances_df_1 = pd.DataFrame(random_forest.feature_importances_,columns=["importances"],index=X_train.columns)
print(feature_importances_df_1.sort_values(axis = 0,ascending = False, by = 'importances'))

#提取importance大于平均值的特征
mean_importances = feature_importances_df_1.mean().importances
feature_importances_df_max_1 = copy.copy(feature_importances_df_1[feature_importances_df_1['importances']>mean_importances])
predictors = feature_importances_df_max_1.index.tolist()
predictors.append('yonghuzhuangtai')  #加上標(biāo)簽字段

importance系數(shù)較大的特征截圖


image.png

提煉了69個(gè)特征中的30個(gè),其他特征刪掉。

  1. 基于Logistics Regression看特征正負(fù)作用
    直接使用logistics regression模型,對(duì)數(shù)據(jù)進(jìn)行訓(xùn)練,提取每個(gè)特征對(duì)應(yīng)的系數(shù),從正負(fù)號(hào)看出每個(gè)特征對(duì)最
    終標(biāo)簽的正負(fù)影響。
from sklearn.linear_model import LogisticRegression
#1、訓(xùn)練模型
lr = LogisticRegression(penalty = 'l1')  #直接默認(rèn)參數(shù)
lr.fit(X_train,y_train.values.ravel())  #用原始數(shù)據(jù)訓(xùn)練

#2、提取系數(shù)
lr_coef_df = pd.DataFrame(lr.coef_.T,columns=["lr_coef_df"],index=X_train.columns)

#3、跟randomforest的結(jié)果合并同一個(gè)dataframe
df = pd.merge(feature_importances_df_max_2, lr_coef_df, left_index=True, right_index=True, how='left')
print(df)

yonghuzhuangtai_201711_using,是負(fù)數(shù),那么就是對(duì)離網(wǎng)是負(fù)影響,也就是有這個(gè)1標(biāo)識(shí),越不會(huì)離網(wǎng)
yonghuzhuangtai_201711_stop_using,是正數(shù),那么就是對(duì)離網(wǎng)是正影響,有這個(gè)1標(biāo)識(shí),就越會(huì)離網(wǎng)
基本跟認(rèn)識(shí)一致。

image.png

6.后續(xù)提升

異常值的詳細(xì)查看、無(wú)量綱化、降維、正態(tài)分布/冪律分布分析等并未深入了解,待分析。
補(bǔ)充說(shuō)明:之前嘗試過(guò)對(duì)數(shù)據(jù)進(jìn)行無(wú)量綱化,但是卡在兩個(gè)問(wèn)題上:
第一:異常值,如果對(duì)數(shù)據(jù)進(jìn)行歸一化的無(wú)量綱處理,前提要把異常值踢掉,比如apru值,有500多的少數(shù)用戶,歸一化就會(huì)把正常用戶壓縮在一個(gè)小范圍內(nèi),其實(shí)不歸一化也會(huì),還是回歸到怎么處理異常,怎么定義異常上了。
第二:分布規(guī)律,基本接觸到的機(jī)器學(xué)習(xí)處理,都默認(rèn)數(shù)據(jù)是正態(tài)分布的,但是從arpu值、mou值、活躍日數(shù)等數(shù)據(jù)的分布來(lái)看,都不是正態(tài),而是冪律分布,那么用到的算法要適當(dāng)調(diào)整嗎?

image.png


四、模型訓(xùn)練


經(jīng)常說(shuō)80%的時(shí)間在特征學(xué)習(xí),20%的時(shí)間在模型訓(xùn)練,還真覺(jué)得對(duì)啊。另外,強(qiáng)大的sklearn都把模型封裝好了,直接用就是?,F(xiàn)在的思路是各種ensemble模型輪流來(lái)一次看看效果,選幾個(gè)還不錯(cuò)的繼續(xù)調(diào)參優(yōu)化。

1. 各種ensemble模型,默認(rèn)參數(shù)跑

image.png

(Logistics Regression不是ensemble model)

以隨機(jī)森林random forest為例跑一次,其他模型大同小異

# 數(shù)據(jù)準(zhǔn)備 
#1、將特征X和標(biāo)簽Y拆分開
X = data.loc[:, data.columns != 'yonghuzhuangtai']
y = data.loc[:, data.columns == 'yonghuzhuangtai']

#2、然后隨機(jī)提取80%的數(shù)據(jù)作為模型訓(xùn)練用,20%數(shù)據(jù)留作模型性能測(cè)試用
from sklearn.model_selection  import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.2, random_state = 0)
from sklearn.ensemble import RandomForestClassifier

#1、生成模型對(duì)象,參數(shù)都是默認(rèn)
random_forest = RandomForestClassifier() 
#2、用那80%的數(shù)據(jù)進(jìn)行模型訓(xùn)練,其實(shí)就一句話
random_forest.fit(X_train,y_train.values.ravel()) 
#3、用訓(xùn)練的模型對(duì)剩下的20%數(shù)據(jù)進(jìn)行預(yù)測(cè),將預(yù)測(cè)結(jié)果和已知標(biāo)簽對(duì)比,得出模型性能
y_pred = random_forest.predict(X_test.values) 

#4、畫出性能圖
plt.figure()
plot_confusion_matrix(y_test,y_pred,title='Confusion matrix')

image.png

判斷標(biāo)準(zhǔn)

結(jié)果出來(lái),是一個(gè)混淆矩陣,橫坐標(biāo)是預(yù)測(cè),縱坐標(biāo)是實(shí)際發(fā)生,性能主要看三個(gè)指標(biāo):

  1. recall 召回率,真實(shí)流失客戶中,多少被預(yù)判為流失。


    image.png
  2. precision 準(zhǔn)確率,預(yù)測(cè)為流失的客戶中,真的會(huì)走的的有多少。


    image.png
  1. f1,綜合考慮recall 和 precision的指標(biāo)。


    image.png

再解釋通俗講一遍就是,模型預(yù)測(cè)的1000個(gè)客戶,有800個(gè)確實(shí)最后離網(wǎng)了,80%的precision,但是也有另外800個(gè)真實(shí)離網(wǎng)的沒(méi)被預(yù)測(cè)到,50%的recall。預(yù)測(cè)的都蠻準(zhǔn),但是預(yù)測(cè)不全。

各個(gè)模型的效果對(duì)比

默認(rèn)參數(shù)下,GradientBoostingClassifier、RandomForest、XGBClassifier明顯效果好一點(diǎn)。

#       GradientBoostingClassifier  LogisticRegression  RandomForest  \
# 0.1                     0.579078            0.414419      0.506922   
# 0.2                     0.647005            0.498207      0.602151   
# 0.25                    0.653581            0.525630      0.602367   
# 0.3                     0.657226            0.550074      0.629484   
# 0.35                    0.654224            0.524365      0.629584   
# 0.4                     0.649972            0.499580      0.631519   
# 0.45                    0.646009            0.485224      0.631757   
# 0.5                     0.641439            0.469859      0.615846   
# 0.6                     0.616350            0.418735      0.587390   
# 0.65                    0.593640            0.361297      0.587639   
# 0.7                     0.566000            0.276610      0.552564   
# 0.75                    0.536923            0.190199      0.552240   
# 0.8                     0.501413            0.114034      0.466256   
# 0.85                    0.442625            0.064789      0.466127   
# 0.9                     0.341222            0.034093      0.322901   
# time                   66.251000            4.351000     15.549000   

#       AdaBoostClassifie  ExtraTreesClassifier  XGBClassifier  MLPClassifier  
# 0.1            0.125537              0.501672       0.570283       0.008401  
# 0.2            0.125537              0.597911       0.643224       0.008401  
# 0.25           0.125537              0.597909       0.650471       0.008401  
# 0.3            0.125537              0.617750       0.651945       0.008401  
# 0.35           0.125537              0.618192       0.647942       0.008401  
# 0.4            0.125537              0.613068       0.644493       0.008401  
# 0.45           0.125770              0.612934       0.641509       0.008401  
# 0.5            0.623428              0.591254       0.635485       0.008401  
# 0.6            0.000000              0.563729       0.610550       0.008401  
# 0.65           0.000000              0.563729       0.585824       0.008401  
# 0.7            0.000000              0.520726       0.561148       0.008401  
# 0.75           0.000000              0.520726       0.536541       0.008401  
# 0.8            0.000000              0.450475       0.490799       0.008401  
# 0.85           0.000000              0.450450       0.426007       0.008401  
# 0.9            0.000000              0.320902       0.332662       0.008401  
# time          33.884000              5.247000      38.831000      28.706000  

2、模型調(diào)參

調(diào)參是什么,就是一個(gè)模型有很多參數(shù),比如random forest 隨機(jī)森林,有樹的數(shù)量,樹的深度等等,需要設(shè)置的,那么設(shè)置多少最好呢,都不知道,那就暴力點(diǎn),每種都試試,這就是調(diào)參咯,試出最好的那個(gè)參數(shù)組,random forest主要要調(diào)節(jié)的參數(shù)有:

  • n_estimators
  • max_depth
  • min_samples_split
  • min_samples_leaf
  • max_features

對(duì)以上5個(gè)參數(shù)都要進(jìn)行調(diào)參,逐一GridSearchCV,只拿n_estimators調(diào)參舉例,具體如下,試一下50,70,90,100,120,150中各種取值的效果,提取效果最好的那個(gè)參數(shù):

randomforest_param_grid = {'n_estimators':list((50,70,90,100,120,150))}

grid = GridSearchCV(RandomForestClassifier(min_samples_split=100,min_samples_leaf=20,max_depth=8,\
                                          max_features='sqrt',oob_score=True,random_state=10),\
                   param_grid=randomforest_param_grid, cv=5 ,scoring = 'f1')#scoring = 'roc_auc' or 'f1'
# 這里多說(shuō)兩句:
# param_grid:需要交叉驗(yàn)證的參數(shù),這里有6個(gè)數(shù)據(jù),分別是50,70,90,100,120,150,究竟哪個(gè)參數(shù)出來(lái)的效果最好呢?
# cv=5,就是5折交叉試驗(yàn),把數(shù)據(jù)分為5分,每次提取其中4份跑模型,1份留作驗(yàn)證,5次的平均表現(xiàn)是評(píng)定標(biāo)準(zhǔn)。
#      每個(gè)參數(shù)都跑5次,取平均值再對(duì)比才有說(shuō)服力,那么就總共跑了5*6次,30次了。
# scoring = 'f1',那么效果最好的這個(gè)效果是什么標(biāo)準(zhǔn)呢?可以是‘a(chǎn)ccuracy’,‘roc_auc’,這里選擇'f1'

grid.fit(X_train,y_train.values.ravel())

# 記錄最好的參數(shù)
best_n_estimators = grid.best_estimator_.n_estimators
print(best_n_estimators)

調(diào)參明細(xì):

  • n_estimators: list((50,70,90,100,120,150))
  • max_depth: list((3,7,11,15))
  • min_samples_split: list((50,75,100,135,150))
  • min_samples_leaf: list((20,40,60,80))
  • max_features: list((5,6,7,8,9,11,15,20,25))

這里是最花時(shí)間的,每個(gè)參數(shù)經(jīng)常要1個(gè)小時(shí)才能出來(lái)最優(yōu)那個(gè),5個(gè)參數(shù)基本就是一個(gè)晚上,才能出來(lái)一組最優(yōu)參數(shù)組,最后f1一般能提升1%-3.5%。本項(xiàng)目random forest模型調(diào)參后f1達(dá)到0.620960,提升0.919%,GradientBoostingClassifier調(diào)參后提升到0.629094,提升了2.514%,比random forest調(diào)參后也高0.8134%。

image.png

五、模型使用


可以使用歷史數(shù)據(jù)訓(xùn)練出來(lái)的模型對(duì)當(dāng)前數(shù)據(jù)進(jìn)行預(yù)測(cè),具體的預(yù)測(cè)效果如何呢?試過(guò)一個(gè)假設(shè),T月的流失客戶訓(xùn)練出來(lái)的模型,f1是60%,然后用到T+1的全量數(shù)據(jù)中進(jìn)行預(yù)測(cè),f1是57%,低了3%,數(shù)據(jù)還算是有延續(xù)性,可以預(yù)測(cè)。


六、使用環(huán)境介紹


  • 語(yǔ)言:python
  • IDE:anaconda
  • 寫作:簡(jiǎn)書

小結(jié):由于本人水平有限,本文內(nèi)容估計(jì)有很多錯(cuò)漏的地方,希望各位路過(guò)有緣人指出,學(xué)習(xí)學(xué)習(xí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容