-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
208 lines (208 loc) · 105 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[tensorflow 2 安装以及 ImportError: DLL load failed解决]]></title>
<url>%2Finstall-tensorflow2.html</url>
<content type="text"><![CDATA[tensorflow 2的个人安装过程,以及解决出现的一些问题。 系统要求我安装的版本是 tensorflow 2.1.0,这个版本以及可以支持 CPU 和 GPU 的运行与计算。 Python 3.5-3.7 pip 19.0 或更高版本(需要 manylinux2010 支持) Ubuntu 16.04 或更高版本(64 位) macOS 10.12.6 (Sierra) 或更高版本(64 位)(不支持 GPU) Windows 7 或更高版本(64 位)(仅支持 Python 3) Raspbian 9.0 或更高版本 GPU 支持需要使用支持 CUDA® 的卡(适用于 Ubuntu 和 Windows) Windows安装过程本人是Windows系统,下面写一下Windows安装的过程。Windows安装需要注意以下几点: 安装适用于 Visual Studio 2015、2017 和 2019 的 Microsoft Visual C++ Redistributable。从 TensorFlow 2.1.0 版开始,此软件包需要 msvcp140_1.dll 文件(旧版可再发行软件包可能不提供此文件)。 该可再发行软件包随附在 Visual Studio 2019 中,但可以单独安装。 确保在 Windows 上启用了长路径 安装 64 位适用于 Windows 的 Python 3 版本 Microsoft Visual C++ Redistributable安装如果电脑里安装了Visual Studio 2015, 2017 and 2019,这一步就不用了,如果没有,你那这一步还是好好安装,要不然就会出现ImportError: DLL load failed错误。12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152>>> import tensorflow as tfTraceback (most recent call last): File "C:\Development\Python\Python37\lib\site-packages\tensorflow_core\python\pywrap_tensorflow.py", line 58, in <module> from tensorflow.python.pywrap_tensorflow_internal import * File "C:\Development\Python\Python37\lib\site-packages\tensorflow_core\python\pywrap_tensorflow_internal.py", line 28, in <module> _pywrap_tensorflow_internal = swig_import_helper() File "C:\Development\Python\Python37\lib\site-packages\tensorflow_core\python\pywrap_tensorflow_internal.py", line 24, in swig_import_helper _mod = imp.load_module('_pywrap_tensorflow_internal', fp, pathname, description) File "C:\Development\Python\Python37\lib\imp.py", line 242, in load_module return load_dynamic(name, filename, file) File "C:\Development\Python\Python37\lib\imp.py", line 342, in load_dynamic return _load(spec)ImportError: DLL load failed: The specified module could not be found.During handling of the above exception, another exception occurred:Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Development\Python\Python37\lib\site-packages\tensorflow\__init__.py", line 101, in <module> from tensorflow_core import * File "C:\Development\Python\Python37\lib\site-packages\tensorflow_core\__init__.py", line 40, in <module> from tensorflow.python.tools import module_util as _module_util File "C:\Development\Python\Python37\lib\site-packages\tensorflow\__init__.py", line 50, in __getattr__ module = self._load() File "C:\Development\Python\Python37\lib\site-packages\tensorflow\__init__.py", line 44, in _load module = _importlib.import_module(self.__name__) File "C:\Development\Python\Python37\lib\importlib\__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "C:\Development\Python\Python37\lib\site-packages\tensorflow_core\python\__init__.py", line 49, in <module> from tensorflow.python import pywrap_tensorflow File "C:\Development\Python\Python37\lib\site-packages\tensorflow_core\python\pywrap_tensorflow.py", line 74, in <module> raise ImportError(msg)ImportError: Traceback (most recent call last): File "C:\Development\Python\Python37\lib\site-packages\tensorflow_core\python\pywrap_tensorflow.py", line 58, in <module> from tensorflow.python.pywrap_tensorflow_internal import * File "C:\Development\Python\Python37\lib\site-packages\tensorflow_core\python\pywrap_tensorflow_internal.py", line 28, in <module> _pywrap_tensorflow_internal = swig_import_helper() File "C:\Development\Python\Python37\lib\site-packages\tensorflow_core\python\pywrap_tensorflow_internal.py", line 24, in swig_import_helper _mod = imp.load_module('_pywrap_tensorflow_internal', fp, pathname, description) File "C:\Development\Python\Python37\lib\imp.py", line 242, in load_module return load_dynamic(name, filename, file) File "C:\Development\Python\Python37\lib\imp.py", line 342, in load_dynamic return _load(spec)ImportError: DLL load failed: The specified module could not be found.Failed to load the native TensorFlow runtime.See https://www.tensorflow.org/install/errorsfor some common reasons and solutions. Include the entire stack traceabove this error message when asking for help. 解决方案就是去Microsoft Visual C++下载页面,下载x64: vc_redist.x64.exe, 完成安装。因为你的电脑必须要是64位的,才能安装64位的 Python 3,才能满足 tensorflow 2.1.0的安装要求。 长路径长路径好像不启用,也没什么问题,但保险起见,还是打开吧,反正也挺容易的。 按 win+R,输入 gpedit.msc,打开本地策略组编辑器 依次选择 计算机配置 > 管理模板 > 系统 > 文件系统 在 文件系统 界面下,选择 启用 Win32 长路径,双击打开,选择已启用,然后确定关闭。 64位 Python 3一定要安装64位的 Python 3。查看 Python 3 版本方式有很多,下面写两个最简单的。 打开 cmd 命令行, 输入 python -VV。python -V 是简略的版本信息,python -VV 信息更加详细,包括位数信息,我的64位版本信息如下: 1Python 3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)] 打开python命令行,最开始出现的消息里面就有位数信息。 1234C:\Users\*******>pythonPython 3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> 在 Windows 上,仅支持在 Python 3 64位版本下, 安装 TensorFlow 2.1.0,如果是 Python 2 版本, 在 Windows 上是实现不了的。 安装 TensorFlow 2.1.0安装使用 pip 工具,19.0 或者更高版本。如果在虚拟环境里安装,注意先要更新 pip,然后在进行 pip 的安装 ( python -m pip install --upgrade pip )。1pip install tensorflow 由于安装包比较大,推荐使用国内镜像,在命令行后加 -i [https://xxxxx] 即可,下面是使用清华镜像源,你也可以永久修改默认源的使用,这里就不介绍了。1pip install tensorflow -i https://pypi.tuna.tsinghua.edu.cn/simple GPU 安装支持如果你进行了以上安装,不出意外的话,tensorflow 应该是安装成功了,但你在使用时可能会看到以下警告,因为现在的 tensorflow 只能使用 CPU,无法使用 GPU。1232020-xx-xx xx:xx:xx.xxxxxx: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'cudart64_101.dll'; dlerror: cudart64_101.dll not found2020-xx-xx xx:xx:xx.xxxxxx: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine. 首先查看你的 GPU 是否支持 CUDA,点击查询页面查找自己的显卡是否在列表内。或者使用”显卡名称 + specification“进行搜索,直接查看自己的显卡信息。 显卡支持后,如果要使用 GPU,还需要安装下面几个软件: NVIDIA Graphic Drivers (一般都有) NVIDIA CUDA Toolkit, CUDA 安装文档 cuDNN SDK, cuDNN 安装文档 CUDA 选择 10.1 版本,cuDNN 选择配套版本。安装完成后,import tensorflow 不报错,无警告,应该就成功了。 检查使用情况最后,在看看自己设备上的使用信息。1234567891011121314151617181920from tensorflow.python.client import device_libprint(device_lib.list_local_devices())[name: "/device:CPU:0"device_type: "CPU"memory_limit: 268435456locality {}incarnation: 11567553738839476818, name: "/device:GPU:0"device_type: "GPU"memory_limit: 6661821563locality { bus_id: 1 links { }}incarnation: 17494855292993829603physical_device_desc: "device: 0, name: GeForce GTX 1070 Ti, pci bus id: 0000:01:00.0, compute capability: 6.1"] 至此,结束,感觉挺麻烦的。]]></content>
<tags>
<tag>tensorflow</tag>
</tags>
</entry>
<entry>
<title><![CDATA[机器学习实战第3章笔记]]></title>
<url>%2Fhands-on-chapter3-notes.html</url>
<content type="text"><![CDATA[《机器学习实战》一书第3章笔记。 MNIST数据集用sklearn下载流行数据集,数据保存在C:\Users\<username>\scikit_learn_data文件夹中,不想更改用户名,可以用%HOMEPATH%\scikit_learn_data直接访问。1234from sklearn.datasets import fetch_openmlmnist = fetch_openml('mnist_784', version=1)mnist.keys()# dict_keys(['data', 'target', 'feature_names', 'DESCR', 'details', 'categories', 'url']) 二元分类器SGDClassifier是用随机梯度下降法进行参数训练的线性分类器。1234567from sklearn.linear_model import SGDClassifiersgd_clf = SGDClassifier(max_iter=1000, tol=1e-3, random_state=42)sgd_clf.fit(X_train, y_train_5)# 随机分类器from sklearn.dummy import DummyClassifier 性能考核交叉验证1234567891011121314151617181920from sklearn.model_selection import cross_val_scorecross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring="accuracy")# 手动实现交叉验证from sklearn.model_selection import StratifiedKFoldfrom sklearn.base import cloneskfolds = StratifiedKFold(n_splits=3, random_state=42)for train_index, test_index in skfolds.split(X_train, y_train_5): clone_clf = clone(sgd_clf) X_train_folds = X_train[train_index] y_train_folds = y_train_5[train_index] X_test_fold = X_train[test_index] y_test_fold = y_train_5[test_index] clone_clf.fit(X_train_folds, y_train_folds) y_pred = clone_clf.predict(X_test_fold) n_correct = sum(y_pred == y_test_fold) print(n_correct / len(y_pred)) 混淆矩阵 所有的Negetive和Positive都是指的预测,True和False指预测对错,对角线上的元素都是预测对的。 12345from sklearn.model_selection import cross_val_predictfrom sklearn.metrics import confusion_matrixy_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)confusion_matrix(y_train_5, y_train_pred) 精度和召回率123456from sklearn.metrics import precision_score, recall_scoreprecision_score(y_train_5, y_train_pred)recall_score(y_train_5, y_train_pred)from sklearn.metrics import f1_scoref1_score(y_train_5, y_train_pred) $F_1$公式如下:$$F_1 = \frac{2}{\frac{1}{Precison}+\frac{1}{Recall}} = \frac{2TP}{2TP+FN+FP}$$ 精度/召回率权衡(PR曲线)12345y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3,method="decision_function")# precision_recall_curve需要传入预测分数,而不是预测结果from sklearn.metrics import precision_recall_curveprecisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)plt.plot(recalls, precisions, "b-", linewidth=2) ROC曲线ROC曲线绘制的是真正类率(灵敏度,TPR, Recall)和假正类率(FPR, 1-Specificity)的关系。123456from sklearn.metrics import roc_curvefpr, tpr, thresholds = roc_curve(y_train_5, y_scores)# ROC AUCfrom sklearn.metrics import roc_auc_scoreroc_auc_score(y_train_5, y_scores) 多类别分类器多类别分类器可以由二元分类器扩展,OVR(one-versus-the-rest, or one-versus-all, OVA)或者OVO(one-versus-one), sklearn会自动选择运行OVR还是OVO,多数时候都是OVR,SVM选择OVO。你也可以强制指定选用哪种方法。1234from sklearn.multiclass import OneVsOneClassifierovo_clf = OneVsOneClassifier(sgd_clf)ovo_clf.fit(X_train, y_train)len(ovo_clf.estimators_) # 45 但是有些分类可以直接进行多分类,无需OVR和OVO。SGD就可以。 错误分析通过混淆矩阵,分析某些错误实例。 多标签分类结果输出多个标签,而不是一个。KNN支持多标签分类。123456789from sklearn.neighbors import KNeighborsClassifiery_train_large = (y_train >= 7)y_train_odd = (y_train % 2 == 1)y_multilabel = np.c_[y_train_large, y_train_odd]knn_clf = KNeighborsClassifier()knn_clf.fit(X_train, y_multilabel)knn_clf.predict([some_digit]) # array([[False, True]]) 多输出分类多标签的泛化,标签可以多种类别。123456789# 图片降噪示例,输出是图片的向量noise = np.random.randint(0, 100, (len(X_train), 784))X_train_mod = X_train + noisenoise = np.random.randint(0, 100, (len(X_test), 784))X_test_mod = X_test + noisey_train_mod = X_trainy_test_mod = X_testknn_clf.fit(X_train_mod, y_train_mod)clean_digit = knn_clf.predict([X_test_mod[0]])]]></content>
<tags>
<tag>机器学习实战</tag>
</tags>
</entry>
<entry>
<title><![CDATA[机器学习实战第2章笔记]]></title>
<url>%2Fhands-on-machine-learing-chapter2-notes.html</url>
<content type="text"><![CDATA[《机器学习实战》一书第2章笔记。 性能指标均方根误差(RMSE)$$RMSE(\mathbf{X}, h) \:=\:\sqrt{\frac{1}{m}\sum^{m}_{i=1}{\Big(h(\mathbf{x}^{(i)})-y^{(i)}\Big)^2}}$$ 平均绝对误差(MAE)$$MAE(\mathbf{X}, h) \:=\: \frac{1}{m} \sum^m_{i=1}\Big|h(\mathbf{x}^{(i)})-y^{(i)}\Big|$$ 数据选取问题随机切分保证每次切分数据一致,需要设定随机种子。12345import numpy as npnp.random.seed(42)from sklearn.model_selection import train_test_splittrain_set, test_set = train_test_split(dataset, test_size=0.3, random_state=42) 唯一字段当数据更新后,上面的方法就不一定能保证切分后的训练集包括之前的训练集。可以通过对数据创建唯一字段,对唯一字段编写抽取方法,保证每次抽取的结果一致。1234import hashlibdef test_set_check(identifier, test_ratio, hash=hashlib.md5): return hash(np.int64(identifier)).digest()[-1] < 256 * test_ratio 分层抽样数据中某个字段比较重要,根据该字段进行分层抽样,保证抽样后的训练集与原始数据集比例一致。1234567from sklearn.model_selection import StratifiedShuffleSplitsplit = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)# dataset数据集, income分层依据字段for train_index, test_index in split.split(dataset, dataset["income"]): strat_train_set = dataset.loc[train_index] strat_test_set = dataset.loc[test_index] 数据可视化1234567891011121314151617import pandas as pdimport matplotlib.pyplot as plt# pandas.DataFrame类可以直接调用matplotlib进行画图dataset.hist(bins=20, figsize=(10,10)) # 对所用数值字段画直方图# 画散点图,设定alpha,有密度效果dataset.plot(kind="scatter", x="x_column", y="y_column", alpha=0.1)# 更多维度的散点图dataset.plot(kind="scatter", x="x_column", y="y_column", alpha=0.4, s="z_colunm", label="z_colunm", figsize=(10,7), c="k_column", cmap=plt.get_cmap("jet"), colorbar=True, sharex=False)plt.legend()# 多个散点图看相关性# dataset.corr()方法,可以计算出相关系数矩阵from pandas.plotting import scatter_matrixscatter_matrix(dataset[attr], figsize=(12, 8)) # 如果特征过多,挑选特征传入 数据清洗缺失值处理 删除缺失样本 删除缺失属性 填充缺失值 123456# 填充缺失值from sklearn.impute import SimpleImputerimputer = SimpleImputer(strategy="median")imputer.fit(dataset)X = imputer.transform(dataset)dataset_tr = pd.DataFrame(X, columns=dataset.columns, index=dataset.index) 文本处理和One-Hot编码123456789101112# 将文本类别转成numberfrom sklearn.preprocessing import OrdinalEncoderordinal_encoder = OrdinalEncoder()data_text_encoded = ordinal_encoder.fit_transform(data_text) # 返回arrayordinal_encoder.categories_ # 返回类别# one-hot编码,可以接受文本from sklearn.preprocessing import OneHotEncoder# OneHotEncoder(sparse=False) sparse默认True,false返回numpy的array矩阵text_encoder = OneHotEncoder()data_text_1hot = text_encoder.fit_transform(data_text) # Scipy稀疏矩阵housing_cat_1hot.toarray() # 返回array 自定义转换器12345678910111213# 可以放入pipeline中from sklearn.preprocessing import FunctionTransformerdef test(X, k=True): # input: X: array # output: array if k: return X else: return X[:10]test_func = FunctionTransformer(test, validate=False,kw_args={"k": False})test_func_result = test_func.fit_transform(dataset.values) Pipeline123456789101112131415161718from sklearn.pipeline import Pipelinefrom sklearn.preprocessing import StandardScaler # 标准化num_pipeline = Pipeline([ ('imputer', SimpleImputer(strategy="median")), ('test_func', FunctionTransformer(test, validate=False)), ('std_scaler', StandardScaler()),])datatset_tr = num_pipeline.fit_transform(datatset)# 多个pipeline结果结合from sklearn.pipeline import FeatureUnionold_full_pipeline = FeatureUnion(transformer_list=[ ("num_pipeline", old_num_pipeline), ("cat_pipeline", old_cat_pipeline),]) 模型计算RMSE和MAE12345678910from sklearn.metrics import mean_squared_error # RMSEfrom sklearn.metrics import mean_absolute_error # MAEfrom sklearn.linear_model import LinearRegressionlin_reg = LinearRegression()lin_reg.fit(X, y)y_hat = lin_reg.predict(y)lin_mse = mean_squared_error(y, y_hat)lin_rmse = np.sqrt(lin_mse)lin_mae = mean_absolute_error(y, y_hat) 交叉验证1234from sklearn.model_selection import cross_val_scorescores = cross_val_score(lin_reg, X, y, scoring="neg_mean_squared_error", cv=10)lin_rmse_scores = np.sqrt(-scores) 关于scoring参数选择参见文档 超参数选择网格搜索1234567891011121314151617181920212223from sklearn.model_selection import GridSearchCVfrom sklearn.ensemble import RandomForestRegressorparam_grid = [ # try 12 (3×4) combinations of hyperparameters {'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8]}, # then try 6 (2×3) combinations with bootstrap set as False {'bootstrap': [False], 'n_estimators': [3, 10], 'max_features': [2, 3, 4]},]forest_reg = RandomForestRegressor(random_state=42)# train across 5 folds, that's a total of (12+6)*5=90 rounds of training grid_search = GridSearchCV(forest_reg, param_grid, cv=5, scoring='neg_mean_squared_error', return_train_score=True)grid_search.fit(X, y)grid_search.best_params_grid_search.best_estimator_# 输出每次结果cvres = grid_search.cv_results_for mean_score, params in zip(cvres["mean_test_score"], cvres["params"]): print(np.sqrt(-mean_score), params) 随机搜索1234567891011121314151617181920212223242526from sklearn.model_selection import RandomizedSearchCVfrom scipy.stats import randint, uniform, geom, expon, reciprocal# uniform均匀分布, randint均匀分布的整数形式, geom几何分布, expon指数分布param_distribs = { 'n_estimators': randint(low=1, high=200), 'max_features': randint(low=1, high=8),}forest_reg = RandomForestRegressor(random_state=42)rnd_search = RandomizedSearchCV(forest_reg, param_distributions=param_distribs, n_iter=10, cv=5, scoring='neg_mean_squared_error', random_state=42)rnd_search.fit(X, y)from sklearn.svm import SVRparam_distribs = { 'kernel': ['linear', 'rbf'], 'C': reciprocal(20, 200000), 'gamma': expon(scale=1.0),}svm_reg = SVR()rnd_search = RandomizedSearchCV(svm_reg, param_distributions=param_distribs, n_iter=50, cv=5, scoring='neg_mean_squared_error', verbose=2, n_jobs=4, random_state=42)rnd_search.fit(X, y) reciprocal的概率密度函数如下$$f(x, a, b) = \frac{1}{x\log(b/a)} \qquad \textrm{for } a \le x \le b, \: b \ge a \ge 0$$更多详细的分布,参见官网文档 置信区间123456789101112131415161718from scipy import statssquared_errors = (final_predictions - y_test) ** 2mean = squared_errors.mean()m = len(squared_errors)# t-分布np.sqrt(stats.t.interval(confidence, m - 1, loc=np.mean(squared_errors), scale=stats.sem(squared_errors)))# stats.sem计算标准差,自由度是n-1 # ortscore = stats.t.ppf((1 + confidence) / 2, df=m - 1)tmargin = tscore * squared_errors.std(ddof=1) / np.sqrt(m)np.sqrt(mean - tmargin), np.sqrt(mean + tmargin)# 正态分布zscore = stats.norm.ppf((1 + confidence) / 2)zmargin = zscore * squared_errors.std(ddof=1) / np.sqrt(m)np.sqrt(mean - zmargin), np.sqrt(mean + zmargin) 选k个重要属性1234567891011121314from sklearn.base import BaseEstimator, TransformerMixin# 返回最大的k个数索引def indices_of_top_k(arr, k): return np.sort(np.argpartition(np.array(arr), -k)[-k:])class TopFeatureSelector(BaseEstimator, TransformerMixin): def __init__(self, feature_importances, k): self.feature_importances = feature_importances self.k = k def fit(self, X, y=None): self.feature_indices_ = indices_of_top_k(self.feature_importances, self.k) return self def transform(self, X): return X[:, self.feature_indices_] 加入数据处理的网格搜索在网格搜索中加入数据清洗阶段的参数,需要用到pipeline,通过__调用参数名。12345678910111213141516rp = Pipeline([ ('imputer', SimpleImputer()), ('test_func', FunctionTransformer(test, validate=False)), ('std_scaler', StandardScaler()), ('feature_selection', TopFeatureSelector(feature_importances, k)) ('lin_reg', LinearRegression()),])# feature_importances = grid_search.best_estimator_.feature_importances_param_grid = [{ 'imputer__strategy': ['mean', 'median', 'most_frequent'], 'feature_selection__k': list(range(1, len(feature_importances) + 1))}]grid_search_prep = GridSearchCV(rp, param_grid, cv=5,scoring='neg_mean_squared_error', verbose=2, n_jobs=4)grid_search_prep.fit(X, y)grid_search_prep.best_params_]]></content>
<tags>
<tag>machine learning</tag>
<tag>机器学习实战</tag>
</tags>
</entry>
<entry>
<title><![CDATA[pandas笔记]]></title>
<url>%2Fpandas-notes.html</url>
<content type="text"><![CDATA[pandas常用命令整理。 重命名列名1234# 命名一列df.rename(columns={df.columns[2]: "A"}, inplace=True)# 命名全部df.columns = ['A', 'B', 'C'] 删除行列123456789# 删除一行df.drop(0[, inplace=False])# 删除多行df.drop([a,b])# 删除一列del df['A']df.drop('A')# 删除多列df.drop(['A','B']) 排序12df.sort_values('A'[,inplace=True])df.sort_values(by=['a','c']) 去重12df.duplicated() #返回true or falsedf.drop_duplicates(['column']) 连接数据库123456789import pymysql # 其他数据库也可以,创建数据库连接就行import pandas as import pddb = pymysql.connect(host='', port='', user='', passwd='', db='')# 读取数据query = "" # 查询语句df = pd.read_sql(sql=query, con=db)# 存储数据df.to_sql('table_name', con=db, if_exists='append', index=False) # if_exists: fail, append, replace 写入excel(多sheet)1234writer = pd.ExcelWriter('t.xlsx')df1.to_excel(writer,'sheet1',index=0)df2.to_excel(writer,'sheet2',index=0)writer.save() 透视表1pd.pivot_table(dataframe,index='c1', values=['c2','c3','c4'], aggfunc={'c2':sum,'c3':lambda x: len(x.unique()),'c4':len}, margins=True,margins_name='total') 环比12# 计算环比d2 = (dt-dt_last).reindex(dt.index) 切分类别1pd.cut([sequence], bins, labels) 条件替换123456789# Replace values where the condition is Falsedf.where(cond, other, inplace)# Replace values where the condition is Truedf.mask(cond, other, inplace)# 将`nan`替换成0cond = df.isna()df.where(~cond, 0)# ordf.mask(cond, 0)]]></content>
<tags>
<tag>pandas</tag>
</tags>
</entry>
<entry>
<title><![CDATA[matplotlib笔记]]></title>
<url>%2Fmatplotlib-notes.html</url>
<content type="text"><![CDATA[matplotlib的一些使用整理笔记,详细使用参见官网。 交互绘图matplotlib有交互模式,可以通过交互模式实现动态绘图。主要通过循环绘图==>清除上一幅图片==>绘图,来实现动态图表。1234567891011121314151617181920import matplotlib.pyplot as pltimport numpy as np# plt.ion() 打开交互模式# plt.ioff() 关闭交互模式# plt.clf() 清除图像(figure)# plt.cla() 清除Axes# plt.pause() 交互模式下暂停并展示图表X, Y = np.random.rand(2, 10)x, y = [], []plt.ion()for i in range(len(X)): plt.clf() # 不删除图表一样可以运行,但之前图表会一直占用内存 x.append(X[i]) y.append(Y[i]) plt.scatter(x, y) plt.pause(0.2)plt.ioff()plt.show() 全局变量matplotlib提供了变更全局变量的方式。1234567891011121314import matplotlib as mpl# 方式一mpl.rcParams['lines.linewidth'] = 2mpl.rcParams['lines.color'] = 'r'# 方式二mpl.rc('lines', linewidth=2, color='r')# 中文乱码指定字体plt.rcParams['font.sans-serif'] = ['SimHei']# 正常显示负号plt.rcParams['axes.unicode_minus'] = False# 如果不想每次都指定这些内容,可以将这些内容直接写入到默认配置文件matplotlibrcmpl.matplotlib_fname() # 配置文件路径 风格matplotlib提供了不少的风格选项,可以自己指定,或者使用默认风格。12345678# 输出可用风格print(plt.style.availabel)# 指定全局风格plt.style.use('ggplot')# 只想临时使用某种风格,而不改变全局风格with plt.style.context('ggplot'): plt.plot(np.sin(np.linspace(0, 2 * np.pi)), 'r-o')plt.show() 注释在图表中加入箭头类型的注释文本,具体使用参见网址1plt.annotate(text, xy, xytext, arrowprops) 坐标轴坐标轴设定很多,这里就写一些常用的。123456789101112# 坐标轴标签plt.xlabel("X",fontsize=10,fontweight='bold')# 坐标轴范围plt.axis(xlim=(xmin, xmax), ylim=(ymin, ymax))plt.axis([xmin, xmax, ymin, ymax])plt.xlim(xmin, xmax)# 不显示坐标轴plt.axis('off')# 横纵坐标轴刻度相等plt.axis('equal')# 坐标轴刻度标签plt.xticks([0,1,2,3])]]></content>
<tags>
<tag>matplotlib</tag>
</tags>
</entry>
<entry>
<title><![CDATA[selenium笔记]]></title>
<url>%2Fselenium-notes.html</url>
<content type="text"><![CDATA[selenium简单整理。 设定下载位置1234options = webdriver.ChromeOptions()prefs = {'profile.default_content_settings.popups': 0, 'download.default_directory': path}options.add_experimental_option('prefs', prefs)driver = webdriver.Chrome(executable_path='D:/chromedriver/chromedriver.exe', chrome_options=options) 设定窗口12driver.set_window_size(400, 600)driver.maximize_window() 等待12345678910# 显示等待from selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECwait_result = WebDriverWait(driver=driver, timeout=300, poll_frequency=0.5, ignored_exceptions=None).until( EC.visibility_of_element_located((By.XPATH, '//[]')))# 隐式等待driver.implicitly_wait(100) 滚动条12# 滚动到底driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") 截图和无界面12345678910from selenium import webdriveroptions = webdriver.ChromeOptions()options.headless = True# 指定窗口大小,默认的浏览界面太小的话,定位某些元素时会出错,而且由于你看不到浏览器,这个错误还不容易发现options.add_argument('window-size=1366,768')options.add_argument('--disable-gpu')driver = webdriver.Chrome(chrome_options=options,executable_path='D:/chromedriver/chromedriver.exe')# 截图driver.get_screenshot_as_file('file.png')]]></content>
<tags>
<tag>selenium</tag>
</tags>
</entry>
<entry>
<title><![CDATA[numpy笔记]]></title>
<url>%2Fnumpy-notes.html</url>
<content type="text"><![CDATA[对以前所学的numpy进行整理,详细使用说明参见官网,或者翻阅《Python for Data Analysis, 2nd Edition》一书,有其他博主进行翻译过。 数组和矩阵numpy主要有两大类,数组<class 'numpy.ndarray'>和矩阵<class 'numpy.matrix'>。两大类方法有些类似,但在有些操作上是不同的,也可以相互转换。123456789101112import numpy as np# 数组a = np.array([[1, 2], [3, 4]])# 矩阵bb = np.mat([[1, 2], [3, 4]])# 数组转矩阵b = np.mat(a)# 矩阵转数组b.A 矩阵和数组在乘法上有所区别,矩阵可以直接相乘,而数组需要dot方法,如果数组直接相乘,结果是相应位置相乘,矩阵要实现相应位置相乘,要调用np.multiply方法。 $X = A_{m \times n} * B_{n \times m}$ 1234567# a.shape = (m, n)# b.shape = (n, m)# 矩阵相乘x = a * b# 数组相乘x = a.dot(b)x = np.dot(a, b) $X_{ij} = A_{ij}*B_{ij}$ 12345# a.shape = b.shape# 矩阵相乘x = np.multiply(a, b)# 数组相乘x = a * b 常用方法摘自《Python for Data Analysis, 2nd Edition》。 数组创建 Function Description array Convert input data (list, tuple, array, or other sequence type) to an ndarray either by inferring a dtype or explicitly specifying a dtype; copies the input data by default asarray Convert input to ndarray, but do not copy if the input is already an ndarray arange Like the built-in range but returns an ndarray instead of a list ones, ones_like Produce an array of all 1s with the given shape and dtype; ones_like takes another array and produces a ones array of the same shape and dtype zeros, zeros_like Like ones and ones_like but producing arrays of 0s instead empty, empty_like Create new arrays by allocating new memory, but do not populate with any values like ones and zeros full, full_like Produce an array of the given shape and dtype with all values set to the indicated “fill value”; full_like takes another array and produces a filled array of the same shape and dtype eye, identity Create a square N × N identity matrix (1s on the diagonal and 0s elsewhere) 线性代数使用numpy.linalg函数 Function Description diag Return the diagonal (or off-diagonal) elements of a square matrix as a 1D array, or convert a 1D array into a square matrix with zeros on the off-diagonal dot Matrix multiplication trace Compute the sum of the diagonal elements det Compute the matrix determinant eig Compute the eigenvalues and eigenvectors of a square matrix inv Compute the inverse of a square matrix pinv Compute the Moore-Penrose pseudo-inverse of a matrix qr Compute the QR decomposition svd Compute the singular value decomposition (SVD) solve Solve the linear system Ax = b for x, where A is a square matrix lstsq Compute the least-squares solution to Ax = b one-hot编码使用numpy进行one-hot编码。1234567# label.shape = (1, )# 将label转换成int,因为index是intlabel_int = label.astype(int) # 计算标签种类k = len(set(label_int))# one-hot编码label = np.eye(k)[label_int]]]></content>
<tags>
<tag>numpy</tag>
</tags>
</entry>
<entry>
<title><![CDATA[用python操作office软件]]></title>
<url>%2Foffice-with-python.html</url>
<content type="text"><![CDATA[我用过的操作office的python包。 openpyxl工作中,有时候会需要批量处理一些文件,或者,产出日常报表。我之前的工作就有涉及到日常报表的产出,报表是Excel文件,内容有一定格式要求,每天做总有点无趣,而且人工也有失误的时候,实现自动化是十分有必要的。一开始使用vba进行处理,后来遇到了一些麻烦,主要是数据来源是多方面的,有的是一份excel文件,有的需要数据库查询,这时候用vba写就显得有点麻烦。后来我改用python去处理,调用openpyxl包,进行excel文件内容的写入和格式的设定,主要是格式设定也不是很复杂,太过复杂的格式处理,openpyxl也处理不了,大部分的格式处理都已经涵盖了,很少会有超出的,即使有,也可以用一些替代方案。最终,用python实现了一键运行产出报表。12345678910from openpyxl import Workbookfrom openpyxl.styles import PatternFill, Border, Side, Alignment, Font, colorswb = Workbook()ws = wb.activews.title = "Sheet1"ws.cell(row, column).value = Nonefilename = "test.xlsx"wb.save(filename)# 网格不显示ws.sheet_view.showGridLines = False 具体单元格样式更改参见官网教程,官网上也用详细的教程和说明。 pywin32出了上面的openpyxl外,还有不少其他的包,个人愚见,其中功能最全面的应该是pywin32包。当然,我也觉得它是最难用的包,用起来并不简单。如果说,openpyxl还有些功能实现不了以外,pywin32几乎实现了日常使用的所有功能。而且,pywin32不仅可以操作excel,还可以操作word,其他的office好像也可以操作,不过我没有使用过。工作中,有次接了个任务,把公司平台上的试卷按格式导出,包括试题和答案。我就是用pywin32去操作word,从试卷平台上抓数据(我还没有试卷平台的数据库,写爬虫抓的数据),写入word,最后调整格式,产出word文件。整个pywin32,几乎用的都是vba一样的接口,不知道这是不是它没有一份完整详细的官方说明文档的原因。关于,vba的知识可以查看微软的相关网址。如果能熟练运用vba,相信pywin32上手很快。我不是很熟悉,折腾了一番。 结语上面的这些工具,能够大幅度减少重复性高的日常工作或者是批量工作,个人工作上的体会。]]></content>
<tags>
<tag>python</tag>
<tag>office</tag>
<tag>word</tag>
<tag>excel</tag>
<tag>openpyxl</tag>
<tag>pywin32</tag>
</tags>
</entry>
<entry>
<title><![CDATA[python爬虫学习笔记]]></title>
<url>%2Fpython-crawler-notes.html</url>
<content type="text"><![CDATA[总览对以前学过的爬虫进行总结,巩固知识,也希望能帮助他人。初学爬虫的时候,看了一段视频入门,再后来走了不少弯路,究其原因是没有对爬虫有个整体性的掌握。我想整里一份框架,概括自己所学的同时,给初学者一点指导和帮助。学习爬虫,首先需要一门编程语言来实现,我推荐python,简单易学,上手快。还要学习一些相关的python爬虫包,如requests。再来,需要了解一下HTML网页的知识,因为你需要从网页中提取信息,不了解网页是不行。学会使用抓包工具,如fiddle4,其实大部分情况下,chrome浏览器的控制台就足够了。学会反爬,没办法,现在很多网站都有反爬,不会一点技巧,难以获得信息。如果你需要将信息存入数据库的话,你还要学会操作数据库,关系型数据库,如MySQL,非关系型数据库,如mongo,redis。当然,大规模抓取的时候,少不了用一些框架,如scrapy。简单的列举如下: python 爬虫相关包:requests, selenium, … HTML fiddler4,chrome控制台 反爬 数据库:MySQL, mongo, redis, … 爬虫框架:scrapy, PySpider, … … python和HTML知识就不介绍了,相关信息很容易查阅,下面会依次介绍一下python里面和爬虫相关的包。 requestsrequests是python3里面,爬虫的核心package,详情见官网。官网里面有详细的文档和教程。另一个相关包,selenium就不在本文介绍了。 编码问题requests请求返回的结果有时候会显示为乱码,你可以指定编码。有时候,有些文本(例如表情)因为编码问题无法保存到txt,excel或者数据库,你可以使用编码后再解码的方式过滤掉。1234import requestsr = requests.get('https://www.baidu.com')r.enconding = 'utf8' # 指定编码text = r.text.encode('utf8', 'ignore').decode('utf8') # 编码后解码 参数传递传递参数一般使用字典构造,不同方法,传递参数的关键字也不同。123456789payload = {'key1': 'value1', 'key2': 'value2'}# GET方法r = requests.get("http://httpbin.org/get", params=payload)# POST方法,需要注意的是,即使是POST方法,有时候仍然会有params参数r = requests.post("http://httpbin.org/post", data=payload)# POST有时会用json作为参数r = requests.post(url, json=payload) json返回requests提供了json返回的便捷接口。12# 返回json解码后的dictr.json() 需要注意的是,如果r.text不是json格式,r.json()解码失败。但即使解码成功,也不意味这你获得了你想要的结果,有些服务器在失败的响应中返回的也是json对象,你需要验证r.status_code和内容。 定制HEADER定制HEADER可以说是反爬的第一步,也是最简单的一步。很多网站会禁止机器访问,定制header是十分有必要的。header里面有很多参数,有些有用,有些就不是那么必要,看情况。1234h = { 'user-agent:': '' # 可以在浏览器里面copy一下}r = requests.get(url, headers=headers) Cookie和简单的反爬技巧cookie是登录网站的记录,一般网站都会用cookie来限制爬虫。自动登录网站,获取cookie,大多数时候不是那么容易实现的。大多数网站都是通过javascript脚本验证登录,中间经历多个传参和跳转,最终才能拿到cookie,微博登录就是典型的例子。还有的,加入了验证码。这就比较麻烦了,简单的验证码还好处理,复杂的验证码,几乎没办法。有些平台提供了验证码识别的api,当然是付费的。你可以调用他们的api,实现验证码输入。当然,如果你对数据量需求不大,同时,网站服务器也没有针对账号和ip进行反爬,自己手动登录,获取cookie,进行爬虫是最简单的处理方案。针对账号反爬,会限制同一账户短时间内的过多访问,如果需要短时间大量爬取数据,多账号是必不可少的。ip限制也是类似,可以通过代理池解决。如果需要的数据量不大,控制访问速度就行了。12345678910cookie = { 'key': 'value'}r = requests.get(url, cookies=cookie)# 代理proxies = { "http": "http://10.10.1.10:3128", "https": "http://10.10.1.10:1080",}r = requests.get("http://example.org", proxies=proxies) 关于cookie获取,还有个需要注意的地方。在实现自动登录获取cookie的时候,有些教程会建议使用session的会话方式记住cookie,这种方式有时可行,有的时候不行。究其根本,是在登录过程中进行了多次跳转,多次设置cookie,session的方式没能成功的设置最后的cookie。这种时候,需要自己去分析登录过程中的参数传递和cookie设置。有些小伙伴,可能在此过程中找不到cookie,发现r.cookies是空的,或者没有自己要的cookies,可以在返回的请求头r.headers里面找找看,它的set-cookie可能就是你需要的。r.request.headers也可以试试,如果你某些参数设置错误,你的cookie可能会进到里面,在另外一篇博文里面看到的,具体是哪篇想不起来了。 信息提取从HTML中提取信息方法很多,可以用re,xpath,BeautifulSoup,等等。re适用于任何文本的提取,就不说了。xpath和BeautifulSoup网上的教程也有很多,建议两种方法都掌握,都很简单。 xpath基础语法 表达式 描述 nodename 选取此节点的所有子节点。 / 从根节点选取。 // 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 . 选取当前节点。 .. 选取当前节点的父节点。 @ 选取属性。 12345678910111213from lxml import etreeimport requestr = requests.get('https://www.baidu.com')html = etree.HTML(r.text)result = etree.tostring(html)# tostring()方法即可输出修正后的HTML代码,但是结果是bytes类型print(result.decode('utf-8'))result = html.xpath('//li')# 返回的是list类型,每个元素是element类型,选取什么元素,就用基础语法进行组合就好,节点内文本使用text()html.xpath('//li[@class="li"]/a/text()')# 属性有多个值就需要用 contains() 函数html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()') BeautifulSoup的selectBeautifulSoup支持最常用的CSS selectors,通过select方法调用。当然,BeautifulSoup也有自己的方法,使用起来也用方便。1234from bs4 import BeautifulSoupr = requests.get('https://www.baidu.com')soup = BeautifulSoup(r.text, 'html.parser')soup.select('title') 下表来自w3schools的CSS Selector Reference,只拿了一部分,完整表格参见网址,可能有部分不支持。 Selector Example Example description .class .intro Selects all elements with class=”intro” .class1.class2 <div class="name1 name2">...</div> Selects all elements with both name1 and name2 set within its class attribute .class1 .class2 <div class="name1"><div class="name2">...</div></div> Selects all elements with name2 that is a descendant of an element with name1 #id #firstname Selects the element with id=”firstname” * * Selects all elements element p Selects all <p> elements element.class p.intro Selects all <p> elements with class=”intro” element,element div, p Selects all <div> elements and all <p> elements element element div p Selects all <p> elements inside <div> elements element>element div > p Selects all <p> elements where the parent is a <div> element element+element div + p Selects all <p> elements that are placed immediately after <div> elements element1~element2 p ~ ul Selects every <ul> element that are preceded by a <p> element [attribute] [target] Selects all elements with a target attribute [attribute=value] [target=_blank] Selects all elements with target=”_blank” [attribute~=value] [title~=flower] Selects all elements with a title attribute containing the word “flower” [attribute|=value] [lang|=en] Selects all elements with a lang attribute value starting with “en” [attribute^=value] a[href^=”https”] Selects every <a> element whose href attribute value begins with “https” [attribute$=value] a[href$=”.pdf”] Selects every <a> element whose href attribute value ends with “.pdf” [attribute*=value] a[href*=”w3schools”] Selects every <a> element whose href attribute value contains the substring “w3schools” 数据库我主要使用的数据库还是MySQL,mongo和redis使用很少,它们使用起来都不困难,python都提供了相应的包进行操作。pymysql是python里面用来操作mysql数据库的包,详情参见官网。操作很简单,下面是官网的例子。12345678910111213141516171819202122232425262728import pymysql.cursors# Connect to the databaseconnection = pymysql.connect(host='localhost', user='user', password='passwd', db='db', charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor)try: with connection.cursor() as cursor: # Create a new record sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)" cursor.execute(sql, ('[email protected]', 'very-secret')) # connection is not autocommit by default. So you must commit to save # your changes. connection.commit() with connection.cursor() as cursor: # Read a single record sql = "SELECT `id`, `password` FROM `users` WHERE `email`=%s" cursor.execute(sql, ('[email protected]',)) result = cursor.fetchone() print(result)finally: connection.close() 爬虫框架实际上,小规模的爬取数据根本用不上框架。爬虫框架一般用来进行大规模爬取,搭建一个爬虫工程。我之前就用了scrapy搭建了一个抓取题库的项目,主要是网站上的选择题,存入数据库。scrapy是异步框架,但是没有实现多进程,需要自己分配爬取队列,来实现多进程的爬取。如果要进行分布式爬取,那建立一个爬取队列的数据库的很有必要的,保证每个框架间的队列是唯一的,不做重复爬取。爬虫框架使用起来很简单,教程很多,不展开了。 结尾上面写的这些内容几乎都有尝试过,也有部分很少使用,或者没有经历。但就我这样十分业余的水平来说,应当是可堪用了。]]></content>
<tags>
<tag>python</tag>
<tag>爬虫</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Flask学习笔记]]></title>
<url>%2Fflask-notes.html</url>
<content type="text"><![CDATA[Flask笔记整理,仅有几个点,更多内容访问官网。 指定静态文件夹和端口123from flask import Flaskapp = Flask(__name__,static_folder='static')app.run(host='0.0.0.0', port=8000) 文件夹路径是相对路径,'0.0.0.0'可以监听所有公开路径。 重定向12from flask import redirectredirect('/cookie') # 参数是路由 参数传递通过url传递参数12# http://www.example.com/test?key=valuev = request.args.get('key', '') 通过表单传递参数不同的前端方法不一样,但是按表单传递的后端处理一致。1234567891011121314151617181920<form id="form"> <span>日期:</span><input name="date" type="date" /> <input type="button" value="提交" onclick="insert()"><br/></form><script type="text/javascript"> function insert() { $.ajax({ type: "POST", url: "test" , data: $('#form').serialize(), success: function (values) {}, error : function() {} }); }</script>-----------------------------------<form method="post" action="/test"> <span>日期:</span><input name="date" type="date" /> <button type="submit">提交</button><br/></form> [email protected]('/test', methods=['POST', 'GET'])def get_date(): if request.method == 'POST': date = request.form.get('date') 通过json传递参数前端传递json方法如下12345<script type="text/javascript"> $.post('test', JSON.stringify({'key':'value'}),function(data){ r = JSON.parse(data); });</script> 1v = request.get_json(force=True) 结尾我对flask用的不多,掌握的很浅,但即使是这样也能搭建一个简单的小网站,flask作为一个轻量框架真的不错。]]></content>
<tags>
<tag>flask</tag>
</tags>
</entry>
<entry>
<title><![CDATA[转:全面驳斥郎咸平、石述思散布的转基因谣言与谎言]]></title>
<url>%2Fzhuan-fang-lang-with-transgene.html</url>
<content type="text"><![CDATA[作者:方舟子发表日期:2013.7.17 几年来郎咸平一直在散布关于转基因的谣言,妖魔化、阴谋化转基因食品。我在2010年曾经写过《郎咸平用谣言“谋杀”转基因》揭露他。在那篇文章的结尾,我下结论说: “有人说,郎咸平之所以妖魔化转基因,是由于科学素养不足,科学家的科普工作没有做好云云。但是一个诚实的人,即使没有科学素养,也不会使用强盗逻辑,更不会造谣。郎咸平用强盗逻辑和谣言对转基因的‘谋杀’,清楚地表明了,这不是科学素养的问题,而是学术道德的问题,他的学术声誉就此破产。” 他的学术声誉已破产,却不妨碍他继续在中国媒体上为推销其阴谋论而散布谣言与谎言。今年7月14日广东卫视《财经郎眼》节目播出“警惕!转基因!”一集,又集中散布了关于转基因食品的谣言与谎言,只不过这一次除了郎咸平,还来了个石述思,与主持人王牧笛组成所谓“三见客”(还不如说是“三贱客”)跟他一唱一和。 我们先来看看郎咸平在这个节目中的表演。郎咸平一开始就用大屏幕抛出了触目惊心的两项“研究”——转基因食品致癌。一项其实是去年的旧闻(这则旧闻昨天又被《每日经济新闻》的著名造谣记者金微拿出来当新闻炒了一下。该记者昨天还造谣“联合国粮农组织官员称转基因食品对人体不安全”,这笔账我另外再算),即所谓法国科学家发现转基因玉米会让老鼠长肿瘤。郎咸平没有告诉观众的是,这项研究的结果被世界各国以及我国香港的权威机构一致否定,包括法国国家食品安全局和法国高等生物技术委员会也都否定了该研究,认为其在科学上不能成立[1]。 郎咸平抛出的另一项“研究”算是比较新的,是根据不久前黑龙江大豆协会的说法画了张地图,声称我国消费转基因大豆油的区域是肿瘤发病集中区。大豆协会去发布肿瘤发病因素的研究结果,本来就是极其可笑的,更恶劣的是,这是该大豆协会出于不正当竞争的需要,捏造数据,故意撒谎,妖魔化转基因大豆,恐吓中国消费者。我们且看该协会副秘书长王小语是怎么说的: “我依据自身在粮食行业20年的工作经历,发现致癌原因可能与转基因大豆油消费有极大相关性。河南、河北、甘肃、青海、上海、江苏、广东、福建等地,基本是我国转基因大豆油的消费集中区域,这些区域同时也是我国肿瘤发病集中区。黑龙江、辽宁、浙江、山东、湖南、湖北、贵州等地基本不以消费转基因大豆油为主,不是肿瘤发病集中区域。” 我没有找到我国各地转基因大豆油消费状况的数据,无法知道王小语说的这些省份的转基因大豆油消费情况是否属实。但是我找到了这些省份的癌症(恶性肿瘤)发病率情况(据李媛秋硕士学位论文《中国癌症发病率预测统计方法研究》引用的数据 ,这是2008年的统计数据,我国最新的有关数据应是2009年的,但我没有找到2009年的系统资料,仅一年不会有什么差别),稍一对比,就可发现王小语在撒谎。比如被列为“基本不以消费转基因大豆油为主的”浙江乃是我国癌症的高发区,男性发病率322.00/10万,女性220.19/10万,湖北、辽宁乃至该协会所在的黑龙江的癌症发病率也不低,分别是:湖北男性发病率287.09/10万,女性205.50/10万;辽宁男性251.97/10万,女性180.38/10万;黑龙江男性242.47/10万,女性133.39/10万。相反地,被王小语列为“我国转基因大豆油的消费集中区域”的广东、青海的癌症发病率都低于上述几个省份,分别是:广东男性174.80/10万,女性114.10/10万;青海男性233.80/10万,女性144.08/10万。根据郎咸平、黑龙江大豆协会的逻辑,我们是不是可以说,吃转基因大豆油降低了癌症发病率? 如果说,以上只是郎咸平引用了捏造的研究,是别人撒谎而不是他撒谎,他只是不严谨的话,那么下面这些话,就是郎咸平本人的谎言,是有意造谣。 郎咸平造谣说:“因为转基因玉米能致癌,欧洲有6个国家禁止老百姓食用孟山都的转基因玉米,包括奥地利、法国、德国、匈牙利、卢森堡、希腊。” 实际上这6个国家并没有禁止老百姓食用转基因玉米,含转基因玉米成分的食品同样能在这些国家买到。这些国家只是以保护环境为由禁止种植或进口某些转基因品种的种子。这些禁令有的是十几年前就有的,跟去年的什么致癌研究毫无关系[2]。最近的是法国在2008年禁止种转基因玉米,该禁令在2011年被法国法庭和欧洲法庭推翻,在2012年法国农业部长再禁种植转基因玉米,又被欧洲食品安全局否决[3]。 郎咸平造谣说:“美国禁止几种转基因食品的食用,包括土豆、小麦、甜菜、甜椒、西红柿。” 事实上,美国种植的甜菜绝大部分是转基因的,占了95%[4],不供人食用难道是种着玩的?转基因土豆、小麦、甜椒是因为从没种过,转基因西红柿(Flavr Savr)在1994年上市后,因为种植成本太高,公司经营不善,1998年退市。到今年5月美国食品药品管理局(FDA)审核批准、确认安全的转基因作物品种共98种,包括:玉米、棉花、大豆、油菜、小麦、水稻、苜蓿、香瓜、匍匐剪股颖、亚麻、木瓜、李子、土豆、菊苣、南瓜、甜菜、西红柿[5]。 郎咸平造谣说:“你以为美国人吃转基因食品啊,转基因小麦根本不准上桌,食用的是非转基因玉米和大豆,除了零食之外,肉类、蛋类、乳制品全部是非转基因,……饲养牲畜比如说玉米是不是转基因的,美国现在搞得非常清楚,他说这个猪,这个牛,他吃的是非转基因的饲料,他会标得非常清楚的,为什么,他给老百姓一个知情权和选择权。” 说美国人不吃转基因食品,是一个被驳斥过无数次、老得不能再老的谎言。孟山都研发的转基因小麦在2001年获得了FDA批准,确认了安全,也就准许上桌,只不过由于经济的原因孟山都没有去申请商业化种植。肉类、蛋类、乳制品目前根本就没有成熟的转基因产品,大家当然都只能吃非转基因的(转基因三文鱼很快就要在美国获得安全证书上市了,到时候再看郎咸平怎么造谣)。FDA认定转基因食品与同类非转基因食品实质等同,不要求做特殊标识,在美国吃玉米、大豆,除非是那些专挑保证不含转基因成分的“有机食品”买的另类[6],否则根本就不知道自己吃的是转基因还是非转基因。去年11月7日,美国加州选民公投,否决了关于是否强制标识转基因食品的37号议案,今年5月25日美国参议院以71:27否决了强制给转基因食品标识的议案,也就是说,在美国给人吃的食品是否含转基因都不做标识,美国老百姓都没有这方面的知情权和选择权,难道给猪牛吃的饲料反而要标识,还要是非转基因的?郎咸平说的是他梦中的美国? 郎咸平造谣说:“证明转基因食品危害性的论文,许多登在权威学术期刊上,大量论文发表之后,欧洲老百姓觉醒,不吃转基因食品了。如果是伪造的研究,他们会不知道吗,研究多如牛毛,根本不可能都是假的。” 事实上,号称证明转基因食品危害的论文只有零星几篇,除了第一篇关于一种研发中的转基因大豆的是登在《柳叶刀》上的(主编后来解释说是有意要引起争论),其他都登在不入流的期刊上,而且全都在后来被否定,目前没有一篇关于转基因食品有害的论文是经得起推敲、被学术界普遍认可的。郎咸平眼中的牛,是不是就只有几根一拔就掉的毛? 我们再来看石述思是怎么造谣的。 石述思造谣说:“阿根廷种了转基因大豆,它会变异,要用新的农药,阿根廷不掌握,就要向孟山都买,被孟山都控制。” 转基因大豆目前有两种,抗虫的BT转基因大豆本来就是减少农药使用的,如果害虫出现了抗性,这种转基因大豆就不能种了,与要不要用新农药毫无关系。抗除草剂的转基因大豆抗的是草甘膦,这是一种用了很多年的除草剂,虽然是孟山都研发的,但是专利早已过时,中国大量生产草甘膦出口到阿根廷,阿根廷用的草甘膦主要是从中国进口的,孟山都根本没法控制。 石述思造谣说:“转基因大豆浸泡了不会发芽,这是绝育技术啊,人吃了也会绝育,无后啊,不孝有三无后为大嘛。” 转基因大豆只是转了一个抗虫或抗除草剂(抗农达)基因,并不会让大豆不育。转基因大豆是可以留种的,允不允许留种看当地的政策。根据联合国粮农组织的报告《2003-04粮食及农业状况》中文版第50页:“在美国,抗农达技术有专利保护,销售使用时与农民签署销售合同;而阿根廷则没有任何形式的知识产权保护。因此,农民可以不用从孟山都手中获得抗农达大豆,而且法律允许他们种自己留种的大豆。结果,阿根廷农民购买抗农达种子的价格溢价较低,约30%;而美国农民则平均多付出43%。”十几年前有人研发过用转基因技术让种子不育,以防止农民留种,但是该技术并没有被应用。即使种子是绝育的,跟人绝育又有什么关系?难道石述思吃了无籽西瓜、香蕉就不育了?吃了阉鸡、阉猪就成太监了? 石述思在节目中说:“转基因食品不知道谁审的,不公开。”后来在微博上解释说:“俺在节目中没有反对转基因,只是希望能吃得明明白白——现在对当大白鼠的感觉不爽,希望能吃得明白,吃得放心。” 石述思上节目大谈转基因,却不知道中国有一部《农业转基因生物安全管理条例》,规定了转基因作物由农业转基因生物安全委员会进行评价,这些都是公开的信息,包括该委员会的成员名单在农业部网站上也都是公开可查的,最新一届的名单见注[7]。 中国对含转基因成分的食品是要求做标识的,比如转基因大豆油都会标着“原料为转基因大豆”。石述思不去看,不去查,却在那里嚷嚷不知道、不公开、不明白,这不是很可笑吗?人家把知情权都交给你了,还在那里要知情权,这不是无理取闹吗?美国转基因食品都是谁审的,你知道吗?美国转基因食品还不做标识,你吃得更不明白,石述思最好都别去美国,去了美国一定要记得带上方便面,千万别吃美国食品,那很可能都含有转基因成分,你吃得不明不白,要三代绝育的哦。 不仅郎咸平、石述思在节目中大肆造谣,主持人王牧笛也在造谣。比如他说:“请不来方舟子,请了他也不敢来。”观众还以为他们请我去录这个节目而我不敢去。他们没有请过我,不存在请得来请不来的问题;即使我不去,也不会是因为不敢,会是因为别的原因,比如不认为那是个公正的辩论平台。我以前参加过深圳卫视、凤凰卫视关于转基因的辩论节目,何时请不来不敢来了?在保证人身安全的前提下,我随时随地欢迎郎咸平来跟我辩论转基因问题,当众揭穿这个学术骗子炮制的无数谎言、谣言。 1.见:http://www.afp.com/en/node/615056 ↩2.见:http://www.nature.com/nbt/journal/v29/n4/fig_tab/nbt.1840_T1.html ↩3.见:http://www.guardian.co.uk/environment/2012/may/22/french-ban-gm-maize-rejected ↩4.见:http://www.isaaa.org/resources/publications/briefs/43/executivesummary/default.asp ↩5.见:http://www.accessdata.fda.gov/scripts/fcn/fcnNavigation.cfm?rpt=bioListing ↩6.2011年有机食品仅占美国食品市场份额的4.2%,几乎可以忽略:http://www.foodnavigator-usa.com/Markets/US-organic-market-continues-to-outpace-conventional-food-sales-growth ↩7.见:http://www.moa.gov.cn/govpublic/KJJYS/201305/P020130514323834835075.doc (已失效:最新见:http://jiuban.moa.gov.cn/fwllm/hxgg/201606/P020160617356726885840.doc) ↩]]></content>
<tags>
<tag>转基因</tag>
<tag>方舟子</tag>
</tags>
</entry>
<entry>
<title><![CDATA[在vultr上搭建ss]]></title>
<url>%2Fvps-in-vultr.html</url>
<content type="text"><![CDATA[在国内上谷歌或者访问外网不太方便,看网上有很多人买了vps,搭建了自己的ss,博主也尝试了一下。整个过程并不复杂,网上教程也很多,我整理了一下。 选择vps服务商网上的vps很多,博主选择了vultr。如果你使用的是其他服务商,也没关系,大体上没多少差异。下面是博主的推荐链接,现在12月有活动,新用户赠送25美元。 优惠链接:https://www.vultr.com/?ref=7692960 注册与登录没有注册的小伙伴可以通过上面的优惠链接进行注册,也可以自己访问官网注册,不过没有优惠。目前优惠期只限12月份,过了优惠期,通过上面的链接也不能有优惠了。 注册完成,通过邮箱验证,登录就好。 充值进去后再左侧选择Billing,选择付款方式,支持信用卡(国外的)、Paypal、比特币、支付宝、微信支付、礼物码六种方式,选择自己合适的金额就行。 vultr计费方式vultr是按小时收费的,不同的服务器配置小时收费不同。 但是注意,如果你不想用了,将服务器停止了,vultr仍然收费。所以,如果你真的不想用了,就把服务器Destroy。 搭建ss选择线路Location地理位置Hostname官方测试服务器ipDownload Test File下载测试文件(Asia)Tokyo, Japan[日本 东京]hnd-jp-ping.vultr.com100Mb 1000MbSingapore[新加坡]sgp-ping.vultr.com100Mb 1000Mb(AU) Sydney, Australia[悉尼]syd-au-ping.vultr.com100Mb 1000Mb(EU) Frankfurt, DE[德国 法兰克福]fra-de-ping.vultr.com100Mb 1000Mb(EU) Amsterdam, NL[荷兰 阿姆斯特丹]ams-nl-ping.vultr.com100Mb 1000Mb(EU) London, UK[英国 伦敦]lon-gb-ping.vultr.com100Mb 1000Mb(EU) Paris, France[法国 巴黎]par-fr-ping.vultr.com100Mb 1000MbSeattle, Washington[美东 华盛顿州 西雅图]wa-us-ping.vultr.com100Mb 1000MbSilicon Valley, Ca[美西 加州 硅谷]sjo-ca-us-ping.vultr.com100Mb 1000MbLos Angeles, Ca[美西 加州 洛杉矶(推荐)]lax-ca-us-ping.vultr.com100Mb 1000MbChicago, Illinois[美东 芝加哥]il-us-ping.vultr.com100Mb 1000MbDallas, Texas[美中 德克萨斯州 达拉斯]tx-us-ping.vultr.com100Mb 1000MbNew York / New Jersey[美东 新泽西]nj-us-ping.vultr.com100Mb 1000MbAtlanta, Georgiaa[美东 乔治亚州 亚特兰大]ga-us-ping.vultr.com100Mb 1000MbMiami, Florida[美东 佛罗里达州 迈阿密]fl-us-ping.vultr.com100Mb 1000Mb 在命令行内ping相应的的ip,根据自己的网络情况,选择合适的线路。 选择配置在左侧选择servers,点击右侧的加号,根据ping的结果,选择合适的服务期,系统选择64位的CentOS 7,服务器的大小跟进自己需求选择,但是现在不要轻易选2.5美元一个月的,这种配置有ipv6的线路,比较麻烦,选择3.5或者5美元一个月一般都能满足了。最后创建后就行,创建服务器需要一段时间,等待服务器变成running状态就行。 远程连接主机远程连接的软件有不少,博主使用putty和xshell。连接上远程主机后,依次输入以下命令: 123wget --no-check-certificate https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks.shchmod +x shadowsocks.sh./shadowsocks.sh 2>&1 | tee shadowsocks.log 耐心等待出现输入密码的界面,输入密码,这个密码不是主机密码,是后面连接ss的密码,可以通过配置文件进行更改。 端口默认即可,加密方式选择aes-256-cfb。最后出现Congratulations即为成功,记录下Server IP、Server Port、Password ip被封 情况一:ip可以ping通,但是远程ssh连不上,这种情况有可能就是ip被封了。 情况二:之前都可以正常使用,今天突然就不连不上了,重启服务器也没有用,也可能是ip被封了。 上面两种情况都不能具体判断ip是否被封,ip被封的情况应该是国内不可以访问,而国外可以访问。 国内端口检测:http://tool.chinaz.com/port 国外端口检测:https://www.yougetsignal.com/tools/open-ports/ 如果国内端口检测关闭,国外端口检测open,那么ip就是被封了,只能换一个ip了。 删掉原来的服务器,重建服务器。如果发现ip和以前一样,就先保留当前服务器,再建一个服务器,获取不同的ip后,在删除原来的服务器。或者,你就等几天,再次重建服务器,ip也会不一样。 多账号配置多账号需要配置两个文件,一个是shadowsocks配置文件,一个是防火墙文件,可以用xftp这一类的软件,上传覆盖文件,或者在vim模式下编辑文件。 shadowsocks配置文件123456789101112131415161718// filepath: /etc/shadowsocks.json// [port]: 选择[1,65535]任一数字// example:// "port_password":{// "8989": "123456",// "9001": "123456"// },{ "server":"0.0.0.0", "local_address":"127.0.0.1", "local_port":1080, "port_password":{ "[port]": "[password]" }, "timeout":300, "method":"aes-256-cfb", "fast_open":false} 防火墙文件文件路径在/etc/firewalld/zones/public.xml,按照原来的方式,把端口号添加进去。123456789<?xml version="1.0" encoding="utf-8"?><zone> <short>Public</short> <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description> <service name="dhcpv6-client"/> <service name="ssh"/> <port protocol="tcp" port="8989"/> <port protocol="udp" port="8989"/></zone> 启用配置配置好文件后,需要在shell中启用配置,依次输出下面两条语句 12/etc/init.d/shadowsocks restartfirewall-cmd --reload 安装魔改版bbr123wget -N --no-check-certificate "https://raw.githubusercontent.com/chiakge/Linux-NetSpeed/master/tcp.sh"chmod +x tcp.sh./tcp.sh 运行上面的语句,重启服务器,后再次运行./tcp.sh,选择自己想要的版本即可 软件共享最后共享一下我自己用的软件 百度云链接 提取码:bn6b]]></content>
<tags>
<tag>vultr</tag>
<tag>shadowsocks</tag>
</tags>
</entry>
<entry>
<title><![CDATA[selenium的无界面模式]]></title>
<url>%2Fselenium-with-chrome-headless-on-python.html</url>
<content type="text"><![CDATA[前一段时间,尝试了一下selenium的无界面模式,结果没有成功,现在又重新来尝试解决这个问题。123456from selenium import webdriverchrome_options = webdriver.ChromeOptions()chrome_options.add_argument('--headless')chrome_options.add_argument('--disable-gpu')driver = webdriver.Chrome(chrome_options=chrome_options,executable_path='/driver/chromedriver') 这个浏览器的初始设置,没有问题,出问题的地方是,我在进行模拟登陆的时候,提示我登录框不可见。 123ElementNotVisibleException: Message: element not visible (Session info: headless chrome=70.0.3538.77) (Driver info: chromedriver=2.40.565498 (****************),platform=Windows NT 6.1.7601 SP1 x86_64) 后来想到了以前也遇到这样的问题,当时因为界面不够大的原因,调整浏览器大小就能解决。我在stackoverflow也看到了解决方法。 1chrome_options.add_argument('window-size=1200,1100') 添加后,完美解决!!! 参考链接:ElementNotVisibleException when use headless Chrome browser]]></content>
<tags>
<tag>selenium</tag>
<tag>headless</tag>
</tags>
</entry>
<entry>
<title><![CDATA[基于关键词搜索的微博爬虫]]></title>
<url>%2Fweibo-crawler-for-keyword-search-under-simulated-login.html</url>
<content type="text"><![CDATA[引言虽然微博爬虫已经有很成熟的方案和现成的代码,但是博主没有自己做过,还是想自己写一写。博主采用了两种方式,一个是采用selenium,使用浏览器抓取数据(已经忘了是使用哪位大佬的代码了),还有一个是采用超详细的Python实现新浪微博模拟登陆(小白都能懂)这篇文章介绍的模拟登录的方法,使用了CN-AlbertWu96这位大大的代码,采用BeautifulSoup去解析了html,没有使用代码中的lxml去解析页面,最终的结果使用DateFrame去保存为csv或者excel。我的博文就不详细讲方法了,各大前辈已经写得很清楚了,我就说说踩得坑吧。 第一种:使用selenium抓取使用selenium比较简单,主要就是找各种元素的位置,看代码大致就能明白。 第二种:模拟登陆抓网页主要的坑都在这个 获取不到正确cookies估计是我改动一些代码,导致我返回的页面和别人返回的有些差别,尽管我最后也成功了,但着实费了一番力气。 应该返回的代码:1234567891011121314<html><head><title>新浪通行证</title><meta http-equiv="Content-Type" content="text/html; charset=GBK" /><script charset="utf-8" src="http://i.sso.sina.com.cn/js/ssologin.js"></script></head><body>正在登录 ...<script>try{sinaSSOController.setCrossDomainUrlList({"retcode":0,"arrURL":["http:\/\/crosdom.weicaifu.com\/sso\/crosdom?action=login&savestate=1473605342","http:\/\/passport.97973.com\/sso\/crossdomain?action=login&savestate=1473605342","http:\/\/passport.weibo.cn\/sso\/crossdomain?action=login&savestate=1"]});}catch(e){}try{sinaSSOController.crossDomainAction('login',function(){location.replace('http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&ssosavestate=1473605342&ticket=ST-MzU2MjI3OTUwMQ==-1442069342-xd-E69DF7FE9517FBB10247C39F3D1C20F5&retcode=0');});}catch(e){}</script></body></html> 我返回的:1{"retcode":"0","uid":"5041606751","nick":"\\u537f\\u5357\\u738b","crossDomainUrlList":["https:\\/\\/passport.weibo.com\\/wbsso\\/login?ticket=ST-NTA0MTYwNjc1MQ%3D%3D-1533638234-yf-1AA4D6632C94B8C9CD341E77686D6C6E-1&ssosavestate=1533638234","https:\\/\\/passport.weibo.cn\\/sso\\/crossdomain?action=login&savestate=1"]} 最后提取了ticket的相关内容,重新拼接url,得到了cookies。 编码问题返回的html页面,里面所以的中文都变成\\u537f类似的符号,双斜杠应该变成单斜杠才能正常显示中文,最后通过下面代码才成功。1str.encode('utf-8').decode('unicode_escape') 但是在最后df.to_csv的时候仍然出错,显示如下。1UnicodeEncodeError: 'utf-8' codec can't encode characters in position 349-352: surrogates not allowed 网上查阅相似的结果说是路径文件,但实际上就是有些字符不能被编码成utf-8。最后又在上述代码上加了一些,过滤不能被utf-8的字符。我猜,可能是微博里的一些表情导致出错。1str.encode('utf-8').decode('unicode_escape').encode('utf-8','ignore').decode() 全局变量错误程序一开始很正常运行,结果突然告诉我出现全局变量错误,我一开始很不了解,在网上找了半天,结果实际上是我爬的太快,需要网页验证码,这也是自己没有在代码里考虑该问题的结果。错误信息如下:1UnboundLocalError: local variable 'outData' referenced before assignment 以上就是我踩过的所有坑,最后放上自己的代码链接。Github传送门 PS:参考文章和代码就不写了,太多了,记不住……]]></content>
<tags>
<tag>selenium</tag>
<tag>微博爬虫</tag>
<tag>模拟登录</tag>
<tag>关键词搜索</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Excel自定义函数实现一对多查找]]></title>
<url>%2Fexcel-custom-function-to-achieve-one-to-many-lookup.html</url>
<content type="text"><![CDATA[这个问题很多人问过我,excel自带的函数组合也能够做到,但实际上效果一般都不理想,而且再次使用也很麻烦,所以自己写了个自定义函数。这个自定义函数,是将所有符合条件的文本放在同一个单元格里,按给定的分隔符分隔。 12345678910111213141516171819202122232425262728Public Function Contxts(delimiter As String, ParamArray args() As Variant) Dim tmptext As Variant, i As Variant, Cellv As Variant Dim Cell As Range tmptext = "" For i = 0 To UBound(args) If Not IsMissing(args(i)) Then Select Case TypeName(args(i)) Case "Range" For Each Cell In args(i) If Cell <> "" Then tmptext = tmptext & Cell & delimiter End If Next Cell Case "Variant()" For Each Cellv In args(i) If Cellv <> "" Then tmptext = tmptext & Cellv & delimiter End If Next Cellv Case Else If args(i) <> "" Then tmptext = tmptext & args(i) & delimiter End If End Select End If Next i Contxts = Left(tmptext, Len(tmptext) - 1)End Function 函数实际上就是利用if得到数组,并把所有的数组用分隔符重新组合,下图就是使用函数的一个例子。 这样的结果里没有排除重复值,所以我又写了一个函数,以应对这种情况。123456789101112Public Function Duplicates(s As String, delimiter As String) Dim qt() As String, str As String Dim n As Long qt = Split(s, delimiter) str = qt(0) & "," For n = 1 To UBound(qt) If InStr(1, str, qt(n)) = 0 Then str = str & qt(n) & "," End If Next n Duplicates = Left(str, Len(str) - 1)End Function 这个函数对任何一个有固定分隔符的字符串,都能进行去重,并重新组合。]]></content>
<tags>
<tag>Excel</tag>
</tags>
</entry>
<entry>
<title><![CDATA[利用Vultr进行云挂卡]]></title>
<url>%2Fhow-to-get-steamcard-using-ASF-in-cloud-server.html</url>
<content type="text"><![CDATA[去年不想再折腾,索性就买了个云主机,搭建shadowsocks,上谷歌什么的,要方便不少,后来看到了steam云挂卡,就试着来了一波,毕竟自己还有好多游戏有卡呢。 准备 Vultr主机一台,系统为Centos 7.x,其他的系统没有尝试过。 Xshell 6,连接主机 Xftp 6,远程ftp工具 步骤安装 .NET Core连接主机,搭建过主机的同学应该都会连接主机,这里不多说了。 1234567yum update -yyum install -y libunwind lttng-ust libcurl openssl-libs libuuid krb5-libs libicu zlibsudo rpm --import https://packages.microsoft.com/keys/microsoft.ascsudo sh -c 'echo -e "[packages-microsoft-com-prod]\nname=packages-microsoft-com-prod \nbaseurl=https://packages.microsoft.com/yumrepos/microsoft-rhel7.3-prod\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/dotnetdev.repo'sudo yum install libunwind libicusudo yum install dotnet-sdk-2.1export PATH=$PATH:$HOME/dotnet 如果提示 Is this ok [y/d/N]: 回复 y 即可 部署ASF12wget https://github.com/JustArchi/ArchiSteamFarm/releases/download/3.1.2.0/ASF-generic.zipunzip -d asf ASF-generic.zip 下载ASF并解压,如果缺少wget和unzip,按如下代码安装。12yum install -y wgetyum install -y unzip 配置ASF编写json文件12345{ "SteamLogin": "name", "SteamPassword": "password", "Enabled": true} 其他更详细配置请自己寻找,保存为xxx.json。用Xshell 6把xxx.json上传到/root/asf/config。 启动ASF正常启动ASF,断开连接就会退出ASF,所以使用screen启动ASF。1234yum install -y screen #安装screenscreen -U -S asf #创建一个 编码模式为UTF-8 名称为 asf 的 screencd asfdotnet ArchiSteamFarm.dll 以下是几个常用的screen命令123screen -ls #查看所有已启动的窗口screen -r #恢复部署在后台的窗口kill [num] #关掉相应的窗口 快捷键 按 Ctrl+c 关闭窗口 按 Ctrl+a+d 会将窗口部署到后台 国内主机无法访问社区在host文件里加相应的ip和域名即可。 1vim /etc/hosts]]></content>
<tags>
<tag>Vultr</tag>
<tag>Steam</tag>
<tag>云挂卡</tag>
</tags>
</entry>
<entry>
<title><![CDATA[学员通过率的逻辑回归(Logistic Regression)模型]]></title>
<url>%2FLogistic-Regression-model-of-students-pass-rate.html</url>
<content type="text"><![CDATA[引言目前APP端已经有学员的知识点得分,知识点得分反映了学生对知识点的掌握情况,但据此来推测学生最终的通过率还略有不足,仍然有许多因素影响学员的成绩。举个例子,有的学员是属于大赛型的选手,平常表现一般,但考试的时候就比较好,相反的,有的学员平时不错,但到真正考试的时候就发挥的不太好。据此,我重新收集数据,建立学员通过率模型。 Logistic Regression学员通过与否是一个二分变量,故选择逻辑回归(Logistic Regression)模型。逻辑回归虽然名字里有回归,但不是一个回归模型,是一个分类模型。 逻辑回归(英语:Logistic regression 或logit regression),即逻辑模型(英语:Logit model,也译作“评定模型”、“分类评定模型”)是离散选择法模型之一,属于多重变量分析范畴,是社会学、生物统计学、临床、数量心理学、计量经济学、市场营销等统计实证分析的常用方法。(摘自维基百科) 逻辑回归实际上是用sigmoid函数将线性回归进行了归一化,把输出值压缩到0-1之间,这个值代表的是发生的概率。这里不过多说明模型的原理。 数据处理由于现有数据的限制,我选取了思想道德修养与法律基础这门科目的1804考期的数据,共18437个样本。 选取字段:学员ID,分数,直播出勤时长,重播出勤时长,出勤次数,观看重播次数,学生总时长,随堂考配置题数,随堂考完成题数,随堂考正确题数,作业配置题数,作业完成题数,作业正确题数,刷题完成题数,刷题正确题数,考试次数,通过次数,试卷总分,总得分。 其中,分数是指学员1804的考试成绩,百分制。删除其中的缺失值,共有9191个样本。 增加衍生变量 随堂考完成率 = 随堂考完成题数/随堂考配置题数 随堂考正确率 = 随堂考正确题数/随堂考完成题数 作业完成率 = 作业完成题数/作业配置题数 作业正确率 = 作业正确题数/作业完成题数 刷题正确率 = 刷题正确题数/刷题完成题数 增加分类变量 最终通过:将百分制的分数变量,按分数小于60为0,大于等于60为1,变换成二分变量 模考通过:按试卷总分和总得分转换成百分制的模考成绩,按相同逻辑,转换成二分变量。 处理时间单位 直播时长h=直播出勤时长/60 重播时长h=重播出勤时长/60 最后再次删除缺失值,共有8851个样本。 数据变量选取经过数据处理,变量增多,如何选取变量是个问题。筛选特征变量方法很多,我选择了递归特征消除(Recursive Feature Elimination, RFE)方法。 递归特征消除 (RFE)通过递归减少考察的特征集规模来选择特征。 首先,预测模型在原始特征上训练,每项特征指定一个权重。之后,那些拥有最小绝对值权重的特征被踢出特征集。如此往复递归,直至剩余的特征数量达到所需的特征数量。 利用调用sklearn中的RFE方法,并结合经验,最后共选取了8个变量。变量如下:直播时长h,重播时长h,随堂考完成率,随堂考正确率,作业完成率,作业正确率,刷题正确率,模考通过。 模型结果与评估选取70%作为训练集,30%作为测试集。利用GridSearchCV()选取模型合适的超参。 模型的变量系数如下: intercept 直播时长h 重播时长h 随堂考完成率 随堂考正确率 -5.68592042 0.01512291 0.01101413 -0.48080453 2.03324583 作业完成率 作业正确率 刷题正确率 模考通过 0.86103971 3.58450959 3.0435501 0.13064 模型在训练集上的评价指标如下: 准确率score 精确率precision 召回率recall 综合评价指标f1-score 0.8447 0.8538 0.9835 0.9140 以0.5为阀值,模型在测试集上的混淆矩阵如下: 真实情况 模型预测 0 1 0 41 393 1 33 2189 测试集上的评价指标为: precision recall f1-score support 0 0.55 0.09 0.16 434 1 0.85 0.99 0.91 2222 avg 0.80 0.84 0.79 2656 模型在测试集上的准确度为(41+2189)/2656=0.8396。模型的准确率还是非常高的(混淆矩阵对角线代表预测正确的数量),接近84%。可是单看混淆矩阵还不够,因为当数据不平衡时,计算的准确率也同样会高,并不代表模型就会好,所以我们进一步的借助于ROC曲线下的面积来衡量模型时候合理。 AUC值为0.76,说明模型预测效果不错。 后续改进虽然模型的准确性达到84%,但是仍然有不少改进空间。 数据完善:本次收集数据中,仍有不少缺失值和缺失字段,有不少字段没能收集到,例如学生知识点得分情况,性别,基础学历,是否拥有密训和模考五套卷等等。 模型改进:后续得到现实数据再次验证,进行模型参数的修改,或者寻找其他更为适合的模型进行替代。]]></content>
<tags>
<tag>Logistic</tag>
</tags>
</entry>
<entry>
<title><![CDATA[pandas中的时间处理]]></title>
<url>%2Fdatetime-process-in-pandas.html</url>
<content type="text"><![CDATA[昨天遇到一个问题,怎么把时间按条件分类。这个问题让我忙活了很久。数据是从csv中导入的,主要想根据不同时间范围划分几类。 一开始我将时间字段和'2018-03-15'相比大小,结果出了问题。csv中导入的时间字段也是字符串,这是字符串之间的比较,得不到想要的结果。写函数进行处理的时候,也搞混了很多问题。最后成功了,总结一下。 利用pandas导入csv,然后对时间列进行处理。首先要对字符串的时间转为datetime,然后对每个时间进行处理。利用循环,返回list;利用apply,针对每个元素处理。12345678910111213141516171819202122232425#!/usr/bin/env python3# -*- coding: utf-8 -*-import pandasfrom datetime import datetimedf=pandas.read_csv(open(file='test.csv'))# 把字符串时间变为datetimedf['time']=pandas.to_datetime(df['时间'])# 设定标准a=datetime(2018,3,15)# 循环函数def test(times): results=[] for x in times: if x<a: results.append(1) else: results.append(0) return results# 利用循环函数,分类时间df['categories1']=test(df['time'])# 利用apply处理df['categories2']=df['time'].apply(lambda x:test(x))print(df) pandas的每一列是Series,本质上就是一个list,apply针对每个元素处理,直接利用函数就要返回list。]]></content>
<tags>
<tag>pandas</tag>
<tag>datetime</tag>
</tags>
</entry>
<entry>
<title><![CDATA[python数据分析学习笔记(一)]]></title>
<url>%2Fpython-data-analysis-study-notes_1.html</url>
<content type="text"><![CDATA[最近在看《利用Python进行数据分析·第2版》这本书,根据自己阅读进度,每次阅读后进行总结。可能涉及很多方面,但这不是一篇系统的教程。有兴趣的同学,可以直接去阅读这本书,网上已经有很多电子版,或者阅读其他教程。 问号使用在Jupyter notebook中,?有多种用法。shift + tab也可以显示相关帮助。1234567891011121314151617181920212223242526272829303132333435363738#变量问号In []: b = [1, 2, 3]In []: b?Type: listString Form:[1, 2, 3]Length: 3Docstring:list() -> new empty listlist(iterable) -> new list initialized from iterable's items#函数问号In []: print?Docstring:print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)Prints the values to a stream, or to sys.stdout by default.Optional keyword arguments:file: a file-like object (stream); defaults to the current sys.stdout.sep: string inserted between values, default a space.end: string appended after the last value, default a newline.flush: whether to forcibly flush the stream.Type: builtin_function_or_method#函数源码In []: add_numbers??Signature: add_numbers(a, b)Source:def add_numbers(a, b): """ Add two numbers together Returns ------- the_sum : type of arguments """ return a + bFile: <ipython-input-9-6a548a216e27>Type: function 魔术命令以%开头的命令,可以通过%magic和%quickref查看所有命令,只在IPython中。下面列出常用的命令。 命令 说明 %hist 打印命令的输入(输出)历史 %run 运行代码 %time 语句单次执行时间 %timeit 语句多次运行平均时间 %xdel 删除变量并清空引用 格式输出1%[name][flags][width].[precision]typecode name为命名。 flags可以有-,' '或0。默认右对齐。-表示左对齐。' '为一个空格,表示在正数的左侧填充一个空格,从而与负数对齐。0表示使用0填充。 width表示显示宽度。 precision表示小数点后精度。 typecode为类型。 类型 说明 %s 字符串 (采用str()的显示) %r 字符串 (采用repr()的显示) %c 单个字符 %b 二进制整数 %d 十进制整数 %i 十进制整数 %o 八进制整数 %x 十六进制整数 %e 指数 (基底写为e) %E 指数 (基底写为E) %f or %F 浮点数 %g 指数(e)或浮点数 (根据显示长度) %G 指数(E)或浮点数 (根据显示长度) %% 字符% 序列函数zip函数zip可以将多个列表、元组或其它序列成对组合成一个元组列表,也可以解压一个序列:12345678910111213141516#组合In []: seq1 = ['foo', 'bar', 'baz']In []: seq2 = ['one', 'two', 'three']In []: list(zip(seq1, seq2))Out[]: [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]#解压In []: pitchers = [('Nolan', 'Ryan'), ('Roger', 'Clemens'), ('Schilling', 'Curt')]In []: first_names, last_names = zip(*pitchers)In []: first_namesOut[]: ('Nolan', 'Roger', 'Schilling')In []: last_namesOut[]: ('Ryan', 'Clemens', 'Curt') sort与sorted12345In []: [7, 1, 2, 6, 0, 3, 2].sort()Out[]: [0, 1, 2, 2, 3, 6, 7]In []: sorted([7, 1, 2, 6, 0, 3, 2])Out[]: [0, 1, 2, 2, 3, 6, 7]]]></content>
<tags>
<tag>python</tag>
<tag>数据分析</tag>
</tags>
</entry>
<entry>
<title><![CDATA[matplotlib图片输出简记]]></title>
<url>%2Fmatplotlib-picture-output-notes.html</url>
<content type="text"><![CDATA[最近在用matplotlib作图,应用到ppt上是时候,总是不方便,有各种问题,在网上搜寻了一番,为自己总结一番。 matplotlib输出图片输出格式支持输出的格式有eps, jpeg, jpg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff。 输出方式直接保存通过作图导入的import matplotlib.pyplot as plt模块,我们在使用plt.show()方法查看图片时,右下角有保存图标,直接点击保存图标,填写图片名称,选择图片格式和位置,保存即可。 代码保存123import matplotlib.pyplot as plt...plt.savefig('***.svg',format='svg') 通过plt.savefig()方法,选择格式,填写位置和名称,运行即可。 应用ppt图片放在ppt上展示的时候,不太清晰,就想选择矢量图。matplotlib输出的eps, svg, pdf等都有矢量效果,但能让ppt支持的只有一个eps,可惜eps格式ppt现在也有问题,导入进去不显示图片,我在网上找到了这篇文章I can no longer insert EPS graphics into PowerPoint来解决,但我试了没成功,有兴趣的可以点开,按照里面的方法试试。但是ppt对emf支持效果还不错,可以通过Inkscape[1]软件转换svg格式为emf格式。 Inkscape命令Inkscape可以支持命令行功能,所以可以直接在python中调用,也可以打开inkscape程序,手动把svg格式转为emf格式。下面简单的介绍几个用法和命令[2]。 inkscape [options] [filename ...] options:123456789101112-?, --help --usage-V, --version-f, --file=FILENAME-e, --export-png=FILENAME-P, --export-ps=FILENAME-E, --export-eps=FILENAME-d, --export-dpi=DPI-w, --export-width=WIDTH-h, --export-height=HEIGHT 示例12345678Microsoft Windows [版本 6.1.7601]版权所有 (c) 2009 Microsoft Corporation。保留所有权利。C:\Users\Administrator>cd desktopC:\Users\Administrator\Desktop>inkscape test.svg --export-emf=test.emfC:\Users\Administrator\Desktop> inkscape如果没有文件具体路径,默认在当前路径下寻找文件。需要注意的是,安装Inkscape不会自动加入到环境变量,所以要想在命令行中调用inkscape,必须自己手动将安装路径加入到环境变量,用管理员权限运行cmd 批处理文件运用批处理文件,一样可以实现。用记事本保存下面代码,后缀名为.bat,放在待转换文件的文件夹内,双击运行。123456@echo off for %%i in (*.svg) do ( echo %%i inkscape -f %%i -M %%~ni.emf ) @echo Finished python实现主要问题是如何通过python实现命令行输入。 os.system()123import osos.system('python -V') 利用os.system()方法,直接输入代码,中间会打开cmd界面,不能获得返回值。 subprocess.Popen()123import subprocesssubprocess.Popen('python -V', shell=True, stdout=subprocess.PIPE, universal_newlines=True) subprocess.Popen()参数比较多,常用的也就两三个。shell=True不会打开cmd界面,stdout是输出缓存,用read或者print方法读出。universal_newlines=True表明子进程的stdout和stderr被视为文本对象,并且不管是unix的行结束符'/n',还是老mac格式的行结束符'/r',还是windows格式的行结束符'/r/n'都将被视为 '/n' 。 subprocess其他方法subprocess.call()1subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False) subprocess.check_call()1subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False) subprocess.check_output()1subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False) 示例123456789101112131415161718192021222324252627282930#!/usr/bin/env python3# -*- coding: utf-8 -*-import matplotlib.pyplot as pltimport numpy as npimport mathfrom pylab import *import subprocessplt.style.use('ggplot')a=2b=0c=0.25D=1.7x=np.arange(-2,2,0.01)y=[c+(1-c)/(1+math.exp(-D*a*(n-b))) for n in x]plot([-2.5,-2],[0.25,0.25], color ='red',linestyle="--")xticks([-2,-1.5,-1,-0.5,0,0.5,1,1.5,2])yticks([0,0.25,0.5,0.75,1])plt.title('Item Characteristic Curve')plt.xlabel('$\\theta$')plt.ylabel('Probability')ylim(0,1.2)x1=np.arange(-2,2,0.01)plt.text(-2,1,r'$a=2$')plt.text(-2,0.95,r'$b=0$')plt.text(-2,0.9,r'$c=0.25$')plt.plot(x,y)plt.savefig('IRT.svg', format='svg')subprocess.Popen('inkscape IRT.svg --export-emf=IRT.emf', shell=True) #不需要获得返回值 因为不需要获得返回值,处理的只有一张图片,所以写的比较简单。经处理的图片,可以直接在ppt中使用,效果还行。 参考资料[1] : Word中插入Python“生成”的矢量图[2] : Python多进程(1)——subprocess与Popen()[3] : python中的subprocess.Popen()使用 1.官网下载界面 ↩2.详情参考官网 ↩]]></content>
<tags>
<tag>matplotlib</tag>
<tag>Inkscape</tag>
<tag>subprocess</tag>
</tags>
</entry>
<entry>
<title><![CDATA[展望教育上的人工智能:自适应学习]]></title>
<url>%2FLooking-at-Artificial-Intelligence-in-Education_Adaptive-Learning.html</url>
<content type="text"><![CDATA[引言人工智能是最近几年比较热门的话题,特别在AlphaGo战胜了几位世界级围棋选手,人工智能在有限规则游戏中的表现超过了大家的预料,人们对其关注大大增加。如果说人工智能在汽车领域上的应用是自动驾驶,那么在教育行业的应用就是自适应学习了。自适应学习,通俗的说,就是“因材施教”,所以这个系统的最终目的就是成为一个能够根据学生个性、能力、环境等各种因素进行教育的“虚拟老师”。当然,现有的自适应学习系统还远远达不到这个要求。目前,在这个行业比较出名的有: 自适应学习行业的开山鼻祖——08年成立的美国Knewton公司,完成了F轮融资,总额约2亿美金,在13年实现盈利 国内呼声比较高的乂学教育,目前知道的是获得了1.2亿(RMB)融资 其他还有新东方在线、优答、爱学堂、学吧课堂等 这个行业现在刚刚起步没多久,行业内鱼龙混杂,很多宣称自己应用自适应学习系统,实现了个性化教育,实际上都十分有限。同时,受到技术和理论上的限制,自适应学习并不完善,还有很长一段路要走。学习报告和试题推荐是自适应学习的一部分,我主要介绍现在主流的模型和算法,并谈谈我对搭建试题推荐系统的看法。 认知诊断模型首先面临的第一个问题就是,如何根据测试结果去评价学生的知识点掌握程度。在认知心理学中,认知诊断模型可以较好地从知识点层面对学生的认知状态进行建模,并在学生矫正计划、学习退学预警等应用中取得了良好的效果[1]。常见的认知诊断模型有项目反应理论(Item Response Theory, IRT)和DINA模型(Deterministic Inputs, Noisy “And” gate model)。 IRT$$P(\theta) =c+\frac{1-c}{1+e^{-Da(\theta-b)}}$$这是一个三参数的IRT模型,$D$ 是常数。根据模型所绘制出的曲线也叫做项目特征曲线(Item Characteristic Curve, ICC)。其意义在于描述出“成功解答某一特定考试项目的可能性”和“被测试者能力”(在函数中以 $\theta$ 表示)之间的关系。 在模型中,共有3个参数:$a$,$b$ 和 $c$。其中参数 $c$ 一般被称为“猜测参数”(guessing parameter)或者“伪猜测参数”(pseudo-guessing parameter)。在图像上,$c$ 所代表的是ICC的下限,其直观意义为:当一个被测试者的能力值非常低(比如接近负无穷),但是他仍然能够有可能做对这道题目的概率 $c$ 就是他猜测的能力,例如4选项的单选题,$c$ 为0.25。 $b$ 叫做项目难度参数,也称为项目难度(item difficulty)。$b$ 一般表示在ICC图像最陡的那一点所对应的 $\theta$ 值。改变 $b$ 会导致ICC的左右移动,但是不改变其形状。当 $b$ 值增加,会使ICC曲线向右移动($\theta$ 值高的的方向),这会引起在即使 $\theta$ 保持不变,但是答题正确率下降,亦即题目难度增加。反之当 $b$ 值减小,ICC曲线向左移动,题目难度降低。 $a$ 叫做区分度参数或项目区分度(item discrimination)。在数学上,$a(1-c)/4$ 的值是ICC曲线拐点处的斜率,即斜率的最大值。在这一点上,能力值微小的改变会造成最大的 $P$ 值(回答正确率)变动。所以 $a$ 体现的是该项目的最大区分度。 当 $a$ 比较大时,要么会做,要么肯定不会做,不存在中间地带[2]。 以IRT为基础,发展不少模型。比如,线性逻辑斯谛克特质模(1inear logistic trait model, LLTM)、多成分潜在特质模型(muhieomponent latent trait model, MLTM)及拓广多成分潜在特质模型(general muhicomponent latent trait model, GLTM)。以及随着后来在线学习的兴起的知识追踪(Knowledge Tracing)。 知识追踪(Knowledge Tracing)希望通过对学习者过往练习的结果分析其当前对一些概念的掌握程度。知识追踪任务可以形式化为一个有监督的序列学习问题:即给定学习者过去的练习记录 $X={x_{1},x_{2},\cdots,x_{t-1}}$,预测学习者对一个新的练习回答正确的概率,即$p(r_{t} =1|q_{t},\,X)$。典型的知识追踪方法有:Bayesian Knowledge Tracing(BKT) 和 Deep Knowledge Tracing(DKT)。 这些最初始的模型都没有考虑题目对应多个知识点的问题,实际考试中,往往一个试题对应多个知识点。后续很多再次开发的模型都融入了 $Q$ 矩阵。 $Q$ 矩阵 Questions 1 2 3 4 5 Concept1 1 0 0 1 1 Concept2 0 1 1 1 0 $Q$ 矩阵主要就是为了解决一个试题对应多个知识点的问题,它是一个题目与知识点的对应矩阵。上表是一个知识点与试题的简单对应关系,其中的值可以是离散的0和1,也可以是0~1之间的概率。搭建 $Q$ 矩阵是一个非常庞大的工程量,同时也是非常重要的一环,它关系到所用的模型效果。如果 $Q$ 矩阵没有没有准确搭建,后续预测和估计准确度会受很大影响。 DINADINA属于潜在分类模型,这类模型的目的在于按照被试的得分模式找到被试在潜在特质上质的差异,根据这样的差异对被试进行分类,属于这类模型的还有:Tatsuoka等提出的规则空间模型(rule space model, RSM)、新发展起来的融合模型(fusion model, FM)、NIDA模型(noisy inputs; deterministic “and” gate model)及贝叶斯网络(bayesian network, BN)等。DINA能够比较好应用 $Q$ 矩阵进行模型搭建和预测。 $$P(X_{ij}\;|\;\xi_{ij})=(1-s_{j})^{\xi_{ij}}g_{j}^{1-\xi_{ij}},\;\text{其中}\;\xi_{ij}=\prod^{K}_{k=1}\alpha^{q_{jk}}_{ik}$$ 表达式中,$P(X_{ij}\;|\;\xi_{ij})$ 表示被试者 $i$ 答对项目 $j$ 的概率; $\xi_{ij}$ 为被试者 $i$ 对作答项目 $j$ 所需知识的掌握程度,$\alpha_{ik}$ 是被试者 $i$ 掌握知识点的情况,$q_{jk}$ 是项目 $j$ 要求掌握的知识点情况,如果被试者 $i$ 掌握了答对项目 $j$ 所需要的所有知识,则 $\xi_{ij}=1$,反之,$\xi_{ij}=1$;$s_{j}$ 为失误参数,表示被试者掌握了答对项目 $j$ 所要求的属性模式,却错答了项目 $j$ 的概率; $g_{j}$ 为猜测参数,表示被试者未掌握答对项目 $j$ 所要求的属性模式,却答对了项目 $j$ 的概率。由此可见,该模型把学生分成两类:一类掌握了正确作答该项目所需的全部属性,另一类至少有一个必需的属性未掌握。因此,DINA模型是一个连续、非补偿模型,其核心思想在于其假定考生在解题时,如果缺少解答这一题所必需的任一个属性,该题的答对概率就低,即使答对了该项目也只是由于猜测[3]。比如,$5\times6+10$ 要求学生掌握乘法和加法,无论缺少哪一种,学生答对的概率都很低。DINA模型仅涉及“失误”和“猜测”两参数,实现了对认知诊断模型的简化,参数易于识别。后续模型发展对其多有借鉴。 知识图谱除了上述问题外,还要考虑一个更加深层的问题——知识点间的相互关联。根据知识点间的关系,构建知识图谱,这也是一个非常庞大的工程。 不同于章节数的包含结构,知识点间的关系远比章节数复杂的多。有的知识点是对过去知识点的丰富,有的知识点却要将之前建立的知识结构推翻重来,建立新的结构。这产生了很多问题。学习了新的知识点,有可能加强了之前的知识点,也有可能没有强化,反而使学生更加困惑,比如容易混淆的知识点。例如,英语中各种词语和语法的用法,初学者很容易糊涂。 同时构建这样一个知识图谱,也可以给后续学生的推荐更加有针对性。根据学生当前的表现情况,生成个人学习报告,联系知识图谱,为其规划下一步的学习路径,实现“因材施教”。 知识图谱也能有效的减少学生试题测试数。要对学生进行个人学习报告分析,首先要了解学生对知识点的掌握情况。以一门学科500个知识点来算,一个知识点1道题,我们至少需要500道题来检测学生,假设答每道题需要5秒钟,答完所有题目也需要41.67分钟,估计没有几个学生能做完所有题目。这显然不是很合理。而联系知识图谱,在每答一道题后,根据已答题目的知识点,推荐下一知识点,寻找覆盖主要知识点的最优路径。例如,数学四则运算,先测乘法,错了就测试加法,对了就测试除法。当然,我们在建模的时候可能不会如此的简单,通过与知识图谱的联系,在答题量和准确度之间进行权衡,最终目的就是想答最少的题目得到最精准的测量。 时间趋势时间也是要考虑的另一因素,前面所提到了BKT和DKT就有涉及到时间,前后知识点的关联也与时间有关。学生的学习行为是时间线上的行为。学生过去学习的知识点,可能会随着时间渐渐遗忘,也可能在这一段时间内不断学习巩固,加强了对其的理解。比如,一学生已经做了100道题,答对50道,能够直接判断学生的能力就为0.5吗?显然不合适。他可能以前错的比较多,50道题对了10道,后面错的比较少,50道题对了40道。这需要建立一个时间窗口,给予近期时间内事件更高的权重,比较久远时间的事件更少权重,模拟学生的“遗忘”行为。 在模拟遗忘的同时,要利用遗忘的规律,找到学生最佳的复习时间,在这个时间内,给学生推荐相关试题和知识点。SuperMemo是比较有名复习算法,早期是开源的,近十年的算法已经不公开了。现在市面不少的英语单词学习软件都加入这样的复习算法。 建议与展望建立试题推荐系统虽然比自适应系统要小一些,但仍然不是一个简单的工程,它取决于对系统精度的要求。要求越是精细,系统越是复杂。它也不仅仅是搭建一个数据模型,需要考虑方方面面。 数据采集:越是复杂精细,越是要求采集更加精细和多维的数据。 模型搭建:模型要尽可能容纳更多更精细的信息,很好的稳定性,庞大的计算量保证能够大量数据的访问和冲击,最重要的是能够对学生有很好的预测能力 知识点:知识点细分粒度,精细的模型,会要求知识点细分粒度达到纳米级;知识图谱的搭建,越是详细的图谱,越会适应精细的系统。 $Q$ 矩阵:$Q$ 矩阵搭建的准确度能够很大程度上影响模型准确度。 考虑的东西越多,搭建系统时花费的时间和资本就越多,但是提升的程度不一定和投入资本同比增加。所以需要在资金和时间的投入与模型最终效果间进行衡量,找到最优的平衡点。同时也要考虑到实际业务上的需要,如果业务上不需要对模型提出高精度的要求,那就只用搭建一个简单模型就可以了。如果花了大力气去研发了一套系统,而不能给实际业务创造收益,那即使这套模型有很好的精度和效果,也是白费力气,没有真正产生价值。模型的实际用途决定了投入资本的上限。不同模型各有特色和适应场景,现有的条件(时间、资金、数据等等)也会对模型选择有一定影响。 最后在展望一下自适应系统的未来。引言提到,自适应系统最终目的就是要成为“虚拟老师”。这需要在对目前的知识点进一步细分,知识图谱进行完善,但最终会反馈为对人工智能的进一步要求——人工智能理解自然语言。自然语言和机器语言有很大差异,自然语言语义丰富,不同场景下,同一句话就可能意思不同,这很难被机器所理解。目前有很多不同的研究方向,我就说一下知识图谱的研究方向吧。很多人都学习过英语,或者其他语言,学习越是深入就会发现,你不仅仅是在学习语言,更是在学习他们的文化、历史、习俗等等,你需要对他们日常知识有所了解。这也是为什么学习一门语言最好的方式就是去当地生活,因为这样的场景下,你会快速的融入进去。所以,要想理解一门语言,你不仅仅需要知道每个字词的意思,更要有对通识的了解。所以,让机器理解也是如此,构建一个通用型知识图谱对机器理解自然语言十分关键。要想构建这样一个知识图谱实在不是件容易的事,因为这种通识不仅非常庞大,还在不断变化。在通用型知识图谱上,要想机器去理解其他专门领域的语言,就要构建领域型知识图谱。越是繁复细腻的图谱,越是能够让机器更好的理解自然语言。 通用型知识图谱至今未建立,所以在此基础上建立领域型知识图谱,形成“虚拟老师”,还有很长一段路要走。 1.Leighton J P,Gierl M J. Cognitive Diagnostic Assessment for Education: Theory and Applications. New York, USA: Cambridge University Press, 2007 ↩2.https://en.wikipedia.org/wiki/Item_response_theory ↩3.Templin J, Henson R. Measurement of psychological disorders using cognitive diagnosis models[J]. Psychological Methods, 2006, (3). ↩]]></content>
<tags>
<tag>自适应</tag>
<tag>试题推荐</tag>
</tags>
</entry>
<entry>
<title><![CDATA[NexT实现LaTex公式]]></title>
<url>%2FLaTex-in-Next.html</url>
<content type="text"><![CDATA[历经磨难,修成正果!我的NexT主题版本为v5.1.4,按照NexT官方给的说法v5.0.1以上的版本,编辑主题配置文件,将mathjax下的enable设定为true即可。cdn用于指定MathJax的脚本地址,默认是MathJax官方提供的CDN地址。1234# MathJax Supportmathjax:enable: truecdn: //cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML 结果我改了之后不成功,看了众多教程尝试无果,重新换了一个cdn,终于成功运行。12345# MathJax Supportmathjax:enable: true- cdn: //cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML+ cdn: //cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML 以下测试: 行公式:$f(x1,x2,\ldots,xn) = x1^2 + x2^2 + \cdots + xn^2$块公式:$$\begin{eqnarray}\nabla\cdot\vec{E} &=& \frac{\rho}{\epsilon_0} \\nabla\cdot\vec{B} &=& 0 \\nabla\times\vec{E} &=& -\frac{\partial B}{\partial t} \\nabla\times\vec{B} &=& \mu_0\left(\vec{J}+\epsilon_0\frac{\partial E}{\partial t} \right)\end{eqnarray}$$]]></content>
<tags>
<tag>NexT</tag>
<tag>LaTex</tag>
</tags>
</entry>
<entry>
<title><![CDATA[第一篇博客]]></title>
<url>%2Fmy-first-blog.html</url>
<content type="text"><![CDATA[这是我的博客,将记录我日后的学习和生活。 搭建过程最近在学习Python,一开始打算自己写一个博客网站,后来遇到了不少困难,又觉得与自己最初目标不符,最后还是选择了一个早已成熟的框架来搭建自己的博客网站。我选择了Hexo,并使用了NexT主题,考虑到访问问题,我把项目代码托管在国内的GitHub即GitCafe,现以被Coding收购了。 遗留问题为了使自己的博客从地址看上去更像是个人的,我在腾讯云上申请了域名,绑定到coding的项目上,结果还是不太顺利。现在国家的域名要求备案,而备案又要求有云服务器,我只是搭建一个博客网站,为此在申请一台服务器实在是没有必要,所以可能以后这网址会失效。如果失效了,就只能用Coding的域名了,我想我不会为此再折腾一番了。 写给自己从去年6月底毕业,到现在已经大半年了,自己却也没什么提升,感到羞愧,又感到彷徨,还有一丝被社会远远抛在后面的恐慌。 逆水行舟,不进则退。 我只能不断去学习,不断去超越自己,或许我最终还是被社会拉下,我希望至少能对得起我曾经追赶的过去。]]></content>
<tags>
<tag>随笔</tag>
</tags>
</entry>
</search>