垃圾邮件分类 python_在python中创建SMS垃圾邮件分类器

垃圾邮件分类 python

介绍 (Introduction)

I have always been fascinated with Google’s gmail spam detection system, where it is able to seemingly effortlessly judge whether incoming emails are spam and therefore not worthy of our limited attention.

我一直对Google的gmail垃圾邮件检测系统着迷,该系统似乎可以毫不费力地判断收到的电子邮件是否是垃圾邮件,因此不值得我们的关注。

In this article, I seek to recreate such a spam detection system, but on sms messages. I will use a few different models and compare their performance.

在本文中,我试图重新创建这样的垃圾邮件检测系统,但要针对短信。 我将使用几种不同的模型并比较它们的性能。

The models are as below:

型号如下:

  1. Multinomial Naive Bayes Model (Count tokenizer)

    多项朴素贝叶斯模型(Count tokenizer)
  2. Multinomial Naive Bayes Model (tfidf tokenizer)

    多项式朴素贝叶斯模型(tfidf tokenizer)
  3. Support Vector Classifier Model

    支持向量分类器模型
  4. Logistic Regression Model with ngrams parameters

    具有ngrams参数的Logistic回归模型

Using a train-test split, the 4 models were put through the stages of X_train vectorization, model fitting on X_train and Y_train, make some predictions and generate the respective confusion matrices and area under the receiver operating characteristics curve for evaluation. (AUC-ROC)

使用火车测试拆分,对这四个模型进行了X_train向量化,对X_train和Y_train进行模型拟合的阶段,进行了一些预测,并在接收器工作特性曲线下生成了相应的混淆矩阵和面积以进行评估。 (AUC-ROC)

The resultant best performing model was the Logistic Regression Model, although it should be noted that all 4 models performed reasonably well at detecting spam messages (all AUC > 0.9).

最终表现最好的模型是Logistic回归模型 ,尽管应该注意的是,这4个模型在检测垃圾邮件方面都表现得相当不错(所有AUC> 0.9)。

Image for post
Photo by Hannes Johnson on Unsplash
Hannes Johnson在Unsplash上拍摄的照片

数据 (The Data)

The data was obtained from UCI’s Machine Learning Repository, alternatively I have also uploaded the used dataset onto my github repo. In total, the data set has 5571 rows, and 2 columns: spamorham indicating it’s spam status and the message’s text. I found it quite funny how the text is quite relatable.

数据是从UCI的机器学习存储库中获得的 ,或者我也将使用过的数据集上传到了我的github存储库中 。 数据集总共有5571行和2列:spamorham(表明其为垃圾邮件状态)和邮件的文本。 我发现文本之间的相关性很好笑。

Definitions: Spam refers to spam messages as they are commonly known, ham refers to non-spam messages.

定义:垃圾邮件是指众所周知的垃圾邮件,火腿是指非垃圾邮件。

Image for post
spam.head(10)
垃圾邮件标题(10)

数据预处理 (Data Preprocessing)

As the dataset is relatively simple, not much preprocessing was needed. Spam messages were marked with a 1, while ham was marked with a 0.

由于数据集相对简单,因此不需要太多预处理。 垃圾邮件标记为1,火腿标记为0。

Image for post
df.head(10)
df.head(10)

探索性数据分析 (Exploratory Data Analysis)

Now, let’s look at the dataset in detail. Taking an average of the ‘target’ column, we find that that 13.409% of the messages were marked as spam.

现在,让我们详细看一下数据集。 取“目标”列的平均值,我们发现有13.409%的邮件被标记为垃圾邮件。

Further, maybe the message length has some correlation with the target outcome? Splitting the spam and ham messages into their individual dataframes, we further add on the number of characters of a message as a third column ‘len’.

此外,消息长度可能与目标结果有一些相关性吗? 将垃圾邮件和火腿邮件拆分为各自的数据帧,然后在第三列“ len”中进一步添加邮件的字符数。

