python中什么是算法_Python之算法模型-5.1

from sklearn.datasets importfetch_20newsgroupsfrom sklearn.feature_extraction.text importTfidfVectorizerfrom sklearn.metrics importclassification_reportfrom sklearn.model_selection importtrain_test_splitfrom sklearn.naive_bayes importMultinomialNB#朴素贝叶斯

defbayes():"""贝叶斯公式:

P(W|C)P(C)

P(C|W) = ——————————

P(W)

说明:P为概率,|在C的前提下W的概率, C分类, W多个条件(特征值)

文档:

P(C):每个文档类别的概率(某文档类别数/文档类别总数)

P(W|C):给定类别特征(被预测文档中出现的词)的概率

拉普拉斯平滑:

避免出现次数为0的时候,计算结果直接为0

Ni + a

P(F1|C) = ———————

N + am

说明:a指系数一般为1, m为W(多个条件)的个数,NI为每个条件的个数,N为W(多个条件)的总个数

优点:

源于古典数学理论,有稳定的分类效率

对缺失数据不太敏感,算法比较简单,常用语文本

分类精确度高,速度快

缺点:

使用样本属性独立性假设,与样本属性关联密切。如果训练集准确率不高,会影响结果"""

#1、原始数据

news =fetch_20newsgroups()#2、处理数据

x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25)print(x_train)#3、特征工程

#抽取特征数据

tf =TfidfVectorizer()#训练集中词的重要性统计

x_train =tf.fit_transform(x_train)#print(tf.get_feature_names())

#根据训练集转换测试集

x_test =tf.transform(x_test)#4、算法

mlt =MultinomialNB()

mlt.fit(x_train, y_train)

y_predict=mlt.predict(x_test)print("预测值:", y_predict)#5、评估

source =mlt.score(x_test, y_test)print("准确率:", source)#精准率和召回率

"""二分类的算法评价指标(准确率、精准率、召回率、混淆矩阵、AUC)

数据:

预测值 0 预测值 1

真实值 0 TN FP

真实值 1 FN TP

精准率(precision):

TP

precision = ——————

TP + FP

召回率(recall):

TP

recall = ———————

TP + FN

模型的稳定性:

2TP 2precision * recall

F1 = ————————————— = ———————————————————

2TP + FN + FP precision + recall"""

print("精准率和召回率:\n", classification_report(y_test, y_predict, target_names=news.target_names))

e、结果

1031841-20190719165944136-459641420.png

3)决策树和随机森林

a、公式

信息熵:

n

H(X) = - ∑ p(x)logp(x)

i=1

说明:log 低数为2,单位比特,H(X)为熵,x为特征具体值,p(x)为该值在x特征值中的概率

信息增益:

g(D, A) = H(D) - H(D|A)

说明:随机森林是在决策树的基础上,种植多颗树的方式,只是每一颗树的深度没有决策树那么深。

特征复杂度决定了决策树的深度,不是树的深度越深,就越好的,有可能存在计算不出结果。

信息熵:是确定树深度的最大值。

信息增益:得知特征X的信息而使得类Y的信息的不确定性的减少程度。

b、优缺点

优点:

简化理解和解释,树木可视化

需要很少的数据准备,其他技术通常需要数据归一化

缺点:

树太过于复杂,过拟合

改进:

减枝cart算法(决策树API中已经实现)

随机森林:

在当前所有算法中具有极好的准确率

能够有效的运行在大数据集上

能够处理具有高维特征的输入样本中,而且不需要降维

能够评估各个特征在分类问题上的重要性

c、代码实现

#决策树和随机森林

defdecision_tree():"""决策树:

信息熵:

n

H(X) = - ∑ p(x)logp(x)

i=1

说明:log 低数为2,单位比特,H(X)为熵,x为特征具体值,p(x)为该值在x特征值中的概率

信息增益:

g(D, A) = H(D) - H(D|A)

优点:

简化理解和解释,树木可视化

需要很少的数据准备,其他技术通常需要数据归一化

缺点:

树太过于复杂,过拟合

改进:

减枝cart算法(决策树API中已经实现)

随机森林:

在当前所有算法中具有极好的准确率

能够有效的运行在大数据集上

能够处理具有高维特征的输入样本中,而且不需要降维

能够评估各个特征在分类问题上的重要性"""

