大数据需要掌握的基本算法

大数据需要掌握的基本算法数学就像一条章鱼,它有触手可以触及到几乎每个学科上面。虽然大部分人在上学的时候有系统的学习,但都没有进行深入的研究和运用,只是拿来拓展自己的思维逻辑。但是如果你想从事数学相关的研究或者岗位,你将不得不努力学习数学。如果你已经完成了数学学位或一些技能学位,你可能会知道你所学的是否…

大数据需要会的基本算法

前言

数学就像一条章鱼,它有触手可以触及到几乎每个学科上面。虽然大部分人在上学的时候有系统的学习,但都没有进行深入的研究和运用,只是拿来拓展自己的思维逻辑。但是如果你想从事数学相关的研究或者岗位,你将不得不努力学习数学。如果你已经完成了数学学位或一些技能学位,你可能会知道你所学的是否都是必要的。

你可能想知道:做大数据需要掌握多少数学知识?在这篇文章中,我们将简单了解大数据需要掌握的基本算法。

机器学习算法,有数百种算法。覆盖每种类型算法的深度不属于本文的范围,本文将讨论您需要知道的以下常用算法的数学算法:

  • Naive Bayes(朴素贝叶斯)
  • Linear Regression(线性回归)
  • Logistic Regression(逻辑回归)
  • K-Means clustering(k均值聚类算法)
  • Decision Trees(决策树)

Naïve Bayes’ Classifiers(朴素贝叶斯分类算法)

朴素贝叶斯分类器是分类算法集合中基于贝叶斯理论的一种算法。

贝叶斯理论

贝叶斯理论指的是,根据一个已发生事件的概率,计算另一个事件的发生概率。贝叶斯理论从数学上的表示可以写成这样:

大数据需要掌握的基本算法

【注意】: AB都是事件,P(B)不为0

上面的公式看着有点复杂,我们可以对它进行分解。 基本上,只要我们给出了事件B为真,那么就能算出事件A发生的概率,事件B也被称为证据。

  • P(A|B)是条件概率。- 在B为真的情况下发生事件A的可能性。
  • P(B|A)也是条件概率。- 给定A的事件B发生的可能性为真。
  • P(A)是事件A的先验(先验概率,例如,在证据之前发生的概率),证据是一个未知事件的一个属性值(在这里就是事件B)。简单来说就是P(A)P(B)是彼此独立观察AB的概率。

接下来我们会通过例子来加深理解。

案例

人们在生活中也经常会无意识的用到贝叶斯定理,比如下面这个例子

推算一下为什么大多数人会认为东北人酒量大?

条件已知:

  • P(A)=遇见酒量大的人的概率。
  • P(B) = 遇见东北人的概率。
  • P(B|A) = 遇见酒量大的人是东北人的概率

推算出东北人的酒量大的概率:P(A|B) = P(A)*P(B|A)/P(B)=遇见酒量大的人的概率*遇见酒量大的人是东北人的概率/遇见东北人的概率。

从上面的公式我们还可以学到如何降低对东北人酒量大的偏见:

  • 减少遇见酒量大的人的概率,遇见酒量大的人是东北人的概率(碰到酒量大的人和哪里人难以控制)。
  • 增加遇见东北人的概率。(这点我们可以选择去东北人多的地方)

上面我们讲的是在生活中的应用,那么用在大数据处理和机器学习有哪些应用呢,请继续看下面这个例子:

垃圾邮件的分类

假设我们有十万邮件,每个邮件都已经标记好是否是垃圾邮件。通过这些数据我们可以算出:

  • P(A)=垃圾邮件的概率,垃圾邮件/所有的邮件。
  • P(B) = 邮件中出现词M的概率,出现词M的邮件/所有的邮件。
  • P(B|A) = 垃圾邮件中出现词M概率,垃圾邮件中含有词M的邮件数量/所有的垃圾邮件。

可以得到: 出现词M的邮件是垃圾邮件的概率P(A|B) = P(A)*P(B|A)/P(B) =邮件中出现词M的概率X垃圾邮件中出现词M概率/是垃圾邮件的概率。

