前言

本文总结了特征选择的常用方法,并附上Python实现代码,其中输入数据集均为Dataframe格式,以便于更接近真实项目场景,在定义的N列数据中,最后一列为标签列,其他列为特征列。

一、为什么要进行特征选择?

在机器学习项目中,我们往往不能直接对原始数据进行建模,我们需要对原始数据进行一系列的预处理,得到最合适的数据集来进行建模,特征选择即是一系列预处理中非常重要的一步。

那什么是最合适的数据集呢?最合适的数据集,应当在不显著降低预测精度、不影响数据分布、具有稳定、适应性强等特点的基础上,尽量的小,以助力模型达到准确性、鲁棒性、可解释性和复杂度之间的最优平衡。数据集尽量小,又包括特征纬度和实例纬度,特征选择部分只讨论特征纬度,如何筛选最有用的特征。

二、选择什么样的特征?

对于机器学习模型来说,特征分为以下三类:

  1. 有效特征:即对模型的效果提升有效果的特征
  2. 无效特征:即删除或保留对模型效果没有影响的特征
  3. 有效重复:即虽然特征有效,但是可以由其他有效特征替代或推断的特征

很明显,我们需要选择第一种,即有效特征,删除无效特征,对有效重复特征进行识别和选择性保留,但在实际特征选择工作中,有效特征和无效特征不会有明显的界限,往往需要通过设置基于筛选标准的阈值或保留特征数来确定保留特征。

三、特征选择方法分类

特征选择方法分为三大类,分别为过滤法(Filter)、包裹法(Wrapper)、嵌入法(Embedding)。

(一)、过滤法(Filter)

Filter方法用某个标准对每个特征分别打分,然后根据打分直接用阈值过滤特征。其中方差过滤法仅考虑每个特征本身的方差,而其他方法均衡量每个特征与响应变量之间的关系,再根据得分扔掉不好的特征。

1.方差过滤法:去掉取值变化小的特征,具体方法是考察每个特征单独的方差值,然后给定一个阈值,过滤掉方差小于阈值的特征。

from sklearn.feature_selection import VarianceThreshold
import pandas as pd
# ##构造数据集df_before
df_before = pd.DataFrame([[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]],columns=["columns1","columns2","columns3"])
print "df_before_select:",df_before
##定义阈值,当列方差小于该阈值,删除该列
thres_ = 0.8
##定义筛选模型
select_model = VarianceThreshold(threshold=(thres_ * (1 - thres_)))
##输出筛选数值结果
df_after = select_model.fit_transform(df_before)
##获取筛选后保留的列名
select_name = [df_before.columns.values.tolist()[i] for i in select_model.get_support(indices=True)]
##将列名和数据组合为dataframe,输出筛选后数据集
df_after = pd.DataFrame(df_after,columns=select_name)
print "df_after_select:",df_after

2.卡方检验过滤法:卡方检验是概率论和数理统计中常用的假设检验的思想,通过观察实际值和理论值的偏差来确定原假设是否成立。首先假设某特征与响应变量是独立的(此为原假设);然后观察实际值和理论值之间的偏差程度,若偏差足够小,则认为偏差是自然的样本误差,接受假设;若偏差大到一定程度,则否认原假设,接受备择假设。

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
import pandas as pd
##构造数据集df_before
df_before = pd.DataFrame([[0, 0, 1,"x"], [0, 1, 0,"y"], [1, 0, 0,"y"], [0, 1, 1,"y"], [0, 1, 0,"x"], [0, 1, 1,"x"]],columns=["columns1","columns2","columns3","label"])
print "df_before_select:",df_before
##定义筛选模型
select_model = SelectKBest(chi2, k=1)#选择k个最佳特征
##输出筛选后的数值及列名
df_after = select_model.fit_transform(df_before[["columns1","columns2","columns3"]],df_before["label"])#iris.data是特征数据,iris.target是标签数据,该函数可以选择出k个特征
select_name = [df_before.columns.values.tolist()[i] for i in select_model.get_support(indices=True)]
##将列名和数据组合为dataframe,输出筛选后的数据集
df_after = pd.DataFrame(df_after,columns=select_name)
print "df_after_select:",df_after