#1、原始数据

taitan = pandas.read_csv("decision_tree/titanic.csv")#2、数据处理

x = taitan[["pclass", "age", "sex"]]

y= taitan["survived"]#缺失值处理

x["age"].fillna(x["age"].mean(), inplace=True)

x_train, x_test, y_train, y_test= train_test_split(x, y, test_size=0.25)#3、特征工程

#采用DictVectorizer目的是,数据更多是文本类型的,借助dict的方式来处理成0/1的方式

dict = DictVectorizer(sparse=True)

x_train= dict.fit_transform(x_train.to_dict(orient="records"))#print(x_train)

x_test = dict.transform(x_test.to_dict(orient="records"))#print(dict.get_feature_names())

#4、算法

tree =DecisionTreeClassifier()

tree.fit(x_train, y_train)#5、评估

score =tree.score(x_test, y_test)print("准确率:", score)#导出决策树图形

export_graphviz(tree, out_file="decision_tree/tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', '女', '男'])#随机森林

#4、算法

rf =RandomForestClassifier()#超参数调优

#网络搜索与交叉验证

params ={"n_estimators": [120, 200, 300, 500, 800, 1200],"max_depth": [5, 8, 15, 25, 30]

}

gc= GridSearchCV(rf, param_grid=params, cv=4)

gc.fit(x_train, y_train)#5、评估

score =gc.score(x_test, y_test)print("准确率:", score)print("最佳参数模型:", gc.best_params_)

n_estimators:随机森林数量, max_depth:最大深度

d、结果

1031841-20190719180122998-1713726090.png

三、回归算法

1)矩阵计算

矩阵:

必须是二维

乘法公式:

(m行, l列)* (l行, n列) = (m行, n列)

例如:

[[1,2,3,4]] * [[5],[6],[7],[8]] = 5 * 1 + 6 * 2 + 7 * 3 + 8 * 4

a、正规线性公式

属性的线性组合:

f(x)= w1x1 + w2x2 + w3x3 + ... + wnxn +b

w:权重, b偏置项, x:特征数据

b:单个特征是更加通用

线性回归:

通过一个或者多个自变量与因变量之间进行建模的回归分析

其中可以为一个或者多个自变量之间的线性组合(线性回归的一种)

一元线性回归:

涉及的变量只有一个

多元线性回归:

涉及变量为两个或者两个以上

通用公式:

h(w)= w0 + w1x1 + w2x2 + ... +wnxn

w,x为矩阵w0为b

b、损失函数(最小二乘法)

损失函数(最小二乘法)(误差的平方和):

j(θ) = (hw(x1) - y1)^2 + (hw(x2) - y2)^2 + ... + (hw(xn) - yn)^2

n

= ∑(hw(xi) - yi)^2

i=1

yi:训练样本的真实值, hw(xi):第i个训练样本的特征、组合预测值

说明:当损失值在最小的时候,说明,函数的拟合状态最好,这种方式,也就更加接近具体的预测轨迹

c、权重值

正规方程:

W = (XtX)^(-1)XtY

X:特征值矩阵, Y:目标值矩阵 Xt:转置特征值(行列替换)

特征比较复杂时,不一定能得出结果

梯度下降:

例子(单变量):

δcost(w0 + w1x1) ||

w1 = -w1 - α———————————————— ||

δw1 || (下降)

δcost(w0 + w1x1) ||

w0 = -w0 - α———————————————— ||

δw1 \/

α:学习速率,需要手动指定

δcost(w0 + w1x1)

———————————————— 表示方向

δw1

说明:在求最小损失值的时候,需要不断的求解W(权重值),权重值的求解方式一般为上面两种。求出的值,然后在计算损失值,然后在反过来推导,权重值。如此得出结果,速率越慢当然拟合程度越高,但都是拟合越高越好。

欠拟合:

原因:

学习到的特征太少