对垃圾邮件学习的过程就是计算P(A|B)的过程。一般会有多个词或多个词的组合尝试,直到找到概率大于预期概率(比如,0.7,0.88,0.93等)的词 M1、M2 等。然后就可以用得到的词计算,判断新的邮件是否是垃圾邮件。

Linear Regression(线性回归)

线性回归,就是能够用一根直线较为精确地描述数据之间的关系。这样当出现新的数据的时候,就能够预测出一个简单的值。

线性回归模型

在机器学习中,数学函数被称为模型。在线性回归的情况下,模型可以表示为:

大数据需要掌握的基本算法

其中a1,a2,...,an表示特定于数据集的参数值,x1,x2,...,xn表示我们选择在模型中使用的要素列,y表示目标列。线性回归的目标是找到最佳描述特征列和目标列之间关系的最佳参数值。换句话说:找到最适合数据的线,以便可以外推趋势线以预测未来结果。为了找到线性回归模型的最佳参数,我们希望最小化模型的残差平方和。

搭建回归模型的基本步骤

  • 根据预测目标,确定自变量和因变量
  • 绘制散点图,确定回归模型类型
  • 估计模型参数,建立回归模型
  • 对回归模型进行检验
  • 利用回归模型进行预测

接下来的案例是关于一个简单的线性回归模型。

简单线性回归 – 一个一元一次回归方程。

y=a+bx+e

  • y:因变量
  • x:自变量
  • a:常数项(回归直线在y轴上的截距)
  • b:回归系数(回归直线的斜率)
  • e:随机误差(随机因素对因变量所产生的影响)

案例-身高体重

如下所示数据,我们随机获取一些男生的身高和体重

编号 身高(cm) 体重(kg)
1 165 60
2 170 64
3 172 66
4 177 68
5 180 70
6 157 55

求根据一名男生的身高预报他的体重的回归方程,并预报一名身高为173cm的男生的体重,散列点如下

大数据需要掌握的基本算法

解:1.选取身高为自变量X,体重为因变量Y,作散点图:

  • 由散点图知道身高和体重有比较好的线性相关关系,因此可以用线性回归方程刻画它们之间的关系。
大数据需要掌握的基本算法

  • 回归方程:y = 0.603x – 38.623
  • 带入求出173cm的体重

python 源码如下:

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.linear_model import LinearRegression

if __name__ == "__main__":
    data = pd.read_csv('./linear.csv')  # TV、Radio、Newspaper、Sales
    print(data)
    x = data[['height', 'weight']]
    # 画出散点图,求x和y的相关系数
    plt.scatter(data.height, data.weight)
    data.corr()
    print(data.corr())
    # 估计模型参数,建立回归模型
    # 首先导入简单线性回归的求解类LinearRegression
    # 然后使用该类进行建模,得到lrModel的模型变量
    lrModel = LinearRegression()
    # 把自变量和因变量选择出来
    x = data[['height']]
    y = data[['weight']]
    plt.xlabel('X')
    # 设置Y轴标签
    plt.ylabel('Y')
    # 调用模型的fit方法,对模型进行训练
    # 这个训练过程就是参数求解的过程
    # 并对模型进行拟合
    lrModel.fit(x, y)
    # 对回归模型进行检验
    lrModel.score(x, y)
    print(lrModel.score(x, y))
    # 利用回归模型进行预测
    lrModel.predict([[160], [170]])
    print(lrModel.predict([[160], [170]]))
    # 查看截距
    alpha = lrModel.intercept_[0]
    # 查看参数
    beta = lrModel.coef_[0][0]

    test = alpha + beta * np.array([167, 170])
    print(alpha, beta, test)
    y_test = beta * x + alpha

    # plt.plot(x, y, 'g-', linewidth=6, label='真实数据')
    plt.plot(x, y_test, 'r-', linewidth=2, label='预测数据')
    plt.show()

总结

建模特点
  • 建模速度快,不需要很复杂的计算,在数据量大的情况下依然运行速度很快。
  • 可以根据系数给出每个变量的理解和解释。
  • 对异常值很敏感。
建模步骤 – sklearn建模流程
  • 建立模型 lrModel = sklearn.linear_model.LinearRegression()
  • 训练模型 lrModel.fit(x,y)
  • 模型评估 lrModel.score(x,y)
  • 模型预测 lrModel.predict(x)