3.相关系数过滤法:在特征选择任务中,可以衡量每个特征变量和响应变量之间的相关性来判断特征变量的重要性,同时也可以衡量特征变量与其他特征变量之间的相关性来判断特征变量之间是否存在信息冗余的情况,以过滤掉可以由其他特征推导或替代的特征变量。

(1) Pearson相关系数

皮尔森相关系数是一种最简单的,能帮助理解特征和响应变量之间关系的方法,该方法衡量的是变量之间的线性相关性,结果的取值区间为[-1,1],-1表示完全的负相关(这个变量下降,那个就会上升),+1表示完全的正相关,0表示没有线性相关。

from scipy.stats import pearsonr
import pandas as pd
##设置阈值
thres_ = 0.3
##构造数据集df_before
df_before = pd.DataFrame([[0, 0, 1,1], [0, 1, 0,1], [1, 0, 0,1], [0, 1, 1,1], [0, 1, 0,1], [0, 1, 1,0]],columns=["columns1","columns2","columns3","label"])
print "df_before_select:",df_before
##输出筛选数值及列名
pearsonr_value_abs = [abs(pearsonr(df_before[i],df_before["label"])[0]) for i in df_before.columns[:-1]]
select_name = [df_before.columns[:-1][i] for i in range(len(pearsonr_value_abs)) if pearsonr_value_abs[i] >=thres_]+[df_before.columns[-1]]
##将列名和数据组合为dataframe,输出筛选后的数据集
df_after = df_before[select_name]
print "df_after_select:",df_after

(2) 距离相关系数

距离相关系数是为了克服Pearson相关系数的弱点而生的。Pearson相关系数是0,我们也不能断定这两个变量是独立的(有可能是非线性相关);但如果距离相关系数是0,那么我们就可以说这两个变量是独立的。

from scipy.spatial.distance import pdist, squareform
import numpy as np
import pandas as pd##设置阈值
thres_ = 0.75
##构造数据集example_df
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
Y = [[j] for j in df_before[df_before.columns[-1]]]
print "df_before:",df_before
##输出筛选后数值及列名
select_name = []
for i in range(len(df_before.columns[:-1])):X = [[j] for j in df_before[df_before.columns[i]]]a = squareform(pdist(X))b = squareform(pdist(Y))A = a - a.mean(axis=0)[None, :] - a.mean(axis=1)[:, None] + a.mean()B = b - b.mean(axis=0)[None, :] - b.mean(axis=1)[:, None] + b.mean()dcov2_xy = (A * B).sum() / float(len(a) * len(a))dcov2_xx = (A * A).sum() / float(len(a) * len(a))dcov2_yy = (B * B).sum() / float(len(a) * len(a))dcor = np.sqrt(dcov2_xy) / np.sqrt(np.sqrt(dcov2_xx) * np.sqrt(dcov2_yy))if dcor>=thres_:select_name.append(df_before.columns[i])
select_name =select_name+[df_before.columns[-1]]
##输出筛选后的数据集
df_after = df_before[select_name]
print df_after

4.互信息和最大信息系数

想把互信息直接用于特征选择其实不是太方便:(1)、它不属于度量方式,也没有办法归一化,在不同数据及上的结果无法做比较;(2)、对于连续变量的计算不是很方便(X和Y都是集合,x,y都是离散的取值),通常变量需要先离散化,而互信息的结果对离散化的方式很敏感。最大信息系数克服了这两个问题。它首先寻找一种最优的离散化方式,然后把互信息取值转换成一种度量方式,取值区间在[ 0 , 1 ] [0,1][0,1]。minepy 提供了MIC功能。(代码待测试)

from minepy import MINE
m = MINE()
import pandas as pd
##设置阈值
thres_ = 0.75
##构造数据集example_df
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
##输出筛选后数值及列名
select_name = []
for i in range(len(df_before.columns[:-1])):X = df_before[df_before.columns[i]]Y = df_before[df_before.columns[-1]]m.compute_score(X, Y)m_score = m.mic()if m_score>=thres_:select_name.append(df_before.columns[i])
select_name =select_name+[df_before.columns[-1]]
##输出筛选后的数据集
df_after = df_before[select_name]
print df_after

5.基于学习模型的特征排序