解决办法:

增加数据的特征数量

过拟合(训练集和测试集表现不好):

原因:

原始特征数量过多,存在一些嘈杂的特征,模型过于复杂是因为模型尝试去兼顾各个测试数据点

解决办法:

进行特征选择,消除一些关联性不大的特征(不好做)

交叉验证(让所有数据进行训练)

正则化

表现形式:

1031841-20190719182423785-297987714.png

最理想的状态不是第三种,而是第二种。

d、对比:

对比:

梯度下降:

1、需要选择学习率α

2、需要多次迭代

3、当特征数量n很大时,也比较适用

4、适用于各种类型的模型

正规方程:

1、不需要选择学习率α

2、一次运算得出

3、需要计算(XtX)^(-1), 如果特征数量n很大时,时间复杂度很高,通常n<100000,可以接受

4、只能用于线性模型,不适合逻辑回归模型等其他模型

a、存在的意义

岭回归:

1、因为线性回归(LinearRegression)容易出现过拟合的情况,所有需要正则化

2、正则化的目的,就是将高幂(x^n,n很大),的权重降到接近于0

3、岭回归为带有正则化的线性回归

4、回归得到的系数更加符合实际,更加可靠,更存在病态数据偏多的研究中存在较大价值

说明:求解模型f(x) = w0 + w1*x1 + w2*x2^2 + ... + wn*xn^n的时候,减少x^n的权重,这样就减少了过拟合(上图第三种)的方式

b、优势

1、具有l2正则化的线性最小二乘法

2、alpha(λ):正则化力度

3、coef_:回归系数

4)代码实现

from sklearn.datasets importload_bostonfrom sklearn.linear_model importLinearRegression, SGDRegressor, Ridgefrom sklearn.model_selection importtrain_test_splitfrom sklearn.preprocessing importStandardScalerfrom sklearn.metrics importmean_squared_errordefregression():"""属性的线性组合:

f(x) = w1x1 + w2x2 + w3x3 + ... + wnxn + b

w:权重, b偏置项, x:特征数据

b:单个特征是更加通用

线性回归:

通过一个或者多个自变量与因变量之间进行建模的回归分析

其中可以为一个或者多个自变量之间的线性组合(线性回归的一种)

一元线性回归:

涉及的变量只有一个

多元线性回归:

涉及变量为两个或者两个以上

通用公式:

h(w) = w0 + w1x1 + w2x2 + ... + wnxn

w,x为矩阵w0为b

矩阵:

必须是二维

乘法公式:

(m行, l列)* (l行, n列) = (m行, n列)

例如:

[[1,2,3,4]] * [[5],[6],[7],[8]] = 5 * 1 + 6 * 2 + 7 * 3 + 8 * 4

损失函数(最小二乘法)(误差的平方和):

j(θ) = (hw(x1) - y1)^2 + (hw(x2) - y2)^2 + ... + (hw(xn) - yn)^2

n

= ∑(hw(xi) - yi)^2

i=1

yi:训练样本的真实值, hw(xi):第i个训练样本的特征、组合预测值

权重:

正规方程:

W = (XtX)^(-1)XtY

X:特征值矩阵, Y:目标值矩阵 Xt:转置特征值(行列替换)

特征比较复杂时,不一定能得出结果

梯度下降:

例子(单变量):

δcost(w0 + w1x1) ||

w1 = -w1 - α———————————————— ||

δw1 || (下降)

δcost(w0 + w1x1) ||

w0 = -w0 - α———————————————— ||

δw1 \/

α:学习速率,需要手动指定

δcost(w0 + w1x1)

———————————————— 表示方向

δw1

回归性能评估:

1 m _

MSE = ——— ∑(yi - y)^2

m i=1

_

yi:预测值 y:真实值

一定要标准化之前的值

对比:

梯度下降:

1、需要选择学习率α

2、需要多次迭代

3、当特征数量n很大时,也比较适用

4、适用于各种类型的模型

正规方程:

1、不需要选择学习率α

2、一次运算得出

3、需要计算(XtX)^(-1), 如果特征数量n很大时,时间复杂度很高,通常n<100000,可以接受

4、只能用于线性模型,不适合逻辑回归模型等其他模型

岭回归:

1、因为线性回归(LinearRegression)容易出现过拟合的情况,所有需要正则化

2、正则化的目的,就是将高幂(x^n,n很大),的权重降到接近于0

3、岭回归为带有正则化的线性回归

4、回归得到的系数更加符合实际,更加可靠,更存在病态数据偏多的研究中存在较大价值

Ridge:

1、具有l2正则化的线性最小二乘法

2、alpha(λ):正则化力度

3、coef_:回归系数"""

