CreditCard_01.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. import sys
  2. import pandas as pd
  3. from sklearn.ensemble import RandomForestRegressor
  4. import matplotlib.pyplot as plt
  5. import matplotlib as mpl
  6. mpl.rcParams['font.sans-serif'] = ['KaiTi']
  7. mpl.rcParams['font.serif'] = ['KaiTi']
  8. import warnings
  9. warnings.filterwarnings("ignore")
  10. from scipy import stats
  11. import numpy as np
  12. from sklearn.linear_model import LogisticRegression
  13. from sklearn.svm import SVC,LinearSVC
  14. from sklearn.preprocessing import MinMaxScaler,StandardScaler
  15. from sklearn.cross_validation import train_test_split
  16. import xgboost as xgb
  17. def get_data():
  18. data = pd.read_csv("../Data/cs-training.csv", index_col=0)
  19. # print(data.info())
  20. pd.set_option('display.max_columns', None)
  21. pd.set_option('display.max_rows', None)
  22. # print("\033[7;37;41m\t 数据详细描述: \033[0m")
  23. # print(data.describe())
  24. print("get data!")
  25. return data
  26. def data_process(data):
  27. def set_missing(df):
  28. # 把已有的数值型特征取出来,MonthlyIncome位于第5列,NumberOfDependents位于第10列
  29. process_df = df.ix[:, [5, 0, 1, 2, 3, 4, 6, 7, 8, 9]]
  30. # 分成已知该特征和未知该特征两部分
  31. known = process_df[process_df.MonthlyIncome.notnull()].as_matrix()
  32. unknown = process_df[process_df.MonthlyIncome.isnull()].as_matrix()
  33. X = known[:, 1:] # X为特征属性值
  34. y = known[:, 0] # y为结果标签值
  35. rfr = RandomForestRegressor(random_state=0, n_estimators=200, max_depth=3)
  36. rfr.fit(X, y)
  37. print(rfr.feature_importances_)
  38. # 用得到的模型进行未知特征值预测月收入
  39. predicted = rfr.predict(unknown[:, 1:]).round(0)
  40. # 用得到的预测结果填补原缺失数据
  41. df.loc[df.MonthlyIncome.isnull(), 'MonthlyIncome'] = predicted
  42. return df
  43. # 用随机森林填补比较多的缺失值
  44. data = set_missing(data)
  45. data = data.dropna()
  46. data = data.drop_duplicates()
  47. states = {
  48. 'SeriousDlqin2yrs': '好坏客户',
  49. 'RevolvingUtilizationOfUnsecuredLines': '可用额度比值', # 无担保放款循环利用比值
  50. 'age': '年龄',
  51. 'NumberOfTime30-59DaysPastDueNotWorse': '逾期30-59天笔数',
  52. 'DebtRatio': '负债率',
  53. 'MonthlyIncome': '月收入',
  54. 'NumberOfOpenCreditLinesAndLoans': '信贷数量',
  55. 'NumberOfTimes90DaysLate': '逾期90天笔数',
  56. 'NumberRealEstateLoansOrLines': '固定资产贷款量',
  57. 'NumberOfTime60-89DaysPastDueNotWorse': '逾期60-89天笔数',
  58. 'NumberOfDependents': '家属数量'
  59. } # 创建字典
  60. data.rename(columns=states, inplace=True)
  61. print(data[data['年龄']>90].count())
  62. data = data[data['年龄']>0]
  63. data = data[data['年龄']<100]
  64. data = data[data['逾期30-59天笔数']<85]
  65. data = data[data['家属数量']<30]
  66. data = data[data['负债率']<100]
  67. print(data.info())
  68. print("data process!")
  69. return data
  70. def data_analysis(data):
  71. # train_box = data.iloc[:,[3,7,9]]
  72. # train_box.boxplot(figsize=(10,4))
  73. # plt.show()
  74. fig = plt.figure(figsize=(15, 10))
  75. a = fig.add_subplot(3, 2, 1)
  76. b = fig.add_subplot(3, 2, 2)
  77. c = fig.add_subplot(3, 2, 3)
  78. d = fig.add_subplot(3, 2, 4)
  79. e = fig.add_subplot(3, 2, 5)
  80. f = fig.add_subplot(3, 2, 6)
  81. a.boxplot(data['可用额度比值'], labels=['可用额度比值'])
  82. b.boxplot([data['年龄'], data['好坏客户']], labels=['年龄', '好坏客户'])
  83. c.boxplot([data['逾期30-59天笔数'], data['逾期60-89天笔数'], data['逾期90天笔数']], labels=['逾期30-59天笔数', '逾期60-89天笔数', '逾期90天笔数'])
  84. d.boxplot([data['信贷数量'], data['固定资产贷款量'], data['家属数量']], labels=['信贷数量', '固定资产贷款量', '家属数量'])
  85. e.boxplot(data['月收入'], labels=['月收入'])
  86. f.boxplot(data['负债率'], labels=['负债率'])
  87. data.hist(figsize=(20, 15))
  88. for k in [1, 2, 4, 5]: # 遍历列
  89. q1 = data.iloc[:, k].quantile(0.25) # 计算上四分位数
  90. q3 = data.iloc[:, k].quantile(0.75) # 计算下四分位数
  91. iqr = q3 - q1
  92. print(q3)
  93. low = q1 - 1.5 * iqr
  94. up = q3 + 1.5 * iqr
  95. if k == 1:
  96. data1 = data
  97. data1 = data1[(data1.iloc[:, k] > low) & (data1.iloc[:, k] < up)] # 保留正常值范围
  98. data = data1
  99. data.info()
  100. data.iloc[:, [1, 2, 4, 5]].boxplot(figsize=(15, 10))
  101. data = data[data['逾期30-59天笔数'] < 80]
  102. data = data[data['逾期60-89天笔数'] < 80]
  103. data = data[data['逾期60-89天笔数'] < 80]
  104. data = data[data['逾期90天笔数'] < 80]
  105. data = data[data['固定资产贷款量'] < 50]
  106. data = data[data['家属数量'] < 15]
  107. print(data['好坏客户'].sum())
  108. def binning(data):
  109. # 定义自动分箱函数,采用最优分段进行分箱
  110. '''采用斯皮尔曼等级相关系数进行变量相关分析,该相关系数对两个变量划分等级在进行分析,[-1,1],
  111. 当两个变量完全单调相关时,斯皮尔曼相关系数则为+1或−1'''
  112. def op(y, x, n=20): # 定义函数,有三个参数,x为要分箱的变量,y对应关注的因变量,即好坏客户,n最大分组数为20,依次减小试验
  113. r = 0
  114. bad = y.sum() # 计算坏客户个数,因为等于1时表示坏客户,所以求和即可得到好客户数
  115. good = y.count() - bad # count统计个数为所有客户数,减去好客户得到好客户人数
  116. while np.abs(r) < 1: # 判断,当绝对值小于1时继续执行,直到相关系数绝对值等于1停止
  117. d1 = pd.DataFrame({"x": x, "y": y, "bucket": pd.qcut(x, n)})
  118. d2 = d1.groupby('bucket',
  119. as_index=True) # 对数据框d1按照bucket变量分组,Ture则返回以组标签为索引的对象,reset_index()可以取消分组索引让其变成dataframe
  120. r, p = stats.spearmanr(d2.mean().x, d2.mean().y) # 分组,数据为组间均值,计算此时x与y的斯皮尔曼等级相关系数,输出相关系数和P值
  121. n = n - 1 # 减小分组数
  122. d3 = pd.DataFrame(d2.x.min(), columns=['min']) # 建立数据框
  123. d3['min'] = d2.min().x
  124. d3['max'] = d2.max().x
  125. d3['sum'] = d2.sum().y # 对应分组的坏客户数
  126. d3['total'] = d2.count().y # 对应分组总客户数
  127. d3['rate'] = d2.mean().y # 坏客户数占该组总人数比
  128. d3['woe'] = np.log((d3['rate'] / (1 - d3['rate'])) / (good / bad)) # 求woe
  129. # d3['iv']=
  130. d4 = (d3.sort_index(by='min')).reset_index(drop=True)
  131. print("=" * 60)
  132. print(d4)
  133. return (d4)
  134. # 利用所定义的函数依次对连续型变量进行最优分段分箱处理,满足条件的有以下
  135. # x2=op(data['好坏客户'],data['年龄'])
  136. # x4=op(data['好坏客户'],data['负债率'])
  137. # x5=op(data['好坏客户'],data['月收入'])
  138. # 对于不能采用最优分段的变量采用等深分段
  139. def funqcut(y, x, n):
  140. cut1 = pd.qcut(x.rank(method='first'), n) # 进行等深分箱,分组
  141. data = pd.DataFrame({"x": x, "y": y, "cut1": cut1})
  142. cutbad = data.groupby(cut1).y.sum() # 求分组下的坏客户数
  143. cutgood = data.groupby(cut1).y.count() - cutbad # 求分组下好客户数
  144. bad = data.y.sum() # 求总的坏客户数
  145. good = data.y.count() - bad # 求总的好客户数
  146. woe = np.log((cutbad / bad) / (cutgood / good)) # 求各分组的woe
  147. iv = (cutbad / bad - cutgood / good) * woe # 求各分组的iv
  148. cut = pd.DataFrame({"坏客户数": cutbad, "好客户数": cutgood, "woe": woe, "iv": iv})
  149. print(cut)
  150. return cut # 返回表格和对应分组列表
  151. # funqcut(train['好坏客户'],train['年龄'],6).reset_index()
  152. x1 = funqcut(data['好坏客户'], data['可用额度比值'], 5).reset_index()
  153. x2 = funqcut(data['好坏客户'], data['年龄'], 8).reset_index()
  154. x4 = funqcut(data['好坏客户'], data['负债率'], 4).reset_index()
  155. x5 = funqcut(data['好坏客户'], data['月收入'], 5).reset_index()
  156. x6 = funqcut(data['好坏客户'], data['信贷数量'], 6).reset_index()
  157. x3 = funqcut(data['好坏客户'], data['逾期30-59天笔数'], 5).reset_index()
  158. x7 = funqcut(data['好坏客户'], data['逾期90天笔数'], 5).reset_index()
  159. x8 = funqcut(data['好坏客户'], data['固定资产贷款量'], 5).reset_index()
  160. x9 = funqcut(data['好坏客户'], data['逾期60-89天笔数'], 5).reset_index()
  161. x10 = funqcut(data['好坏客户'], data['家属数量'], 5).reset_index()
  162. ivx1 = x1.iv.sum()
  163. ivx2 = x2.iv.sum()
  164. ivx3 = x3.iv.sum()
  165. ivx4 = x4.iv.sum()
  166. ivx5 = x5.iv.sum()
  167. ivx6 = x6.iv.sum()
  168. ivx7 = x7.iv.sum()
  169. ivx8 = x8.iv.sum()
  170. ivx9 = x9.iv.sum()
  171. ivx10 = x10.iv.sum()
  172. IV = pd.DataFrame({"可用额度比值": ivx1,
  173. "年龄": ivx2,
  174. "逾期30-59天笔数": ivx3,
  175. "负债率": ivx4,
  176. "月收入": ivx5,
  177. "信贷数量": ivx6,
  178. "逾期90天笔数": ivx7,
  179. "固定资产贷款量": ivx8,
  180. "逾期60-89天笔数": ivx9,
  181. "家属数量": ivx10}, index=[0])
  182. ivplot = IV.plot.bar(figsize=(15, 10))
  183. ivplot.set_title('特征变量的IV值分布')
  184. # 利用等深分段分箱设定,将各个变量的分箱后情况保存为cut1,cut2,cut3...与所得到的分箱情况总结表相对应。其中采用x2/x4/x5采用最优分段的结果
  185. def cutdata(x, n):
  186. a = pd.qcut(x.rank(method='first'), n, labels=False) # 等深分组,label=False返回整数值(0,1,2,3...)对应第一类、第二类..
  187. return a
  188. # 连续变量均被等深分为了5类
  189. # 应用函数,求出各变量分类情况
  190. cut1 = cutdata(data['可用额度比值'], 5)
  191. cut2 = cutdata(data['年龄'], 8)
  192. cut3 = cutdata(data['逾期30-59天笔数'], 5)
  193. cut4 = cutdata(data['负债率'], 4)
  194. cut5 = cutdata(data['月收入'], 5)
  195. cut6 = cutdata(data['信贷数量'], 6)
  196. cut7 = cutdata(data['逾期90天笔数'], 5)
  197. cut8 = cutdata(data['固定资产贷款量'], 5)
  198. cut9 = cutdata(data['逾期60-89天笔数'], 5)
  199. cut10 = cutdata(data['家属数量'], 5)
  200. # 依据变量值的分类替换成对应的woe值
  201. def replace_train(cut, cut_woe): # 定义替换函数,cut为分组情况,cut_woe为分组对应woe值
  202. a = []
  203. for i in cut.unique(): # unique为去重,保留唯一值
  204. a.append(i)
  205. a.sort() # 排序,默认小到大,得到类别列表并排序,实则为[0,1,2,3,4]
  206. for m in range(len(a)):
  207. cut.replace(a[m], cut_woe.values[m],
  208. inplace=True) # 替换函数,把cut中旧数值a[m]即分类替换为对应woe,cut_woe中的woe也是从小到大排序,因此与a[m]对应,正如把cut中的0替换为woe值,没有改变cut的数值顺序
  209. return cut # 返回被替换后的列表
  210. train_new = pd.DataFrame() # 创建新数据框保存替换后的新数据
  211. train_new['好坏客户'] = data['好坏客户']
  212. train_new['可用额度比值'] = replace_train(cut1, x1.woe)
  213. train_new['年龄'] = replace_train(cut2, x2.woe)
  214. train_new['逾期30-59天笔数'] = replace_train(cut3, x3.woe)
  215. train_new['负债率'] = replace_train(cut4, x4.woe)
  216. train_new['月收入'] = replace_train(cut5, x5.woe)
  217. train_new['信贷数量'] = replace_train(cut6, x6.woe)
  218. train_new['逾期90天笔数'] = replace_train(cut7, x7.woe)
  219. train_new['固定资产贷款量'] = replace_train(cut8, x8.woe)
  220. train_new['逾期60-89天笔数'] = replace_train(cut9, x9.woe)
  221. train_new['家属数量'] = replace_train(cut10, x10.woe)
  222. train_new.head()
  223. def train_SVM(data):
  224. x = data.iloc[:, 1:]
  225. y = data.iloc[:, 0]
  226. train_x, test_x, train_y, test_y = train_test_split(x, y, train_size=0.8, random_state=1111)
  227. # 标准化
  228. stand = StandardScaler()
  229. stand = stand.fit(train_x)
  230. train_x = stand.transform(train_x)
  231. test_x = stand.transform(test_x)
  232. model = SVC(probability=True)
  233. result = model.fit(train_x,train_y)
  234. # pred_y = model.predict(test_x)
  235. score = model.score(test_x,test_y)
  236. print("test score:",score)
  237. x1 = test_x[:1]
  238. print("x1:",x1)
  239. y1 = model.predict_proba(x1)
  240. print("y1:",y1)
  241. save(model,"svc_model.pk")
  242. return model, stand
  243. def train_xgb(data):
  244. print("running,",sys._getframe().f_code.co_name)
  245. x = data.iloc[:, 1:]
  246. y = data.iloc[:, 0]
  247. train_x, test_x, train_y, test_y = train_test_split(x, y, train_size=0.8, random_state=1111)
  248. # 标准化
  249. stand = StandardScaler()
  250. stand = stand.fit(train_x)
  251. train_x = stand.transform(train_x)
  252. test_x = stand.transform(test_x)
  253. model = xgb.XGBClassifier(learning_rate=0.1,
  254. n_estimators=1000, # 树的个数--1000棵树建立xgboost
  255. max_depth=6, # 树的深度
  256. min_child_weight = 1, # 叶子节点最小权重
  257. gamma=0., # 惩罚项中叶子结点个数前的参数
  258. subsample=0.8, # 随机选择80%样本建立决策树
  259. colsample_btree=0.8, # 随机选择80%特征建立决策树
  260. objective='binary:logistic', # 指定损失函数
  261. scale_pos_weight=1, # 解决样本个数不平衡的问题
  262. random_state=27 # 随机数
  263. )
  264. result = model.fit(train_x,train_y)
  265. score = model.score(test_x, test_y)
  266. print("test score:", score)
  267. x1 = test_x[:1]
  268. print("x1:",x1)
  269. y1 = model.predict(x1)
  270. y2 = model.predict_proba(x1)
  271. print("y1:",y1,y2)
  272. save(model,"xgb_model.pk")
  273. return model, stand
  274. '''
  275. 假设比例即违约与正常比v为1/70,此时预期分值Z为700,PDD(比率翻倍的分数)为50
  276. B=PDD/log(2)
  277. A=Z+B*log(v)
  278. '''
  279. B=3/np.log(2)
  280. A=60+B*np.log(1/50)
  281. def get_score(bad_prob, good_prob, A=A, B=B):
  282. ''' 评分公式: score = A - B * ln(bad_prob/good_prob)
  283. 或 score = A + PDD * log2(good_prob/bad_prob)
  284. '''
  285. odds = bad_prob/good_prob
  286. score = A - B * np.log(odds)
  287. # print(A+30*np.log2(good_prob/bad_prob))
  288. return score
  289. import pickle
  290. def save(object_to_save, path):
  291. with open(path, 'wb') as f:
  292. pickle.dump(object_to_save, f)
  293. def load(path):
  294. with open(path, 'rb') as f:
  295. object1 = pickle.load(f)
  296. return object1
  297. class AHP:
  298. """
  299. 相关信息的传入和准备
  300. """
  301. def __init__(self, array):
  302. ## 记录矩阵相关信息
  303. self.array = array
  304. ## 记录矩阵大小
  305. self.n = array.shape[0]
  306. # 初始化RI值,用于一致性检验
  307. self.RI_list = [0, 0, 0.52, 0.89, 1.12, 1.26, 1.36, 1.41, 1.46, 1.49, 1.52, 1.54, 1.56, 1.58,
  308. 1.59]
  309. # 矩阵的特征值和特征向量
  310. self.eig_val, self.eig_vector = np.linalg.eig(self.array)
  311. # 矩阵的最大特征值
  312. self.max_eig_val = np.max(self.eig_val)
  313. # 矩阵最大特征值对应的特征向量
  314. self.max_eig_vector = self.eig_vector[:, np.argmax(self.eig_val)].real
  315. # 矩阵的一致性指标CI
  316. self.CI_val = (self.max_eig_val - self.n) / (self.n - 1)
  317. # 矩阵的一致性比例CR
  318. self.CR_val = self.CI_val / (self.RI_list[self.n - 1])
  319. """
  320. 一致性判断
  321. """
  322. def test_consist(self):
  323. # 打印矩阵的一致性指标CI和一致性比例CR
  324. print("判断矩阵的CI值为:" + str(self.CI_val))
  325. print("判断矩阵的CR值为:" + str(self.CR_val))
  326. # 进行一致性检验判断
  327. if self.n == 2: # 当只有两个子因素的情况
  328. print("仅包含两个子因素,不存在一致性问题")
  329. else:
  330. if self.CR_val < 0.1: # CR值小于0.1,可以通过一致性检验
  331. print("判断矩阵的CR值为" + str(self.CR_val) + ",通过一致性检验")
  332. return True
  333. else: # CR值大于0.1, 一致性检验不通过
  334. print("判断矩阵的CR值为" + str(self.CR_val) + "未通过一致性检验")
  335. return False
  336. """
  337. 算术平均法求权重
  338. """
  339. def cal_weight_by_arithmetic_method(self):
  340. # 求矩阵的每列的和
  341. col_sum = np.sum(self.array, axis=0)
  342. # 将判断矩阵按照列归一化
  343. array_normed = self.array / col_sum
  344. # 计算权重向量
  345. array_weight = np.sum(array_normed, axis=1) / self.n
  346. # 打印权重向量
  347. print("算术平均法计算得到的权重向量为:\n", array_weight)
  348. # 返回权重向量的值
  349. return array_weight
  350. """
  351. 几何平均法求权重
  352. """
  353. def cal_weight__by_geometric_method(self):
  354. # 求矩阵的每列的积
  355. col_product = np.product(self.array, axis=0)
  356. # 将得到的积向量的每个分量进行开n次方
  357. array_power = np.power(col_product, 1 / self.n)
  358. # 将列向量归一化
  359. array_weight = array_power / np.sum(array_power)
  360. # 打印权重向量
  361. print("几何平均法计算得到的权重向量为:\n", array_weight)
  362. # 返回权重向量的值
  363. return array_weight
  364. """
  365. 特征值法求权重
  366. """
  367. def cal_weight__by_eigenvalue_method(self):
  368. # 将矩阵最大特征值对应的特征向量进行归一化处理就得到了权重
  369. array_weight = self.max_eig_vector / np.sum(self.max_eig_vector)
  370. # 打印权重向量
  371. print("特征值法计算得到的权重向量为:\n", array_weight)
  372. # 返回权重向量的值
  373. return array_weight
  374. if __name__ == '__main__':
  375. # data = get_data()
  376. # data = data_process(data)
  377. # # model,stand = train_SVM(data)
  378. # model,stand = train_xgb(data)
  379. # test_data = pd.read_csv("Data/cs-test.csv", index_col=0)
  380. # model = load('svc_model.pk')
  381. model = load('xgb_model.pk')
  382. data = pd.read_csv("../Data/cs-training.csv", index_col=0)
  383. # x = np.array([np.array([-0.01867214, 0.28473352, -0.35965723, -0.12996393, -0.18025808, 0.07713616,
  384. # -0.18793693, -0.01226944, -0.19963244, -0.72204477])])
  385. # x = np.array([np.array([-0.92867214, 0.98473352, -0.05965723, -0.92996393, -0.08025808, 0.17713616,
  386. # -0.58793693, -0.91226944, -0.99963244, -0.92204477])])
  387. # print(model.predict(x))
  388. # a,b = model.predict_proba(x)[0]
  389. # print(get_score(b,a),'\n')
  390. print(get_score(0.5,0.5))
  391. # 给出判断矩阵
  392. # b = np.array([[1, 1 / 3, 1 / 8], [3, 1, 1 / 3], [8, 3, 1]])
  393. '''
  394. "个人信息" :"年龄"
  395. "月收入"
  396. "家属数量"
  397. “信贷信息” :"负债率"
  398. "逾期30-59天笔数"
  399. "逾期60-89天笔数"
  400. "逾期90天笔数"
  401. "可用额度比值"
  402. "信贷数量"
  403. "固定资产贷款量"
  404. '''
  405. # "个人信息",“信用信息”
  406. a = np.array([[1, 1/3],
  407. [3, 1]
  408. ])
  409. ahp1 = AHP(a)
  410. # 算术平均法求权重
  411. weight1 = ahp1.cal_weight_by_arithmetic_method()
  412. # weight2 = AHP(a).cal_weight__by_geometric_method()
  413. # 特征值法求权重
  414. weight3 = ahp1.cal_weight__by_eigenvalue_method()
  415. ahp1.test_consist()
  416. # "年龄","月收入","家属数量"
  417. b1 = np.array([
  418. [1 ,1/3,6 ],
  419. [3 ,1 ,9 ],
  420. [1/6,1/9,1]
  421. ])
  422. ahp2 = AHP(b1)
  423. weight4 = ahp2.cal_weight_by_arithmetic_method()
  424. weight5 = ahp2.cal_weight__by_eigenvalue_method()
  425. ahp2.test_consist()
  426. # "负债率","逾期30-59天笔数","逾期60-89天笔数","逾期90天笔数","可用额度比值","信贷数量","固定资产贷款量"
  427. b2 = np.array([
  428. [1 ,2 ,4 ,5 ,3 ,2 ,2 ],
  429. [1/2,1 ,3 ,4 ,1 ,2 ,1 ],
  430. [1/4,1/3,1 ,2 ,1/2,1 ,1/2],
  431. [1/5,1/4,1/2,1 ,1/4,1/5,1/3],
  432. [1/3,1 ,2 ,4 ,1 ,2 ,2 ],
  433. [1/2,1/2,1 ,5 ,1/2,1 ,1 ],
  434. [1/2,1 ,2 ,3 ,1/2,1 ,1 ]
  435. ])
  436. ahp3 = AHP(b2)
  437. weight6 = ahp3.cal_weight_by_arithmetic_method()
  438. weight7 = ahp3.cal_weight__by_eigenvalue_method()
  439. ahp3.test_consist()
  440. pass