这种方法的思路是直接使用你要用的机器学习算法,针对每个单独的特征和响应变量建立预测模型。其实Pearson相关系数等价于线性回归里的标准化回归系数。假如某个特征和响应变量之间的关系是非线性的,可以用基于树的方法、或者扩展的线性模型等。基于树的方法比较易于使用,因为他们对非线性关系的建模比较好,并且不需要太多的调试。但要注意过拟合问题,因此树的深度最好不要太大。

from sklearn.model_selection import cross_val_score, ShuffleSplit
from sklearn.ensemble import RandomForestRegressor
import numpy as np
import pandas as pd
##构造数据集example_df
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
X = np.array(df_before[df_before.columns[:-1]])
Y = np.array(df_before[df_before.columns[-1]])
names = df_before.columns.tolist()[:-1]
##构建模型-输出各列分数
rf = RandomForestRegressor(n_estimators=2, max_depth=2)
scores = []
for i in range(X.shape[1]):score = cross_val_score(rf, X[:,i:i+1], Y)scores.append((round(np.mean(score), 3), names[i]))
print sorted(scores, reverse=True)

(二)、包裹法(Wrapper)

Wrapper方法将子集的选择看作是一个搜索寻优问题,生成不同的组合,对组合进行评价,再与其他的组合进行比较。这样就将子集的选择看作是一个优化问题。

1.递归特征消除算法

递归特征消除的主要思想是反复的构建模型然后选出最好的(或者最差的)的特征(可以根据系数来选),把选出来的特征放到一边,然后在剩余的特征上重复这个过程,直到所有特征都遍历。这个过程中特征被消除的次序就是特征的排序。因此,这是一种寻找最优特征子集的贪心算法。RFE的稳定性很大程度上取决于在迭代的时候底层用哪种模型。

from sklearn.feature_selection import RFE
from sklearn.linear_model import LinearRegression
import numpy as np
import pandas as pd
##构造数据集
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
X = np.array(df_before[df_before.columns[:-1]])
Y = np.array(df_before[df_before.columns[-1]])
names = df_before.columns.tolist()[:-1]
##建模-输出排序结果
lr = LinearRegression()
rfe = RFE(lr, n_features_to_select=1)
rfe.fit(X,Y)
print("Features sorted by their rank:")
print(sorted(zip(map(lambda x: round(x, 4), rfe.ranking_), names)))

(三)、嵌入法(Embedding)

有些机器学习方法本身就具有对特征进行打分的机制,或者很容易将其运用到特征选择任务中,例如回归模型,SVM,决策树,随机森林等等。

Embedding方法先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。

1.线性回归模型:线性回归模型常用的特征选择模型有Lasso回归和Ridge回归,当线性回归使用L1正则化时,称为Lasso回归,当线性回归使用L2正则化时,称为Ridge回归。正则化就是把额外的约束或者惩罚项加到已有模型(损失函数)上,以防止过拟合并提高泛化能力。损失函数由原来的E(X,Y)变为E(X,Y)+alpha||w||,w是模型系数组成的向量,alpha参数控制着正则化的强度。

(1)Lasso 回归:L1正则化将系数向量的L1范数作为惩罚项加到损失函数上,由于正则项非零,这就迫使那些弱的特征所对应的系数变成0。因此L1正则化往往会使学到的模型很稀疏(系数w经常为0),这个特性使得L1正则化成为一种很好的特征选择方法。对于Lasso,参数alpha越大,被选中的特征越少。

from sklearn.linear_model import Lasso
from sklearn.feature_selection import SelectFromModel
import numpy as np
import pandas as pd
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
X = np.array(df_before[df_before.columns[:-1]])
Y = np.array(df_before[df_before.columns[-1]])
names = df_before.columns.tolist()[:-1]
##定义模型
lsvc = Lasso(alpha=0.1).fit(X, Y)
model = SelectFromModel(lsvc, prefit=True)
##筛选后的数值和列名
X_new = model.transform(X,)
select_name = [df_before.columns.values.tolist()[i] for i in model.get_support(indices=True)]
##筛选后的Dataframe
df_after = df_before[select_name+[df_before.columns[-1]]]
print df_after