#1、获取数据

lb =load_boston()#2、处理数据

#分隔数据

x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)#3、特征工程

#数据标准化(目的,特征值差异过大,按比例缩小)

#目标值也要进行标准化(目的,特征值标准化后,特征值值过大在回归算法中,得出的权重值差异过大)

#两次标准化实例的目的,就是不同数据之间的实例化不一样

std_x =StandardScaler()

x_train=std_x.fit_transform(x_train)

x_test=std_x.transform(x_test)

std_y=StandardScaler()#目标值也要转成2维数组(-1,不知道样本数)

y_train = std_y.fit_transform(y_train.reshape(-1, 1))

y_test= std_y.transform(y_test.reshape(-1, 1))#print(x_train, y_train)

#4、线性回归正规算法

"""1、通过结果可以看出真实值和预测值的差距还是很大的。

2、这是直接通过线性回归的正确公式来算出权重值的结果。

3、为了更好的减少误差,所以采用梯度下降的方式,来重新计算权重值"""lr=LinearRegression()

lr.fit(x_train, y_train)

y_predict_lr=lr.predict(x_test)#注意这里的预测值是标准化过后的数据,需要转回来

#print("预测值:", std_y.inverse_transform(y_predict_lr).reshape(1, -1))

#print("真实值:", std_y.inverse_transform(y_test).reshape(1, -1))

print("权重值:", lr.coef_)#5、回归评估

print("正规方程均方误差:", mean_squared_error(std_y.inverse_transform(y_test).reshape(1, -1), std_y.inverse_transform(y_predict_lr).reshape(1, -1)))#4、线性回归梯度下降算法

sgd =SGDRegressor()

sgd.fit(x_train, y_train)

y_predict_sgd=sgd.predict(x_test)#注意这里的预测值是标准化过后的数据,需要转回来

#print("预测值:", std_y.inverse_transform(y_predict_sgd).reshape(1, -1))

#print("真实值:", std_y.inverse_transform(y_test).reshape(1, -1))

print("权重值:", sgd.coef_)#5、回归性能评估

print("梯度下降均方误差:", mean_squared_error(std_y.inverse_transform(y_test).reshape(1, -1), std_y.inverse_transform(y_predict_sgd).reshape(1, -1)))#4、线性回归正则化算法(岭回归)

#alpha为超参数,可以通过网格搜索和交叉验证,来确认alpha的值

#alpha范围(0~1, 1~10)

rd = Ridge(alpha=1.0)

rd.fit(x_train, y_train)

y_predict_rd=rd.predict(x_test)#注意这里的预测值是标准化过后的数据,需要转回来

#print("预测值:", std_y.inverse_transform(y_predict_rd).reshape(1, -1))

#print("真实值:", std_y.inverse_transform(y_test).reshape(1, -1))

print("权重值:", sgd.coef_)#5、回归性能评估

print("正则化均方误差:", mean_squared_error(std_y.inverse_transform(y_test).reshape(1, -1), std_y.inverse_transform(y_predict_sgd).reshape(1, -1)))

5)结果

1031841-20190719183301187-1353664644.png

说明:从结果可以看出差异并不是很大,那是因为训练次数的原因,可以通过多次的训练来达到效果

1)公式:

公式:

1

hθ = g(θ^Tx) = ————————————

1 + e^(-θ^Tx)

1

g(z) = ——————————

1 + e^(-z)

输入:[0,1]区间的概率,默认值0.5作为阈值