Image for post
The split data frames
分割数据帧
#creating two seperate dfs: 1 for spam and 1 for non spam messages only
df_s = df.loc[ df['target']==1]
df_ns = df.loc[ df['target']==0]df_s['len'] = [len(x) for x in df_s["text"]]
spamavg = df_s.len.mean()
print('df_s.head(5)')
print(df_s.head(5))print('\n\ndf_ns.head(5)')
df_ns['len'] = [len(x) for x in df_ns["text"]]
nonspamavg = df_ns.len.mean()
print(df_ns.head(5))

Further, taking the averages of messages lengths, we can find that spam and ham messages have average lengths of 139.12 and 71.55 characters respectively.

此外,以邮件长度的平均值为基础,我们可以发现垃圾邮件和火腿邮件的平均长度分别为139.12和71.55个字符。

资料建模 (Data Modelling)

Now it’s time for the interesting stuff.

现在该是有趣的东西了。

火车测试拆分 (Train-test split)

We begin with creating a train-test split using the default sklearn split of a 75% train-test split.

我们首先使用默认的sklearn拆分(75%的火车测试拆分)创建火车测试拆分。

计数向量化器 (Count Vectorizer)

A count vectorizer will convert a collection of text documents to a sparse matrix of token counts. This will be necessary for model fitting to be done.

计数矢量化器会将文本文档的集合转换为令牌计数的稀疏矩阵 。 这对于完成模型拟合是必要的。

We fit the CountVectorizer onto X_train, and then further transform it using the transform method.

我们将CountVectorizer拟合到X_train上,然后使用transform方法对其进行进一步转换。

#train test split
X_train, X_test, y_train, y_test = train_test_split(df['text'], df['target'], random_state=0)#fitting and transforming X_train using a Count Vectorizer with default parameters
vect = CountVectorizer().fit(X_train)
X_train_vectorized = vect.transform(X_train)#to look at the object types
print(vect)
print(X_train_vectorized)

MNNB模型拟合 (MNNB Model Fitting)

Let’s first try fitting a classic Multinomial Naive Bayes Classifier Model (MNNB), on X_train and Y_train.

首先让我们尝试经典 多项式朴素贝叶斯分类器模型 (MNNB),位于X_train和Y_train上。

A Naive Bayes model assumes that each of the features it uses are conditionally independent of one another given some class. In practice Naive Bayes models have performed surprisingly well, even on complex tasks where it is clear that the strong independence assumptions are false.

一个朴素的贝叶斯模型假设它使用的每个功能在给定类的条件下彼此独立 。 实际上,朴素贝叶斯模型的表现令人惊讶地出色,即使在很显然独立性强的假设是错误的复杂任务上也是如此。

MNNB模型评估 (MNNB Model Evaluation)

In evaluating the model’s performance, we can generate some predictions then look at the confusion matrix and AUC-ROC score to evaluate performance on the test dataset.

在评估模型的性能时,我们可以生成一些预测,然后查看混淆矩阵和AUC-ROC分数以评估测试数据集的性能。

The confusion matrix is generated as below:

混淆矩阵的生成如下:

Image for post
MNNB confusion matrix
MNNB混淆矩阵

The results seem promising, with a True Positive Rate (TPR) of 92.6% , specificity of 99.7% and a False Positive Rate (FPR) of 0.3%. These results show that the model performs quite well in predicting whether messages are spam, based solely on the text in the messages.

结果似乎很有希望, 真阳性率(TPR)为92.6%特异性为99.7%假阳性率(FPR)为0.3% 。 这些结果表明,仅基于邮件中的文本,该模型在预测邮件是否为垃圾邮件方面表现非常出色。

The Receiver Operator Characteristic (ROC) curve is an evaluation metric for binary classification problems. It is a probability curve that plots the TPR against FPR at various threshold values and essentially separates the ‘signal’ from the ‘noise’. The Area Under the Curve (AUC) is the measure of the ability of a classifier to distinguish between classes and is used as a summary of the ROC curve.