(2)Ridge 回归:L2正则化将系数向量的L2范数作为惩罚项加到了损失函数中。由于L2惩罚项中系数是二次方的,这使得L2和L1有着诸多差异,最明显的一点就是,L2正则化会让系数的取值变得平均。对于关联特征,这意味着他们能够获得更相近的对应系数。系数之和为常数时,各系数相等时惩罚是最小的,所以才有了L2会让各个系数趋于相同的特点。但是对于L2来说,第一个模型的惩罚项是2alpha,但第二个模型的是4*alpha。L2正则化对于特征选择来说一种稳定的模型,不像L1正则化那样,系数会因为细微的数据变化而波动。所以L2正则化和L1正则化提供的价值是不同的,L2正则化对于特征理解来说更加有用:表示能力强的特征对应的系数是非零。

from sklearn.linear_model import Ridge
from sklearn.feature_selection import SelectFromModel
import numpy as np
import pandas as pd
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
X = np.array(df_before[df_before.columns[:-1]])
Y = np.array(df_before[df_before.columns[-1]])
names = df_before.columns.tolist()[:-1]
##定义模型
lsvc = Ridge(alpha=0.1).fit(X, Y)
model = SelectFromModel(lsvc, prefit=True)
##筛选后的数值及列名
X_new = model.transform(X,)
select_name = [df_before.columns.values.tolist()[i] for i in model.get_support(indices=True)]
##筛选后的Dataframe
df_after = df_before[select_name+[df_before.columns[-1]]]
print df_after

2. SVM/logistic:对于SVM和逻辑回归,都有一个C参数,代表的是在线性不可分的情况下,对分类错误的惩罚程度,C值越大,分类器就越不愿意允许分类错误,而C值过小时,分类器就会过于“不在乎”分类错误,于是分类性能就会较差,在特征选择上可以通过参数C控制稀疏性,C越小,被选中的特征越少。

from sklearn.svm import LinearSVC
from sklearn.feature_selection import SelectFromModel
import numpy as np
import pandas as pd
##构造数据集
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
X = np.array(df_before[df_before.columns[:-1]])
Y = np.array(df_before[df_before.columns[-1]])
names = df_before.columns.tolist()[:-1]
##定义模型
lsvc = LinearSVC(C=0.5, penalty="l1", dual=False).fit(X, Y)
model = SelectFromModel(lsvc, prefit=True)
##筛选后的数值和列名
X_new = model.transform(X,)
select_name = [df_before.columns.values.tolist()[i] for i in model.get_support(indices=True)]
##筛选后的Dataframe
df_after = df_before[select_name+[df_before.columns[-1]]]
print df_after
from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import SelectFromModel
import numpy as np
import pandas as pd
##构造数据集
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
X = np.array(df_before[df_before.columns[:-1]])
Y = np.array(df_before[df_before.columns[-1]])
names = df_before.columns.tolist()[:-1]
##定义模型
lsvc = LogisticRegression().fit(X, Y)
model = SelectFromModel(lsvc, prefit=True)
##筛选后的数值列名
X_new = model.transform(X,)
select_name = [df_before.columns.values.tolist()[i] for i in model.get_support(indices=True)]
##筛选后的Dataframe
df_after = df_before[select_name+[df_before.columns[-1]]]
print df_after

3. 决策树:基于树的预测模型能够用来计算特征的重要程度,因此能用来去除不相关的特征。

from sklearn.ensemble import ExtraTreesClassifier
import numpy as np
import pandas as pd
# ##设置阈值
thres_ = 0.75
##构造数据集
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
X = np.array(df_before[df_before.columns[:-1]])
Y = np.array(df_before[df_before.columns[-1]])
names = df_before.columns.tolist()[:-1]
##建模
clf = ExtraTreesClassifier()
clf = clf.fit(X, Y)
score =  clf.feature_importances_
##筛选后的列名
select_name = [df_before.columns[i] for i in range(len(score)) if score[i]>=thres_]
select_name =select_name+[df_before.columns[-1]]
##筛选后的数据集
df_after = df_before[select_name]
print df_after

4. 随机森林:随机森林提供了两种特征选择的方法:平均不纯度减少和平均精确度减少。