g(z):sigmoid函数,z为回归结果

说明:逻辑回归,是算一种二分类算法。比如:是否是猫、狗等。我们不能完全确认,他是否是猫,那就用概率的方式来确认分类。概率值越高说明是,反之否。通过大约阈值来确认分类,这种方式人图像识别中还是比较常用的方式。

2)损失函数:

损失函数:

与线性回归原理相同,但是由于是分类问题。损失函数不一样。

只能通过梯度下降求解。

对数似然损失函数:

{ -log(hθ(x)) if y = 1

cost(hθ(x), y) = {

{ -log(1 - hθ(x)) if y = 0

hθ(x)为x的概率值

说明:在均方误差中不存在多个最低点,但是对数似然损失函数,会存在多个低点的情况

完整的损失函数:

m

cost(hθ(x), y) = ∑-yilog(hθ(x)) - (1 - yi)log(1 - hθ(x))

i=1

cost损失值越小,那么预测的类别精准度更高

对数似然损失函数表现:(目前没有好的方式去解决确认最低点的问题)

1031841-20190726113646459-795849349.png

改善方式:

1、多次随机初始化,多次比较最小值结果

2、求解过程中,调整学习率

上面两种方式只是改善,不是真正意义上的解决这个最低点的问题。虽然没有最低点,但是最终结果还是不错的。

损失函数,表现形式:

1031841-20190726111925920-1526692383.png

说明:如果真实值为y=1时,当hθ(x)的概率越接近1时,说明损失函数的值越小。图形公式 -log(P)

1031841-20190726112319412-1962569944.png

说明:如果真是值为y=0时,概率越小,损失值就越小

3)代码实现

importnumpyimportpandasfrom sklearn.linear_model importLogisticRegressionfrom sklearn.preprocessing importStandardScalerfrom sklearn.model_selection importtrain_test_splitfrom sklearn.metrics importmean_squared_error, classification_report#逻辑回归

deflogic_regression():"""公式:

1

hθ = g(θ^Tx) = ————————————

1 + e^(-θ^Tx)

1

g(z) = ——————————

1 + e^(-z)

输入:[0,1]区间的概率,默认值0.5作为阈值

g(z):sigmoid函数,z为回归结果

损失函数:

与线性回归原理相同,但是由于是分类问题。损失函数不一样。

只能通过梯度下降求解。

对数似然损失函数:

{ -log(hθ(x)) if y = 1

cost(hθ(x), y) = {

{ -log(1 - hθ(x)) if y = 0

hθ(x)为x的概率值

说明:在均方误差中不存在多个最低点,但是对数似然损失函数,会存在多个低点的情况

完整的损失函数:

m

cost(hθ(x), y) = ∑-yilog(hθ(x)) - (1 - yi)log(1 - hθ(x))

i=1

cost损失值越小,那么预测的类别精准度更高"""

"""penalty:正则化方式默认值l2,

C为回归系数默认值1.0"""

#1、原始数据

#地址:https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/

#数据:https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data

column_names = ["Sample code number","Clump Thickness","Uniformity of Cell Size","Uniformity of Cell Shape","Marginal Adhesion","Single Epithelial Cell Size","Bare Nuclei","Bland Chromatin","Normal Nucleoli","Mitoses","Class"]

data= pandas.read_csv("classify_regression/breast-cancer-wisconsin.data", names=column_names)#print(data)

#2、数据处理

#缺失值处理

data = data.replace(to_replace="?", value=numpy.NAN)#删除缺失值数据

data =data.dropna()#特征值,目标值

x = data[column_names[1:10]]

y= data[column_names[10]]#数据分割

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)#3、特征工程

std =StandardScaler()

x_train=std.fit_transform(x_train, y_train)

x_test=std.transform(x_test)#4、算法工程

lr = LogisticRegression(penalty="l2", C=1.0)#训练

lr.fit(x_train, y_train)print("权重值:", lr.coef_)#5、评估

print("准确率:", lr.score(x_test, y_test))

y_predict=lr.predict(x_test)print("召回率:", classification_report(y_test, y_predict, labels=[2, 4], target_names=["良性", "恶性"]))print("均方误差:", mean_squared_error(y_test, y_predict))

4)结果:

1031841-20190726141454318-566605176.png

五、上面说的都是监督学习的算法,下面介绍一种非监督学习的算法(k-mean)

1)步骤和优缺点

k值:

分类个数,一般是知道分类个数的,如果不知道,进行超参数设置

算法实现过程:

1)随机在数据中抽取K个样本,当做K个类别的中心点

2)计算其余的点到这K个点的距离,每一个样本有K个距离值,从中选出最近的一个距离点作为自己的标记

这样就形成了K个族群

3)计算着K个族群的平均值,把这K个平均值,与之前的K个中心点进行比较。

如果相同:结束聚类

如果不同:把K个平均值作为新的中心点,进行计算

优点:

采用迭代式算法,直观易懂并且非常实用

缺点:

容易收敛到局部最优解(多次聚类)

注意:聚类一般是在做分类之前

2)评估方式

轮廓系数:

bi - ai

sci = ———————————

max(bi, ai)

注:对于每个点i为已聚类数据中的样本,bi为i到其他族群的所有样本的距离

最小值,ai为i到本族群的距离平均值

最终算出所有的样本的轮廓系数平均值

sci范围:[-1, 1],越靠近1越好

3)代码实现方式

from matplotlib importpyplotimportpandasfrom sklearn.cluster importKMeansfrom sklearn.decomposition importPCAfrom sklearn.metrics importsilhouette_score#聚类

defk_means():"""k值:

分类个数,一般是知道分类个数的,如果不知道,进行超参数设置

算法实现过程:

1)随机在数据中抽取K个样本,当做K个类别的中心点

2)计算其余的点到这K个点的距离,每一个样本有K个距离值,从中选出最近的一个距离点作为自己的标记

这样就形成了K个族群

3)计算着K个族群的平均值,把这K个平均值,与之前的K个中心点进行比较。

如果相同:结束聚类

如果不同:把K个平均值作为新的中心点,进行计算

优点:

采用迭代式算法,直观易懂并且非常实用

缺点:

容易收敛到局部最优解(多次聚类)

注意:聚类一般是在做分类之前"""

#1、原始数据

orders = pandas.read_csv("market/orders.csv")

prior= pandas.read_csv("market/order_products__prior.csv")

products= pandas.read_csv("market/products.csv")

aisles= pandas.read_csv("market/aisles.csv")#2、数据处理

#合并数据

_msg = pandas.merge(orders, prior, on=["order_id", "order_id"])

_msg= pandas.merge(_msg, products, on=["product_id", "product_id"])

merge_data= pandas.merge(_msg, aisles, on=["aisle_id", "aisle_id"])#交叉表(特殊分组)

#(用户ID, 类别)

cross = pandas.crosstab(merge_data["user_id"], merge_data["aisle"])print(cross.shape)#3、特征工程

#降维

pca = PCA(n_components=0.9)

data=pca.fit_transform(cross)print(data.shape)#4、算法

"""n_clusters:开始均值的中心数量"""km= KMeans(n_clusters=4)#减少数据量

# data = data[1:1000]#训练

km.fit(data)#预测结果

predict =km.predict(data)print("预测值:", predict)#5、评估

"""轮廓系数:

bi - ai

sci = ———————————

max(bi, ai)

注:对于每个点i为已聚类数据中的样本,bi为i到其他族群的所有样本的距离

最小值,ai为i到本族群的距离平均值

最终算出所有的样本的轮廓系数平均值

sci范围:[-1, 1],越靠近1越好"""

print("预测效果:", silhouette_score(data, predict))#6、图形展示

pyplot.figure(figsize=(10, 10))

colors= ["red", "blue", "orange", "yellow"]

color= [colors[i] for i inpredict]

pyplot.scatter(data[:,1], data[:, 20], color=color)

pyplot.xlabel("1")

pyplot.ylabel("20")

pyplot.show()

4)结果:

1031841-20190726154245952-165721683.png

1031841-20190726154308460-1522810825.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值