接收者操作员特征(ROC)曲线是二进制分类问题的评估指标。 这是一条概率曲线,在不同的阈值下绘制了TPRFPR的关系 ,并从本质上将“信号”与“噪声”分开曲线下面积(AUC)是分类器区分类的能力的度量,并用作ROC曲线的摘要。

Image for post
this article本文图片

The model produced an AUC score of 0.962, which is significantly better than if the model made random guesses of the outcome.

该模型产生的AUC得分为0.962,这比该模型对结果进行随机猜测的结果要好得多。

Although the Multinomial Naive Bayes Classifier seems to have worked quite well, I felt that maybe the result could possibly be improved further through a different model

尽管多项式朴素贝叶斯分类器的效果似乎很好,但我认为通过不同的模型可以进一步改善结果

#fitting a multinomial Naive Bayes Classifier Model with smoothing alpha=0.1
model = sklearn.naive_bayes.MultinomialNB(alpha=0.1)
model_fit = model.fit(X_train_vectorized, y_train)#making predictions & looking at AUC score
predictions = model.predict(vect.transform(X_test))
aucscore = roc_auc_score(y_test, predictions) #good!
print(aucscore)#confusion matrix
from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(y_test, predictions).ravel()
print(pd.DataFrame(confusion_matrix(y_test, predictions),columns=['Predicted Spam', "Predicted Ham"], index=['Actual Spam', 'Actual Ham']))
print(f'\nTrue Positives: {tp}')
print(f'False Positives: {fp}')
print(f'True Negatives: {tn}')
print(f'False Negatives: {fn}')print(f'True Positive Rate: { (tp / (tp + fn))}')
print(f'Specificity: { (tn / (tn + fp))}')
print(f'False Positive Rate: { (fp / (fp + tn))}')

MNNB(Tfid矢量化器)模型拟合 (MNNB(Tfid-vectorizer) Model Fitting)

I then attempt to use a tfidf vectorizer instead of a count-vectorizer to see if it improves the results.

然后,我尝试使用tfidf矢量化器而不是count-vectorizer来查看它是否可以改善结果。

The goal of using tfidf is to scale down the impact of tokens that occur very frequently in a given corpus and that are hence empirically less informative than features that occur in a small fraction of the training corpus.

使用tfidf的目的是减少在给定语料库中非常频繁出现的令牌的影响,因此,从经验上讲,这些令牌的信息少于在训练语料库的一小部分中出现的特征。

MNNB(Tfid矢量化器)模型评估 (MNNB(Tfid-vectorizer) Model Evaluation)

In evaluating the model’s performance we look at the AUC-ROC numbers and the confusionn matrix again. It generates an AUC score of 91.67%

在评估模型的性能时,我们再次查看AUC-ROC数和混淆矩阵。 它的AUC得分为91.67%

The results seem promising, with a True Positive Rate (TPR) of 83.3% , specificity of 100% and a False Positive Rate (FPR) of 0.0%%.

结果似乎很有希望, 真阳性率(TPR)为83.3%特异性为100%假阳性率(FPR)为0.0 %%

Image for post
tfid confusion matrix
tfid混淆矩阵

When comparing the two models based on AUC scores, it seems like the tfid vectorizer did not improve upon model accuracy, but even introduced more noise into the predictions! However, the tfid seems to have greatly improved the model’s ability to detect ham messages to the point of 100% accuracy.

当根据AUC分数比较两个模型时,tfid矢量化器似乎并没有提高模型的准确性,但甚至在预测中引入了更多噪声! 但是,tfid似乎已大大提高了该模型检测火腿消息的能力,准确性达到100%。