Logistic Regression(逻辑回归)

逻辑回归算法(Logistic Regression)虽然是线性回归算法,但是其它线性回归有所不同,逻辑回归的预测结果只有两种,即true(1)和false(0)。因此,Logistic regression ( 逻辑回归 ) ,尽管它的名字是回归,是一个用于分类的线性模型而不是用于回归。所以,逻辑回归算法往往适用于数据的分类。

那么要想数据将数据的拟合结果映射到1和0上,就需要构造一个函数,使得该函数的结果只有0、1。事实上,逻辑回归算法的拟合函数称为sigmond函数,该函数的输出值只有0、1,而且是一个平滑的函数。我们又称该函数为逻辑函数。该函数的表达式如下:

大数据需要掌握的基本算法

  • Y为决策值
  • x为特征值
  • e为自然对数。

那么为什么sigmoid函数总是返回0到1之间的值?请记住,从代数中将任何数字提高到负指数与将该数字的倒数提高到相应的正指数相同。

我们可以用 Python 把它的函数图像画出来

大数据需要掌握的基本算法

从图上可知,Y的值域为(0,1),那么就可以将决策函数值大于等于 0.5 的具有对应x属性的对象归为正样本,决策函数值小于 0.5 的具有对应x属性的对象归为负样本。这样就可以对样本 数据进行二分类。

上图的代码如下:

import matplotlib.pyplot as plt
import numpy as np

def sigmoid(x):
    # 直接返回sigmoid函数
    return 1 / (1 + np.exp(-x))

if __name__ == '__main__':
    # param:起点,终点,间距
    x = np.arange(-10, 10, 0.2)
    y = sigmoid(x)
    plt.plot(x, y, 'r-', linewidth=2)
    plt.show()

Logistic Regression的目的是寻找一个非线性函数 Sigmoid的最佳拟合参数,在求解过程中用最优化算法完成。该算法的优点是容易理解与实现,计算代价不高

案例1 – 鸢尾花数据收集

鸢尾花数据集或许是最有名的模式识别测试数据

该数据集包括3个鸢尾花类别,每个类别有50个样 本。其中一个类别是与另外两类线性可分的,而另 外两类不能线性可分。

该数据集共150行,每行1个样本。 每个样本有5个字段,分别是

  • 花萼长度
  • 花萼宽度
  • 花瓣长度
  • 花瓣宽度
  • 类别(共3类)
    • Iris setosa山鸢尾
    • Iris versicolor杂色鸢尾
    • Iris Virginica维吉尼亚鸢尾

我们看看代码的实现效果图

大数据需要掌握的基本算法

从图中我们可以看到,预测的分类结果与训练数据的真实结果结果基本一致,部分鸢尾花出现交叉。 项目源码如下

import numpy as np
import pandas as pd
from sklearn import preprocessing
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.pipeline import Pipeline
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches


if __name__ == "__main__":
    path = './iris.data'  # 数据文件路径
    data = pd.read_csv(path, header=None)
    data[4] = pd.Categorical(data[4]).codes
    x, y = np.split(data.values, (4,), axis=1)
    # print 'x = \n', x
    # print 'y = \n', y
    # 仅使用前两列特征
    x = x[:, :2]
   
    # y.ravel()是获取矩阵
    lr = LogisticRegression(C=1e5)
    # pipeline 优化逻辑回归准确度 参数集在新数据集(比如测试集)上的重复使用
    # 管道机制更像是编程技巧的创新,而非算法的创新。
    # 可放在Pipeline中的步骤可能有 (1)特征标准化是需要的,可作为第一个环节
    # (2)既然是分类器,classifier也是少不了的,自然是最后一个环节
    # 标准化数据 - PolynomialFeatures类可以进行特征的构造
    # lr = Pipeline([('sc', StandardScaler()),
    # ('poly', PolynomialFeatures(degree=1)),
    # ('clf', LogisticRegression())])
    lr.fit(x, y.ravel())
    y_hat = lr.predict(x)
    y_hat_prob = lr.predict_proba(x)
    np.set_printoptions(suppress=True)
    print('y_hat = \n', y_hat)
    print('y_hat_prob = \n', y_hat_prob)
    print('准确度:%.2f%%' % (100*np.mean(y_hat == y.ravel())))
    # 画图
    N, M = 200, 200     # 横纵各采样多少个值
    x1_min, x1_max = x[:, 0].min(), x[:, 0].max()   # 第0列的范围
    x2_min, x2_max = x[:, 1].min(), x[:, 1].max()   # 第1列的范围
    t1 = np.linspace(x1_min, x1_max, N)
    t2 = np.linspace(x2_min, x2_max, M)
    x1, x2 = np.meshgrid(t1, t2)                    # 生成网格采样点
    print(x1, x2)
    x_test = np.stack((x1.flat, x2.flat), axis=1)   # 测试点


    # mpl.rcParams['font.sans-serif'] = ['simHei']
    # mpl.rcParams['axes.unicode_minus'] = False
    cm_light = mpl.colors.ListedColormap(['#77E0A0', '#FF8080', '#A0A0FF'])
    cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])
    y_hat = lr.predict(x_test)                  # 预测值
    y_hat = y_hat.reshape(x1.shape)                 # 使之与输入的形状相同
    print("y_hat", y_hat)
    plt.figure(facecolor='w')
    #这个函数讲x1,x2的两个网络矩阵和对应的预测值y_hat绘制在图片上,可以发现输出为三个颜色区块,分布表示分类的区域
    plt.pcolormesh(x1, x2, y_hat, cmap=cm_light)     # 预测值的显示
     # 样本的散列点
    plt.scatter(x[:, 0], x[:, 1], c=y.flat, edgecolors='k', s=50, cmap=cm_dark)
    plt.xlabel(u'Iris height', fontsize=14)
    plt.ylabel(u'Iris width', fontsize=14)
    print(x1_min, x1_max, x2_min, x2_max)
    plt.xlim(x1_min, x1_max)
    plt.ylim(x2_min, x2_max)
    plt.grid()
    patchs = [mpatches.Patch(color='#77E0A0', label='Iris-setosa'),
              mpatches.Patch(color='#FF8080', label='Iris-versicolor'),
              mpatches.Patch(color='#A0A0FF', label='Iris-virginica')]
    plt.legend(handles=patchs, fancybox=True, framealpha=0.8)
    # plt.title(u'鸢尾花Logistic回归分类效果 - 标准化', fontsize=17)
    plt.show()

部分代码解析
  • 绘制数据散列点
#第一种方法
#获取第一列的数据
X = [x[0] for x in DD]  
#获取第二列的数据
Y = [x[1] for x in DD]  
plt.scatter(X[:50], Y[:50], color='red', marker='o', label='setosa') #前50个样本
plt.scatter(X[50:100], Y[50:100], color='blue', marker='x', label='versicolor') #中间50个
plt.scatter(X[100:], Y[100:],color='green', marker='+', label='Virginica') #后50个样本