(1)平均不纯度减少:随机森林由多个决策树构成。决策树中的每一个节点都是关于某个特征的条件,为的是将数据集按照不同的响应变量一分为二。当训练决策树的时候,可以计算出每个特征减少了多少树的不纯度。对于一个决策树森林来说,可以算出每个特征平均减少了多少不纯度,并把它平均减少的不纯度作为特征选择的值。

from sklearn.ensemble import RandomForestRegressor
import numpy as np
import pandas as pd
##构建数据集
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
X = np.array(df_before[df_before.columns[:-1]])
Y = np.array(df_before[df_before.columns[-1]])
names = df_before.columns.tolist()[:-1]
##建模
rf = RandomForestRegressor()
rf.fit(X, Y)
##输出排序结果
print "特征排序-按得分:"
print sorted(zip(map(lambda x: round(x, 4), rf.feature_importances_), names),reverse=True)

(2)平均精确度减少:另一种常用的特征选择方法就是直接度量每个特征对模型精确率的影响。主要思路是打乱每个特征的特征值顺序,并且度量顺序变动对模型的精确率的影响。很明显,对于不重要的变量来说,打乱顺序对模型的精确率影响不会太大,但是对于重要的变量来说,打乱顺序就会降低模型的精确率。

from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import ShuffleSplit
from sklearn.metrics import r2_score
from collections import defaultdict
import numpy as np
import pandas as pd
##构造数据集
df_before = pd.DataFrame([[1,2,3,1],[2,2,3,2],[3,1,2,9],[4,1,2,4],[5,2,3,4]],columns=["columns1","columns2","columns3","label"])
X = np.array(df_before[df_before.columns[:-1]])
Y = np.array(df_before[df_before.columns[-1]])
names = df_before.columns.tolist()[:-1]
##建模-评分
rf = RandomForestRegressor()
scores = defaultdict(list)for train_idx, test_idx in ShuffleSplit(len(X), 100, .3):X_train, X_test = X[train_idx], X[test_idx]Y_train, Y_test = Y[train_idx], Y[test_idx]r = rf.fit(X_train, Y_train)acc = r2_score(Y_test, rf.predict(X_test))for i in range(X.shape[1]):X_t = X_test.copy()np.random.shuffle(X_t[:, i])shuff_acc = r2_score(Y_test, rf.predict(X_t))scores[names[i]].append((acc - shuff_acc) / acc)
##输出排序结果
print "特征排序-按得分:"
print sorted([(round(np.mean(score), 4), feat) for feat, score in scores.items()], reverse=True)

四、总结

特征决定上限,模型逼近上限。但是很少有一本机器学习的书讨论如何开展特征工程工作,因此本文对一些特征选择的常见方法进行了总结,以便作为日后特征选择工作的参考。

参考文献

1.特征选择/筛选方法总结:https://blog.csdn.net/jliang3/article/details/88912464

2. 机器学习:特征选择(feature selection)https://blog.csdn.net/qq_33876194/article/details/88403394

3. 机器学习之特征选择 https://www.cnblogs.com/nolonely/p/6435083.html

4. 特征选择——卡方检验(使用Python sklearn进行实现) https://blog.csdn.net/snowdroptulip/article/details/78867053?utm_source=blogxgwz4

5. Distance correlation(距离相关系数)https://blog.csdn.net/jiaoaodechunlv/article/details/80655592

6. 结合Scikit-learn介绍几种常用的特征选择方法https://blog.csdn.net/Bryan__/article/details/51607215

7. sklearn的feature_importances_含义是什么?https://blog.csdn.net/weixin_37659245/article/details/100171656