# fitting and transforming X_train using a tfid vectorizer, ignoring terms with a document frequency lower than 3.
vect = TfidfVectorizer(min_df=3).fit(X_train)
X_train_vectorized = vect.transform(X_train)# fitting training data to a multinomial NB model
model = sklearn.naive_bayes.MultinomialNB()
model_fit = model.fit(X_train_vectorized, y_train) #looking at model features
feature_names = np.array(vect.get_feature_names())
sorted_tfidf_index = X_train_vectorized.max(0).toarray()[0].argsort()
((pd.Series(feature_names[sorted_tfidf_index[:20]]),pd.Series(feature_names[sorted_tfidf_index[-21:-1]])))#making predictions
predictions = model_fit.predict(vect.transform(X_test))
aucscore = roc_auc_score(y_test, predictions)
print(aucscore)#confusion matrix
from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(y_test, predictions).ravel()
print(pd.DataFrame(confusion_matrix(y_test, predictions),columns=['Predicted Spam', "Predicted Ham"], index=['Actual Spam', 'Actual Ham']))
print(f'\nTrue Positives: {tp}')
print(f'False Positives: {fp}')
print(f'True Negatives: {tn}')
print(f'False Negatives: {fn}')print(f'True Positive Rate: { (tp / (tp + fn))}')
print(f'Specificity: { (tn / (tn + fp))}')
print(f'False Positive Rate: { (fp / (fp + tn))}')

Being a stubborn person, I still believe that better performance can be obtained, with a few tweaks.

作为一个固执的人,我仍然相信通过一些调整就能获得更好的性能。

SVC模型拟合 (SVC Model Fitting)

I now attempt to fit and transform the training data X_train using a Tfidf Vectorizer, while ignoring terms that have a document frequency strictly lower than 5. Further adding an additional feature, the length of document (number of characters), I then fit a Support Vector Classification (SVC) model with regularization C=10000.

我现在尝试使用Tfidf Vectorizer拟合和变换训练数据X_train,同时忽略文档频率严格低于5的术语。进一步添加附加功能,即文档长度(字符数),然后适合支持具有正则化C = 10000的向量分类(SVC)模型。

SVC模型评估 (SVC Model Evaluation)

This results in the following:

结果如下:

  • AUC score of 97.4%

    AUC分数为97.4%
  • TPR of 95.1%

    TPR为95.1%
  • Specificity of 99.7%

    特异性为99.7%
  • FPR of 0.3%

    FPR为0.3%
Image for post
SVC confusion matrix
SVC混淆矩阵
#defining an additional function
def add_feature(X, feature_to_add):"""Returns sparse feature matrix with added feature.feature_to_add can also be a list of features."""from scipy.sparse import csr_matrix, hstackreturn hstack([X, csr_matrix(feature_to_add).T], 'csr')#fit and transfor x_train and X_test
vectorizer = TfidfVectorizer(min_df=5)X_train_transformed = vectorizer.fit_transform(X_train)
X_train_transformed_with_length = add_feature(X_train_transformed, X_train.str.len())X_test_transformed = vectorizer.transform(X_test)
X_test_transformed_with_length = add_feature(X_test_transformed, X_test.str.len())# SVM creation and model fitting
clf = SVC(C=10000)
clf.fit(X_train_transformed_with_length, y_train)
y_predicted = clf.predict(X_test_transformed_with_length)#auc score
roc_auc_score(y_test, y_predicted)#confusion matrix
from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(y_test, y_predicted).ravel()
print(pd.DataFrame(confusion_matrix(y_test, y_predicted),columns=['Predicted Spam', "Predicted Ham"], index=['Actual Spam', 'Actual Ham']))print(f'\nTrue Positives: {tp}')
print(f'False Positives: {fp}')
print(f'True Negatives: {tn}')
print(f'False Negatives: {fn}')print(f'True Positive Rate: { (tp / (tp + fn))}')
print(f'Specificity: { (tn / (tn + fp))}')
print(f'False Positive Rate: { (fp / (fp + tn))}')

Logistic回归模型(n克)拟合 (Logistic Regression Model (n-grams) Fitting)

Using a logistic regression I further include the use of ngrams which allow the model to take into account groups of words, of max size 3, when considering whether a message is spam.

使用逻辑回归,我进一步包括使用ngram,当考虑消息是否为垃圾邮件时,该模型允许模型考虑最大大小为3的单词组。