#第二种
plt.scatter(x[:, 0], x[:, 1], c=y.flat, edgecolors='k', s=50, cmap=cm_dark)   
  • lr = LogisticRegression(C=1e5) lr.fit(x, y.ravel())
    初始化逻辑回归模型并进行训练,C=1e5表示目标函数,正则项系数的倒数具体可以查看官网
  • x1_min, x1_max = x[:, 0].min(), x[:, 0].max()
    x2_min, x2_max = x[:, 1].min(), x[:, 1].max()
    获取的鸢尾花两列数据,对应为花萼长度和花萼宽度,每个点的坐标就是(x,y)。 先取X二维数组的第一列(长度)的最小值、最大值 生成数组,再取X二维数组的第二列(宽度)的最小值、最大值生成数组, 最后用meshgrid函数生成两个网格矩阵x1和x2,如下所示:
    [[4.3 4.31809045 4.3361809 ... 7.8638191 7.88190955 7.9 ]
    

[4.3 4.31809045 4.3361809 … 7.8638191 7.88190955 7.9 ] [4.3 4.31809045 4.3361809 … 7.8638191 7.88190955 7.9 ] … [4.3 4.31809045 4.3361809 … 7.8638191 7.88190955 7.9 ] [4.3 4.31809045 4.3361809 … 7.8638191 7.88190955 7.9 ] [4.3 4.31809045 4.3361809 … 7.8638191 7.88190955 7.9 ]] [[2. 2. 2. … 2. 2. 2. ] [2.0120603 2.0120603 2.0120603 … 2.0120603 2.0120603 2.0120603] [2.0241206 2.0241206 2.0241206 … 2.0241206 2.0241206 2.0241206] … [4.3758794 4.3758794 4.3758794 … 4.3758794 4.3758794 4.3758794] [4.3879397 4.3879397 4.3879397 … 4.3879397 4.3879397 4.3879397] [4.4 4.4 4.4 … 4.4 4.4 4.4 ]] “`

  • x.ravel() 调用ravel()函数将xx和yy的两个矩阵转变成一维数组

  • y_hat = y_hat.reshape(x1.shape)
    用reshape()函数修改形状,将其y_hat转换为两个特征(长度和宽度)。输出如下

    [[1. 1. 1. ... 2. 2. 2.]
     [1. 1. 1. ... 2. 2. 2.]
     [1. 1. 1. ... 2. 2. 2.]
     ...
     [0. 0. 0. ... 2. 2. 2.]
     [0. 0. 0. ... 2. 2. 2.]
     [0. 0. 0. ... 2. 2. 2.]]
    
  • lr.predict(x_test)
    对数据进行预测函数

  • plt.pcolormesh(x1, x2, y_hat, cmap=cm_light)

    这个函数讲x1,x2的两个网络矩阵和对应的预测值y_hat绘制在图片上,可以发现输出为三个颜色区块,分布表示分类的区域

更多知识点希望读者下来后进行拓展,也推荐大学从Sklearn开源知识官网学习最新的实例。

案例2

逻辑回归实例

如果你想深入了解概念,我建议学习概率论以及离散数学或实际分析。

K-Means clustering(k均值聚类算法)

k-means聚类算法是一种无监督机器学习算法,用于对未标记的数据(即未定义类别或组的数据)进行分类。该算法通过在数据中查找组来工作,组的数量由变量k表示。然后,它遍历数据,根据提供的特征将每个数据点分配给k个组中的一个。k-means聚类依赖于整个算法中距离的概念来“分配”数据点给一个聚类。如果你不熟悉距离的概念,它指的是两个给定项目之间的空间量。在数学中,任何描述集合中任意两个元素之间距离的函数称为距离函数或度量。

定义

聚是一个将数据集中在某些方面相似的数据成员进行分类组织的过程,聚类就是一种发现这种内在结构的技术,聚类技术经常被称为无监督学习。

k均值聚类是最著名的划分聚类算法,由于简洁和效率使得他成为所有聚类算法中最广泛使用的。给定一个数据点集合和需要的聚类数目k,k由用户指定,k均值算法根据某个距离函数反复把数据分入k个聚类中。

度量有两种类型:欧几里德度量和出租车度量。
欧几里德度量定义

欧几里德度量定义如下:

大数据需要掌握的基本算法

其中
(x1, y1)
(x2, y2)是笛卡尔平面上的坐标点。虽然
欧几里德度量是足够的,但在某些情况下它不起作用。假设你在一个大城市里散步,如果有一座巨大的建筑物挡住了你的去路,那么说“我离目的地只有6.5个单位”是没有意义的。为了解决这个问题,我们可以使用出租车指标

出租车度量

出租车指标如下:

大数据需要掌握的基本算法

这一个没那么复杂;实际上你只需要知道加减法,了解代数的基本知识,就可以掌握距离公式。但是为了对这些度量中的每一种几何的基本类型有一个明确的理解,我推荐一个同时包含欧几里德几何非欧几里德几何的几何类。为了深入了解度量和度量空间的含义,需要阅读数学分析并学习一门真正的分析课程。

算法

步骤如下

  • 先随机取 k 个对象作为初始的聚类中心。
  • 计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。
  • 聚类中心以及分配给它们的对象就代表一个聚类。
  • 一旦全部对象都被分配了,每个聚类的聚类中心会根据聚类中现有的对象被重新计算。
  • 重复上面的步骤直到满足某个终止条件,终止条件可以是下面:
    • 没有(或最小数目)对象被重新分配给不同的聚类。
    • 没有(或最小数目)聚类中心再发生变化。
    • 误差平方和局部最小。

Decision Trees(决策树)

大数据需要掌握的基本算法

上面的图就是我在网上找的一张决策树图,最终的结果是心仪或者不心仪。

基本概念

决策树是类似流程图的树结构,它使用分支方法来说明决策的每个可能结果。树中的每个节点代表对特定变量的测试 – 每个分支都是该测试的结果。

组成

  • 决策点,是对几种可能方案的选择,即最后选择的最佳方案。如果决策属于多级决策,则决策树的中间可以有多个决策点,以决策树根部的决策点为最终决策方案。
  • 状态节点,代表备选方案的经济效果(期望值),通过各状态节点的经济效果的对比,按照一定的决策标准就可以选出最佳方案。由状态节点引出的分支称为概率枝,概率数目表示可能出现的自然状态数目每个分枝上要注明该状态出现的概率。
  • 结果节点,将每个方案在各种自然状态下取得的损益值标注于结果节点的右端。

决策树依赖于一种称为信息理论的理论来确定它们是如何构建的。在信息理论中,人们对某个主题的了解越多,人们可以知道的新信息就越少。信息理论的关键措施之一被称为熵。

关于熵

熵的概念源于物理学,用于度量一个热力学系统的无序程度。

信息熵:不得不提香农这个大写的人啦!信息论里面的知识。在信息论里面,信息熵衡量信息量的大小,也就是对随机变量不确定度的一个衡量。熵越大,不确定性越大。

熵可以这样写:

大数据需要掌握的基本算法

推荐看这个连接,里面讲解的很详细,并且附有demo 决策树讲解

  • P(x) 是数据集中发生特征的概率。 从定义中可知:0≤Entropy(X)≤log(n) 当随机变量只取两个值时,即 X的分布为 P(X=1)=p,X(X=0)=1−p,0≤p≤1则熵为:Entropy(X)=−plog2(p)−(1−p)log2(1−p)。

熵值越高,则数据混合的种类越高,其蕴含的含义是一个变量可能的变化越多(反而跟变量具体的取值没有任何关系,只和值的种类多少以及发生概率有关),它携带的信息量就越大。熵在信息论中是一个非常重要的概念,很多机器学习的算法都会利用到这个概念。 应该注意,任何基数b都可以用于对数;但是我们常用的是2,e和10 。你可能注意到一个像S的一个符号。这是求和符号,它意味着尽可能多次地连续添加求和之外的任何函数。加多少次取决于求和的下限和上限。在计算了熵之后,我们可以利用信息增益来构造决策树,从而判断哪一个分裂将最大程度地降低熵。信息增益公式如下:

大数据需要掌握的基本算法

信息增益衡量一个人能获得多少“比特”信息。在决策树的情况下,我们可以计算数据集中每个列的信息增益,以便找到哪个列将为我们提供最大的信息增益,然后对该列进行拆分。

  • 1)一般而言,信息增益越大,则意味着用属性 A 进行划分所获得的”纯度提升”越大,因此,我们可用信息增益来进行决策树的划分属性选择。

  • 2)著名的ID3 决策树学习算就是以信息增益为准则来选择划分属性。

案例dem

基本的代数和概率是你真正需要刮掉决策树的表面。如果你想要对概率和对数进行深入的概念性理解,我会推荐概率论和代数课程

总结

数学在数据科学中无处不在。虽然有些数据科学算法有时会感觉像魔术,但我们可以理解许多算法的细节而不需要代数和基本概率和统计数据。 如果你不想学习任何数学?从技术上讲,你 可以依靠机器学习库,如scikit-learn为你做所有这些。但是,对于数据科学家来说,对这些算法背后的数学和统计学有充分的了解非常有帮助,这样他们就可以为他们的问题和数据集选择最佳算法,从而做出更准确的预测。所以拥抱痛苦,深入数学!它并不像你想象的那么难,而且我们甚至已经开设了一些关于这些主题的课程来帮助你入门:

参考链接

今天的文章大数据需要掌握的基本算法分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21219.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注