机器学习特征工程之特征选择相关推荐

  1. 机器学习——特征工程之特征选择

    特征工程包括以下三种类型: 1.特征提取:从文字.图像.声音等非结构化特征中提取新信息作为特征.例如:从淘宝宝贝的名称中提取出 产品类别,产品颜色,是否是网红 产品等等. 2.特征创造:把现有特征进行 ...

  2. 机器学习-特征工程中的特征选择

    对于一个机器学习问题,数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限.由此可见,数据和特征在模型的整个开发过程中是比较重要.特征工程,顾名思义,是对原始数据进行一系列工程处理,将其提炼为 ...

  3. 双样本T检验——机器学习特征工程相关性分析实战

    最近在做数据分析方面的工作,经常需要检验两组样本之间是否存在差异,所以会遇到统计学中假设检验相关的知识.在机器学习特征工程这一步,笔者最常用到的是假设检验中的卡方检验去做特征选择,因为卡方检验可以做两 ...

  4. 机器学习-特征工程中的特征降维

    对于一个机器学习问题,数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限.由此可见,数据和特征在模型的整个开发过程中是比较重要.特征工程,顾名思义,是对原始数据进行一系列工程处理,将其提炼为 ...

  5. 机器学习-特征工程中的数据预处理

    对于一个机器学习问题,数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限.由此可见,数据和特征在模型的整个开发过程中是比较重要.特征工程,顾名思义,是对原始数据进行一系列工程处理,将其提炼为 ...

  6. 机器学习实战 | 机器学习特征工程最全解读

    作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/41 本文地址:https://www.showmeai.tech/article-d ...

  7. 机器学习特征工程之连续变量离散化:聚类法进行分箱

    机器学习特征工程之连续变量离散化:聚类法进行分箱 离散化,就是把无限空间中有限的个体映射到有限的空间中: 根据用户的听音乐的数据来预测哪些歌曲更受欢迎. 假设大部分人听歌都很平均,会不停的听新的歌曲, ...

  8. 机器学习特征工程之连续变量离散化:等频分箱

    机器学习特征工程之连续变量离散化:等频分箱 离散化,就是把无限空间中有限的个体映射到有限的空间中: 根据用户的听音乐的数据来预测哪些歌曲更受欢迎. 假设大部分人听歌都很平均,会不停的听新的歌曲,但是有 ...

  9. 机器学习特征工程之连续变量离散化:连续变量二值化(Binarizer)

    机器学习特征工程之连续变量离散化:连续变量二值化(Binarizer) 离散化,就是把无限空间中有限的个体映射到有限的空间中: 根据用户的听音乐的数据来预测哪些歌曲更受欢迎. 假设大部分人听歌都很平均 ...

最新文章

  1. Tomcat+Apache 负载均衡
  2. 【Linux 内核 内存管理】内存管理架构 ⑤ ( sbrk 内存分配系统调用代码示例 | 在 /proc/pid/maps 中查看进程堆内存详情 )
  3. 根据html页面模板动态生成html页面(c#类)
  4. django(7)modelform操作及验证、ajax操作普通表单数据提交、文件上传、富文本框基本使用...
  5. STM32工作笔记0011---认识跳线帽
  6. linux驱动开发框架
  7. 【Music】Never took the time
  8. 使用javassist
  9. 移动硬盘插入提示需要格式化RAW_使用驱动器X:中的光盘之前需要将其格式化
  10. Reincarnation
  11. keyshot局部打光_KeyShot新手的第一次打光,无脑三点打光塑造模型质感
  12. Java开源在线商城系统 ostocy-jshop
  13. 从网友评论中思考成长性思维和固定性思维
  14. 高端大气的艺术海报的ps教程
  15. cadence SPB17.4 - CIS - add a new part
  16. 算法给小码农八大排序 八奇计只为宝儿姐
  17. 工作中常用的设计模式 -- 责任链模式
  18. Sourcetree的下载与安装
  19. 全国科技者工作日:关注科技工作者的工作与贡献,共创美好未来
  20. 小学网管中心计算机使用规定,中小学网管中心管理制度范本模板.doc

热门文章

  1. 求教各位大侠:问题事件AppHangB1
  2. MySQL餐饮管理系统
  3. 计算机组成原理(第三版)唐朔飞-第六章计算机的运算方法-课后习题(1-16)
  4. 莫冲动,捂口袋,练内功
  5. 与孩子一起学编程代码_这周与您的孩子一起做一个代码小时
  6. ngnix、tinyproxy搭建http正向代理
  7. (附源码)计算机毕业设计Java二手车车况在线评估
  8. 微信公众号第三方授权获取用户的的地理位置--坑
  9. 360浏览器浏览记录本地路径
  10. 「进击」的马老师、「疯抢」华为以及想打疫苗的中国人|极客一周