Logistic回归模型(n-gram)评估 (Logistic Regression Model (n-grams) Evaluation)

This results in the following:

结果如下:

  • AUC score of 97.7%

    AUC分数为97.7%
  • TPR of 95.6%

    TPR为95.6%
  • Specificity of 99.7%

    特异性为99.7%
  • FPR of 0.3%

    FPR为0.3%
from sklearn.linear_model import LogisticRegressionvectorizer = TfidfVectorizer(min_df=5, ngram_range=[1,3])X_train_transformed = vectorizer.fit_transform(X_train)
X_train_transformed_with_length = add_feature(X_train_transformed, [X_train.str.len(),X_train.apply(lambda x: len(''.join([a for a in x if a.isdigit()])))])X_test_transformed = vectorizer.transform(X_test)
X_test_transformed_with_length = add_feature(X_test_transformed, [X_test.str.len(),X_test.apply(lambda x: len(''.join([a for a in x if a.isdigit()])))])clf = LogisticRegression(C=100)clf.fit(X_train_transformed_with_length, y_train)y_predicted = clf.predict(X_test_transformed_with_length)roc_auc_score(y_test, y_predicted)#confusion matrix
from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(y_test, y_predicted).ravel()
print(pd.DataFrame(confusion_matrix(y_test, y_predicted),columns=['Predicted Spam', "Predicted Ham"], index=['Actual Spam', 'Actual Ham']))
print(f'\nTrue Positives: {tp}')
print(f'False Positives: {fp}')
print(f'True Negatives: {tn}')
print(f'False Negatives: {fn}')print(f'True Positive Rate: { (tp / (tp + fn))}')
print(f'Specificity: { (tn / (tn + fp))}')
print(f'False Positive Rate: { (fp / (fp + tn))}')

型号比较 (Model Comparison)

After training and testing these 4 models, it’s time to compare them. I primarily look at comparing them based on AUC scores as the TPR and TNR rates are all somewhat similar.

在训练和测试了这四个模型之后,是时候进行比较了。 我主要考虑根据AUC分数比较它们,因为TPR和TNR率都有些相似。

The logistic regression had the highest AUC score, with the SVC model and MNNB 1 model being marginally behind. Relatively, the MNNB 2 model seemed to have underperformed the rest. However, I would still opine that all 4 models produce AUC scores which are much higher than 0.5, showing that all 4 perform good enough to beat a model that only randomly guesses the target.

Logistic回归的AUC得分最高,SVC模型和MNNB 1模型仅次于。 相对而言,MNNB 2模型的表现似乎不如其他模型。 但是,我仍然认为所有4个模型产生的AUC得分都远高于0.5,这表明所有4个模型的表现都足以击败仅随机猜测目标的模型。

Image for post
AUC score comparison between the 4 models
4个模型之间的AUC得分比较
import seaborn as sb
label = ['MNNB 1', 'MNNB 2', 'SVC', 'Logistic']
auclist = [0.9615532083312719, 0.9166666666666667, 0.97422863173865, 0.976679612130807]#generates an array of length label and use it on the X-axis
def plot_bar_x():# this is for plotting purposeindex = np.arange(len(label))clrs = ['grey' if (x < max(auclist)) else 'red' for x in auclist ]g=sb.barplot(x=index, y=auclist, palette=clrs) # color=clrs)   plt.xlabel('Model', fontsize=10)plt.ylabel('AUC score', fontsize=10)plt.xticks(index, label, fontsize=10, rotation=30)plt.title('AUC score for each fitted model')ax=gfor p in ax.patches:ax.annotate("%.2f" % p.get_height(), (p.get_x() + p.get_width() / 2., p.get_height()),ha='center', va='center', fontsize=11, color='gray', xytext=(0, 20),textcoords='offset points')g.set_ylim(0,1.25) #To make space for the annotationsplot_bar_x()

感谢您的阅读! (Thanks for the read!)

Do find the code here.

在这里找到代码 。

