美文网首页python
python实战-唐宇迪

python实战-唐宇迪

作者: 当安东尼遇到玛丽 | 来源:发表于2018-11-08 10:46 被阅读0次

    X[:,0]是numpy中数组的一种写法,取数组的索引,表示对一个二维数组,取该二维数组第一维中的所有数据,第二维中取第0个数据,直观来说,X[:,0]就是取所有行的第0列个数据, X[:,1] 就是取所有行的第1列个数据。

    temp.index = temp.pop("date")     temp.pop原有列字段的数据挪出来 做索引

    insert()方法语法:list.insert(index, obj)    参数  index -- 对象     obj 需要插入的索引位置。    obj -- 要插入列表中的对象。

    resharp(1,-1)样本转化成行向量形式 -1是推断操作

    [axis=0代表列,axis=1代表行

    KMeans(n_clusters=2,random_state=1) n_clusters样本分几堆  random_state使每次随机结果保持一致

    例: loc[n]表示索引的是第n行(index 是整数) loc[‘d’]表示索引的是第’d’行(index 是字符) 2. .iloc   :通过行号获取行数据,不能是字符 3.  ix——结合前两种的混合索引

    np.random.seed 设置相同的seed,则每次生成的随机数也相同,如果不设置seed,则每次生成的随机数都会不一样

    umpy.random中shuffle与permutation的区别        函数shuffle与permutation都是对原来的数组进行重新洗牌(即随机打乱原来的元素顺序);区别在于shuffle直接在原来的数组上进行操作,改变原来数组的顺序,无返回值。而permutation不直接在原来的数组上进行操作,而是返回一个新的打乱顺序的数组,并不改变原来的数组。

    逻辑回归 from sklearn.linear_model import LogisticRegression       函数  predict    predict_proba

    以及三种括号如何使用,如何表示矩阵:1.小括号:表示一个tutle元组,这是一个不可更改的数据表示,只能读取  2.中括号:定义一个list列表,这里注意不能用list来表示我们常说的“数组”,数组的定义需要用到numpy,例如你定义一个变量:a=[[1,2,3],[4,5,6],[7,8,9]]这也只是表示a是个元素的list变量的list,不可以用a[:,:]的形式来提取值,而可以使用a[0][1]这样的形式。但是,数据的寻找是逐步的,所以a[:][1]和a[1][:]是用一种结果3.大括号:代表dict字典数据类型,字典是由键对值组组成。冒号':'分开键和值,逗号','隔开组。

    print titanic.describe() 查看所有特征

    unique 某一特征下的属性详细包含

    from sklearn.cross_validation import KFold 交叉验证

    from sklearn.feature_selection import SelectKBest, f_classif选出哪个特征最重要

    value_counts 特征值得个数统计

    len() 方法返回列表元素个数 样本个数

    unique

    roc_curve

    roc_auc_score

    reset_index

    cross_val_score

    groupby

    scatter_plot_by_category

    drop参数

    get_dummies

    notnull

    isnull

    logspace

    np.concatenate

    columns.tolist() 查看特征所有名

    交叉验证

    shuffled 重新洗牌

    5 numpy 用于做矩阵 excel行和列就是矩阵

    一维表,就是在工作表数据区域的顶端行为字段名称(标题),以后各行为数据(记录),并且各列只包含一种类型数据的数据区域。维表每个数据都只有一个对应值,而二维表每个数据有两个对应值。每一列都是独立的参数那就是一维表,如果每一列都是同类参数那就是二维表。为了后期更好地创建各种类型的数据透视表,强烈建议用户在数据录入时,采用一维表形式的数据录入,避免采用二维表的形式对数据进行录入。

    numpy中一维数组用一个中括号 二维用两个

    变量.shap 看数组的结构

    np.genformtxt 打印出表格每一行数据

    取一行的其中一个数据  变量名[1,4]  取所有列[:1] 所有行 第一列  [:0:2] 取0和2两列  print(变量拍[suoyin==10]) 打印出array的布尔值

    找出等于25的行数据。。

    7    变量名.astype(float)  改变数据类型    矩阵求和 matrix.sum(axis=1)代表行

    8    矩阵变换 

    向量变成矩阵

    .size 矩阵中有多少数值  np.zeros((3,4)) 初始化为0的矩阵  np.ones((2,3,4)) 都为一的3维矩阵。np.random.random(2,3)调用random模块下的random函数    np.linespace 随机造数

    每个数值做一个平方操作。

    np.range(10,30,5) 范围。起点为10,终点为30间隔为五。。

    9    a.ravel 矩阵变成向量

    10.不同复制操作对比

    11 pandas 数据处理应用   print(变量名.columns)

        12  print(变量名.loc[0]) 取第一行第零个数据。 loc[4:3]    取列的数据。print(变量名[“列名”])用列名进行定位。增加列以及数值重要。 新建列变量名["新列名"]

        13     tainan["age"][age_is_null==false]  去掉缺失值,提出有值的项

    row_index_83_age  第83个样本值是多少?。

    14     剔除缺失值  good_ages = titanic_survival["Age"][age_is_null == False]

    pivot_table量与其他量关系的函数 index以谁为基准 aggfunc统计与什么之间的关系   aggfunc统计两个之间的什么关系 不写表示求均值       port_stats = titanic_survival.pivot_table(index="Embarked", values=["Fare","Survived"], aggfunc=np.sum)

    print(port_stats)

    15 apply自定义函数 功能未提供 所以自己写的函数 titanic_survival.apply(not_null_count)  

    统计哪一列有空值个数   pd.isnull(column)

    28 三个特征之间用直方图。特征与特征之间用散点图。

    35 有监督学习。分类问题。分类猫和狗。做法要执行的时候有一个标签纸。猫和狗分别打标签是有监督的学习。摸个狗混在一起,要分类出来是无监督学习。最终预测出一个具体的值就是回归。分类是一和零的问题。是有还是无

    35-38线性回归推导。x1 x2代表工资和年龄两个特征。Θ1Θ2是对x1x2的影响程度。hΘ银行最终会借多少钱?由x1x2决定。X1x2由Θ1Θ2决定 相当于wx+b。  Θ0 转换成矩阵格式 变成增加一个列为1的特征值。公式化转后x是列向量。Θ转制是行向量。行与列相乘得hΘ值。 y是标签值。

    np.linalg.inv() 矩阵求逆 mat=x.T.dot(...)是先求这个3*3矩阵的转置(.T),再求与点积(.dot)点积就是矩阵各个对应元素相乘, 这个时候要求两个矩阵必须同样大小。

    https://zhidao.baidu.com/question/811675877155828172.html

    39 逻辑回归。做一个分类任务。sigmod把特征值转化成零到一区间的概率纸。

    40梯度下降。一个最优化算法,梯度下降的方向就是用负梯度方向为搜索方向,沿着梯度下降的方向求解极小值。

    https://blog.csdn.net/chengqiuming/article/details/80187824

    Θ0截距 Θ1斜率

    41-46决策树  为达到目标定出的条件,选择其概率的优先度。

     解决分类问题和回归问题 如:是否相亲成功 熵:表集合的混乱程度     gini系数:信息增益率=信息增益/自身的熵值 率值越高越好

    H(T) 叶子节点的熵值 Nt 叶子节点的样本数 (权重值)gini也相当于熵值

    决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解法  决策树是一个预测模型,他代表的是对象属性与对象值之间的一种映射关系。其中每个内部节点表示一个属性上的测试,每个分支代表一个测试输出,每个叶节点代表一种类别。是监督学习就是给定一堆样本,每个样本都有一组属性和一个类别,这些类别是事先确定的,那么通过学习得到一个分类器,这个分类器能够对新出现的对象给出正确的分类。

    不同决策树算法的划分方法。

    ID3系列算法:使用信息熵作为集合纯度的评估  信息增益的缺点是倾向于选择取值较多是属性,在有些情况下这类属性可能不会提供太多有价值的信息。 ID3算法只能对描述属性为离散型属性的数据集构造决策树 。

    CART算法:使用GINI系数作为集合纯度的评估

    https://www.sohu.com/a/208748892_716346

    https://www.sohu.com/a/155545922_609133

    https://blog.csdn.net/ruggier/article/details/78756447

    46 决策树剪枝。防止过拟合 样本数少特征数多容易过拟合   方法:预剪枝 后剪枝     47随机森林模型。解决决策树的过拟合现象  48决策树参数。交叉验证

    49-53贝叶斯推导及实例。

    54-59     支持向量机

    61至75。K近邻,三基本要素:K值的选择,距离度量,分类决策。

    image转化成数据XxYxZ,W找一些权重参数,得出每个类的得分

    超参数。交叉验证。得分函数。损失函数。正则化惩罚项。惩罚权重不均匀的项

    softmax分类器。

    exp 做e的x次幂 放大数值 突出好坏特征明显 再做标准化 变概率值 

    sigmod函数。梯度下降。

    过程:x值通过w参数得到得分值 ,再e的x次幂做归一。得到类别概率值。就可求loss值。就可进行最优化。x到loss的过程就是显像传播的过程

    学习率。反向传播。

    由loss往回传 算什么样的w值该更新 更新多大。最优化是在反向传播中体现出来的。反向传播中最重要的。就是更新权重参数。。

    神经网络。激活函数。如果实例中。线性函数分不开样本点。要是用激活函数来分。sigmod             digw3[sig w2[sig[w,x1]]]  但是是sigmod会产生梯度消失。所以被淘汰了这个用法。relu替换。

    过拟合。w值内部神经元数据无法展现出。神经元就相当于w参数个数。导致训练与测试与相差很大。λ (lambda) 郑则惩罚项。解决过拟合问题。

    数据预处理。 W不能用铃铛初始。b用零做初始化是可以的。

    权重初始化。dropout。

    x作为全连接操作。容易出现过拟合。dropout每次只贷60%。随机选取。可降低过拟合风险。

    卷积神经网络。

    76-81 xgboost 

    使用多颗树 用不同的特征 每个相当于一个分类七。每家一棵树需要效果得到提升。。。。每个叶子节点给予的分值。最后将相同叶子结点的得分值相加。不能让叶子结点个数更多。加入惩罚项损失函数。

    目标函数。

    82 adaboost

    83至86。自然语言处理。

    88 softmax

    89 90cbow

    91 梯度上升。

    92负采样。

    95无监督学习

    95,96 kmeans

    97-98 k近邻算法

    98

    99-100 kca

    101 102svd

     dot()函数是矩阵乘,而*则表示逐个元素相乘一

    52邮件过滤

    73

    小写的θ是:数学上常代表平面的角

    ---------------------------

    实例

    104   lr = LinearRegression()    lr.fit(cars[["weight"]], cars["mpg"])   lr.fit(inputs,outut)inputs:原数据转换成fit格式的矩阵,行是样本 列是每一个特征  output标签值

    实例  lr = LinearRegression()    ①lr.fit(X, y, sample_weight=None)  ②predictions = lr.predict(X)

    对模型预测好坏的评估  用均方误差法 (预测值-真实值)**2

    mse = mean_squared_error(cars["mpg"], predictions)    rmse = mse ** (0.5)  mean_squared_error(预测值,真实标签值) 标签值:预测的参考

    105 逻辑回归

    两步 Wx算出得分值S,再转换成正数值。再压缩到0-1的区间上。(W权重参数 x特征值)

    from sklearn.linear_model import LogisticRegression    logistic_model = LogisticRegression()    logistic_model.fit(admissions[["gpa"]], admissions["admit"])    计算概率值   pred_probs = logistic_model.predict_proba(admissions[["gpa"]]) 想查看表

    106如何评判模型

    print(predicted_label.value_counts())  value_counts确认数据出现的频率。    

    预测值==真实值 那么就是预测对了 求精度概率值accuracy = len(correct_predictions) / float(len(admissions))   但精度预测也不靠谱 所以。。。

    以上公式表示检测模型正类效果 检测负例效果

    true_positive_filter = (admissions["predicted_label"] == 1) & (admissions["actual_label"] == 1)    true_positives = len(admissions[true_positive_filter])   

     false_negative_filter = (admissions["predicted_label"] == 0) & (admissions["actual_label"] == 1)    false_negatives = len(admissions[false_negative_filter])

    sensitivity = true_positives / float((true_positives + false_negatives))  检验正类的效果有多少    0.127049180328 100人88人应该被录取 但模型没给录取

    0.9625负类检测效果好 应该被拒 实际也被拒

    107  

    admissions["actual_label"] = admissions["admit"] 创建actual_label列 ,值采用admit的值   

    admissions = admissions.drop("admit", axis=1)删除damit列 axis索引为1

    #返回一个新的打乱顺序的数组() 元数据可能以升序等方式排列 )shuffled_index = np.random.permutation(admissions.index)  permutation返回index值

    #划分测试数列集  train = shuffled_admissions.iloc[0:515]     接下来用划分的数据集来训练测试  model.fit(train[["gpa"]], train["actual_label"])    labels = model.predict(test[["gpa"]])        如果训练测试结果相差大 就是过拟合

    probabilities = model.predict_proba(test[["gpa"]])  predict_proba求预测的概率值  #roc_curve曲线  fpr, tpr, thresholds = metrics.roc_curve(test["actual_label"], probabilities[:,1]) 参数实际值,预测的概率值    thresholds 预值  fpr, tpr要求图形的面积越大预测效果越好            #求曲线面积值  auc_score = roc_auc_score(test["actual_label"], probabilities[:,1])

    108 交叉验证

    admissions.ix[0:128, "fold"] = 1  数据切5份  自动建立个新列 fold=1表第一个块的数据

    kf = KFold(len(admissions), 5, shuffle=True, random_state=8)

    lr = LogisticRegression()

    #cross_val_score交叉验证,返回验证一个结果 参数lr加载一个模型,加载数据,标签,返回的结果可以是精度值accuracies或面积值roc_auc等等,cv要求几倍的交叉验证

    kf = KFold(len(admissions), 5, shuffle=True, random_state=8)  len(admissions)=n样本个数  切分块数=5     accuracies = cross_val_score(lr,admissions[["gpa"]], admissions["actual_label"], scoring="roc_auc", cv=kf)     cross_val_score交叉验证  admissions[["gpa"]]=data   admissions["actual_label"]=label  scoring="roc_auc"=返回的结果 也可以用精度accuracy

    109 回归用在多类别问题上  转成多个2分类问题  方法:把一个特征用多维度列形式表示

    dummy_cylinders = pd.get_dummies(cars["cylinders"], prefix="cyl")  cars["cylinders"]要使用的特征咧 prefix起名为cyl   cars = pd.concat([cars, dummy_cylinders], axis=1)  concat把元数据连接在一起

    highest_train_row = int(cars.shape[0] * .70)70%做测试集train =shuffled_cars.iloc[0:highest_train_row]

    将数据拿到手 unique_origins = cars["origin"].unique()   再听吧

    110  print (kobe.shape)数据总数  kobe = raw[pd.notnull(raw['shot_made_flag'])]  notnull不为空的列都保留下     print(kobe.action_type.unique())打印某特征值中包含的多个属性    print(kobe.shot_type.value_counts())每个属性的个数

    112  数据预处理  对机器无法是别的特征值转换  raw['season'] = raw['season'].apply(lambda x: int(x.split('-')[1]) )        lambda 写命名函数 对数值切分  

    pd.DataFrame({'matchup':kobe.matchup, 'opponent':kobe.opponent})  传进2个列 起名matchup

    plt.scatter(raw.dist, raw.shot_distance, color='blue')两个特征完全正相关  只取一个做特征就好

    兰浩特get_dummies 分多类属于的为1 不属于的为0 pd.get_dummies(raw['combined_shot_type'], prefix='combined_shot_type')[0:2]   combined_shot_type起前缀名 

    随机森林 range_n参数 要构造多少棵树 不知道 先取一个范围 range_m树的深度 不过拟合选多少一个个试rfc = RandomForestClassifier(n_estimators=n)

    115 tatanic 数据预处理  

    print (titanic.describe()) 查看所有数据 缺失值填充 取均值 titanic["Age"] = titanic["Age"].fillna(titanic["Age"].median())  fillna 函数   填充方法median()         字符串的量值转成数字0,1   titanic.loc[titanic["Sex"] == "male", "Sex"] = 0

    116预测    先提取特征 做交叉验证  训练。   想知道某人是否获救   predictions[predictions > .5] = 1  预测与真实值相等的个数   accuracy = sum(predictions[predictions == titanic["Survived"]]) / len(predictions)    0.787878787879  精准度78%   用逻辑回归得出概率值结果两者差不多

    117 用回归做比较初级 ,接下来用随机森林 参数调优要多花费时间 当数据调整不上去了 就换或增加一些数据特征  

    118衡量挑选有价值的特征

    from sklearn.feature_selection import SelectKBest, f_classif 基于SelectKBest库操作        selector = SelectKBest(f_classif, k=5)    #"Survived" 作为label值,衡量重要性selector.fit(titanic[predictors], titanic["Survived"])  

    用多分类器去做 看看效果好的比例

    algorithms = [[GradientBoostingClassifier(random_state=1, n_estimators=25, max_depth=3), ["Pclass", "特征项",]],        [LogisticRegression(random_state=1), ["Pclass", "特征项"]]]

    分别作训练和测试 再把两个预测值取平均test_predictions = (full_test_predictions[0] + full_test_predictions[1]) / 2

    119 案例还款率分类任务  count_classes = pd.value_counts(data['Class'], sort = True).sort_index()图表查看两类的比例  样本不均衡解决方案 过采样(少的增多)和下采样(多的减少)

    先要将特征分布差异调整到差不多不能有的1,有的400  所以 from sklearn.preprocessing import StandardScaler  在preprocessing预处理模块导入StandardScaler 标准化模块  

    data['normAmount'] = StandardScaler().fit_transform(data['Amount'].reshape(-1, 1))

    data = data.drop(['Time','Amount'],axis=1)    fit_transform对数据进行变换  reshape(-1, 1)  -1让模块自己去猜 自动识别  操作后加入新特征normAmount

    121 下采样X = data.ix[:, data.columns != 'Class']  y = data.ix[:, data.columns == 'Class'] 数据做切分         number_records_fraud = len(data[data.Class == 1]) .Class的数 为true的取出来    fraud_indices = np.array(data[data.Class == 1].index)数据拿到手 样本等于1的用index取出来        normal_indices = data[data.Class == 0].index把等于0的index索引拿出来        random_normal_indices = np.random.choice(normal_indices, number_records_fraud, replace = False)    random.choice随机选择(参数:选择的范围,选择的个数,replace :是否用代替)        np.concatenate 0和1数据合并

    122 交叉验证 数据80训练 20验证  80训练中分三份 1,2训练3验证  13练2验证 23练1验证 再3次的结果取平均 目的让数据不偏激 模型参数选择合理性

    from sklearn.cross_validation import train_test_split  cross_validation 交叉验证模块  train_test_split数据集切分   train_test_split(X,y,test_size = 0.3, random_state = 0) test_size 切分比例 random_state数据洗牌操作,随机切分 

    接下来用下采样训练 测试用原始数据的测试集部分 30%

    123 recall 负样本 未检测出的患癌数重要,对其重查

    124正则化惩罚  惩罚力度  lr = LogisticRegression(C = c_param, penalty = 'l1')  c_param表示惩罚力度  param选择惩罚模型l1 l2

    125 from sklearn.cross_validation import KFold, cross_val_score  KFold规定做几倍交叉验证切几份自己定  cross_val_score  验证评估结果         from sklearn.metrics import confusion_matrix,recall_score,classification_report  ·confusion_matrix        

    126 confusion_matrix混淆矩阵  预测与真实值的比较   x,y=1 TP正类 FN x=0y=1 TP,FN对recall有影响     x=1y=0 本来没异常发生 误抓,使精度偏低(精度计算:x0y0+x1y1/x1y0+x0y1)  x=0y=1有样本未检测到

    127   逻辑回归阈值  predict_proba >=0.1    阈值设的大误杀率高>=0.9  0.4-0.6范围有检测不到样本情况  实际应用中根据误判容忍度选择值

    128.SMOTE过采样     from imblearn.over_sampling import SMOTE          oversampler=SMOTE(random_state=0)实例化对象 过采样   os_features,os_labels=oversampler.fit_sample(features_train,labels_train)

    129文本分析

    重要词程度决定法

    131提取数据   content = df_news.content.values.tolist()  把content列拿出来 再转换成tolist格式  

    current_segment = jieba.lcut(line)  lcut进行分词  

    df_content=pd.DataFrame({'content_S':content_S})  DataFrame把分词写在表格 

    132  数据清洗  stopwords=pd.read_csv("stopwords.txt",index_col=False,sep="\t",quoting=3,names=['stopword'], encoding='utf-8')

    停用词表 if word in stopwords:   continue   line_clean.append(word)    all_words.append(str(word))

    出现就过滤掉continue    没出现就拿过来append        df_all_words=pd.DataFrame({'all_words':all_words})看一下出现了哪些词

    words_count=df_all_words.groupby(by=['all_words'])['all_words'].agg({"count":numpy.size})  groupby统计词出现的次数

    print (" ".join(jieba.analyse.extract_tags(content_S_str, topK=5, withWeight=False)))  extract_tags提取关键词   content_S_str传入结果   topK返回结果数

    133 想知道主题里包含了哪些关键词

    134 贝叶斯分类器对新闻分类        df_train.label.unique()展示分类一共的词 不重复的值 

    做映射电脑只认数字  label_mapping = {"汽车": 1, "财经": 2, "科技": }  df_train['label'] = df_train['label'].map(label_mapping)  label值替换用map将label_mapping传进去

    from sklearn.feature_extraction.text import CountVectorizer 把一句话转换成向量

    136 时间序列

    rng = pd.date_range('2016-07-01', periods = 10, freq = '3D')         index=pd.date_range(dt.datetime(2016,1,1),periods=20))指定索引为天  print(time['2016-01-15'])打印天就可直接调数据出来        #时间戳pd.Timestamp('2016-07-10')

    138时间窗口  r = df.rolling(window = 10)     print(r.mean())求均值

    139.数据平稳性arima与差分法 用于根据历史数据预测未来 或未来降雨量  数据必须有惯性特征如果16年和17年分布不一样 就不能用 平稳性要求均值方差不发生明显变化

    要求曲线波动不十分剧烈

    sentiment_short['UMCSENT'].diff(1)    sentiment_short取到有数值的一列  diff相减的时间间隔

    151  贷款预测

    print(loans_2007.iloc[0]) 显示所有特征第一行   print(loans_2007.shape[1]) 列数统计

    value_counts统计每个特征出现次数

    153  模型预测 不能用精度  要用recall  重要盯住 FP 这孙子不能还,却借给了 代表亏损  要降低这个值 TP能还也借了 代表收益 要提高这个值 

    154 数据样本不均衡会导致两个值的预测都很高 6:1  可以降低tp的样本权重是1 升高fp权重为6

    penalty = {    0: 5,   1: 1}    lr = LogisticRegression(class_weight=penalty)  自定义权重比例自定 5:1  class_weight

    也可以随机森林预测等方法  寻找更好方法

    156 客户流失    数据预处理  1 数据取值范围统一化 x-min/max-min 或标准化[-1,1]之间压缩preprocessing.StandardScaler()       2 去除字符串 0-1化     看数据是否均衡   接下来交叉验证 for形式模板 只换分类器名就行  接下来用多个分类器玩 knn  svc rf  并算精度  每个分类器的预测与实际相同比例  精度值不能表现问题 应关注 预测没流失 却流失的数据  求得数据来比较哪个分类器好  MAP比较 面积看哪个好

    159  流失优先级操作

    162  red card   数据查看   df.shap  df.head()  df.describe().T   df.dtypes    df.columns.tolist()

    同一属性特征下有多重数据 看没种的均值 用groupby       grouped = df2['data1'].groupby(df['key1'])   grouped.mean()

    163  相似属性归类  特征值是否有重复检查  all_cols_unique_players[all_cols_unique_players > 1].dropna().head()      all_cols_unique_players[all_cols_unique_players > 1].dropna().shape[0] == 0  

    164查看缺失值 msno.matrix(players.sample(500),   figsize=(16, 7),  width_ratios=(15, 1)) 用插件 

    或自己统计players = players[players.rater1.notnull()]  players.shape[0]

    pandas_profiling.ProfileReport(players)包 自动统计数据 很有用

    170 slice可以根据变量进行各种切分    variable_slice(data, 'total_pop').head()   variable_slice不同国家人口变化情况  

    172   recent[['total_pop', 'urban_pop', 'rural_pop']].apply(scipy.stats.skew)    scipy偏度的计算

    177  一组数据中最大值与最小值相差巨大,如何归一化

    178.应用聚类算法得出异常IP点  多特征权重 

    相关文章

      网友评论

        本文标题:python实战-唐宇迪

        本文链接:https://www.haomeiwen.com/subject/ombpzftx.html