Do feel free to reach out to me on LinkedIn if you have questions or would like to discuss ideas on applying data science techniques in a post-Covid-19 world!

如果您有任何疑问或想讨论在Covid-19后世界中应用数据科学技术的想法,请随时通过LinkedIn与我联系。

这是给您的另一篇文章! (Here’s another article for you!)

翻译自: https://towardsdatascience.com/create-a-sms-spam-classifier-in-python-b4b015f7404b

垃圾邮件分类 python

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/392452.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单易用的MongoDB

从我第一次听到Nosql这个概念到如今已经走过4个年头了&#xff0c;但仍然没有具体的去做过相应的实践。最近获得一段学习休息时间&#xff0c;购买了Nosql技术实践一书&#xff0c;正在慢慢的学习。在主流观点中&#xff0c;Nosql大体分为4类&#xff0c;键值存储数据库&#x…

java断点续传插件_视频断点续传+java视频

之前仿造uploadify写了一个HTML5版的文件上传插件&#xff0c;没看过的朋友可以点此先看一下~得到了不少朋友的好评&#xff0c;我自己也用在了项目中&#xff0c;不论是用户头像上传&#xff0c;还是各种媒体文件的上传&#xff0c;以及各种个性的业务需求&#xff0c;都能得到…

tomcat中设置Java 客户端程序的http(https)访问代理

1、假定http/https代理服务器为 127.0.0.1 端口为8118 2、在tomcat/bin/catalina.sh脚本文件中设置JAVA_OPTS&#xff0c;如下图&#xff1a; 保存后重启tomcat就能生效。转载于:https://www.cnblogs.com/zhangmingcheng/p/11211776.html

MQTT服务器搭建--Mosquitto用户名密码配置

前言&#xff1a; 基于Mosquitto服务器已经搭建成功&#xff0c;大部分都是采用默认的是允许匿名用户登录模式&#xff0c;正式上线的系统需要进行用户认证。 1.用户参数说明 Mosquitto服务器的配置文件为/etc/mosquitto/mosquitto.conf&#xff0c;关于用户认证的方式和读取的…

压缩/批量压缩/合并js文件

写在前面 如果文件少的话&#xff0c;直接去网站转化一下就行。 http://tool.oschina.net/jscompress?type3 1.压缩单个js文件 cnpm install uglify-js -g 安装 1>压缩单个js文件打开cmd,目录引到当前文件夹&#xff0c;cduglifyjs inet.js -o inet-min.js 或者 uglifyjs i…

软件安装(JDK+MySQL+TOMCAT)

一&#xff0c;JDK安装 1&#xff0c;查看当前Linux系统是否已经安装了JDK 输入 rpm -qa | grep java 如果有&#xff1a; 卸载两个openJDK&#xff0c;输入rpm -e --nodeps 要卸载的软件 2&#xff0c;上传JDK到Linux 3&#xff0c;安装jdk运行需要的插件yum install gl…

TensorFlow 2.X中的动手NLP深度学习模型准备

简介&#xff1a;为什么我写这篇文章 (Intro: why I wrote this post) Many state-of-the-art results in NLP problems are achieved by using DL (deep learning), and probably you want to use deep learning style to solve NLP problems as well. While there are a lot …

静态代码块

静态代码块 静态代码块&#xff1a;定义在成员位置&#xff0c;使用static修饰的代码块{ }。位置&#xff1a;类中方法外。执行&#xff1a;随着类的加载而执行且执行一次&#xff0c;优先于main方法和构造方法的执行。格式&#xff1a;作用&#xff1a; 给类变量进行初始化赋值…

学java 的要点_零基础学Java,掌握Java的基础要点

对于程序员群体来说&#xff0c;了解一定的技巧会对学习专业技能更有帮助&#xff0c;也更有助于在自己的职业发展中处于有利地位&#xff0c;无限互联Java培训专家今天就为大家总结Java程序员入门时需要掌握的基础要点&#xff1a;掌握静态方法和属性静态方法和属性用于描述某…

实验人员考评指标_了解实验指标

实验人员考评指标In the first part of my series on experimental design Thinking About Experimental Design, we covered the foundations of an experiment: the goals, the conditions, and the metrics. In this post, we will move away from the initial experimental…

核心技术java基础_JAVA核心技术I---JAVA基础知识(集合set)

一&#xff1a;集合了解(一)确定性&#xff0c;互异性&#xff0c;无序性确定性&#xff1a;对任意对象都能判定其是否属于某一个集合互异性&#xff1a;集合内每个元素都是无差异的&#xff0c;注意是内容差异无序性&#xff1a;集合内的顺序无关(二)集合接口HashSet&#xff…

nba数据库统计_NBA板块的价值-从统计学上讲

nba数据库统计The idea is not to block every shot. The idea is to make your opponent believe that you might block every shot. — Bill Russel这个想法不是要阻止每一个镜头。 这个想法是让你的对手相信你可能会阻挡每一个投篮。 —比尔罗素 The block in basketball ha…

【炼数成金 NOSQL引航 三】 Redis使用场景与案例分析

验证redis的主从复制&#xff0c;将实验过程抓图 复制配置文件 更改slave的端口 和相关master配置 主从复制测试 研究在OAuth中的“一次数”nonce有什么用途&#xff1f;怎样使用&#xff1f;以此熟悉OAuth的全流程 nonce &#xff0c;一个随机的混淆字符串&#xff0c;仅仅被…

js建立excel表格_建立Excel足球联赛表格-传统vs动态数组方法

js建立excel表格介绍 (Introduction) I am going to show you the different ways you can build a football league table in Excel. Some of the methods are old school but others utilise Excel’s new capabilities.我将向您展示在Excel中建立足球联赛表格的不同方法。 其…

postman+newman生成html报告

作为测试菜鸟,在学习postmannewman的使用过程中真的是颇费周折......没办法技术太菜,只能多学习. postman的下载安装不多言说,下载地址:https://www.getpostman.com/downloads/ newman的安装过程: 1.首先需要安装node.js,可以去官网下载,地址:https://nodejs.org/en/#download …

java jdk1.9新特性_JDK1.9-新特性

1. Java平台级模块系统该特性使Java9最大的一个特性&#xff0c;Java提供该功能的主要的动机在于&#xff0c;减少内存的开销&#xff0c;JVM启动的时候&#xff0c;至少会有30~60MB的内存加载&#xff0c;主要原因是JVM需要加载rt.jar&#xff0c;不管其中的类是否被classload…

两个链接合并_如何找到两个链接列表的合并点

两个链接合并了解问题 (Understand the Problem) We are given two singly linked lists and we have to find the point at which they merge.我们给了两个单链表&#xff0c;我们必须找到它们合并的点。 [SLL 1] 1--->3--->5 \ …

安装veket到移动硬盘NTFS分区

如果你已经看过《手动安装veket到硬盘》和《简单的将veket安装到U盘的方法》两篇文章并且安装成功的话&#xff0c;说明不适用本文的安装环境&#xff0c;就不用往下看了。 《手动安装veket到硬盘》一文采用grub4dos来引导硬盘上的veket&#xff0c;主要是用来在本机已安装Wind…

简书使用小技巧

1、不同字体  在 设置->基础设置->富文本 模式下可以实现 2、添加图片&#xff0c;让文章更生动 3、添加代码框 &#xff01;注意&#xff1a;设置为Markdown模式后&#xff0c;只对新创建的文章起作用。转载于:https://www.cnblogs.com/HMJ-29/p/7049540.html

杭电2064

此题是一道简单的递归 此题是一道递归运算题&#xff0c;这题又是一道汉诺塔问题&#xff01;&#xff01;&#xff01;只要了解其规律&#xff0c;呵呵&#xff0c;你就可以很快AC了&#xff01;&#xff01; 这是一般的汉诺塔问题的解题方法照片&#xff01;&#xff01;&…