<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/understanding-linear-svm-with-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://datascienceplus.com/understanding-linear-svm-with-r/"> DataScience+</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Linear Support Vector Machine or linear-SVM(as it is often abbreviated), is a supervised classifier, generally used in bi-classification problem, that is the problem setting, where there are two classes. Of course it can be extended to multi-class problem. In this work, we will take a mathematical understanding of linear SVM along with R code to understand the critical components of SVM. Taking the liberty to assume that some readers are new to machine learning, let us first find out what the supervised classifier is supposed to do. The term <em> supervised </em> comes from the concept of <em> supervised learning</em>. In case of supervised learning, you provide some examples along with their labels to your classifier and the classifier then tries to learn important features from the provided examples. For example, consider the following data set. You, will provide a part of this data to your linear SVM and tune the parameters such that your SVM can can act as a discriminatory function separating the ham messages from the spam messages. So, let us add the following R-code to our task. </p>
<pre>
sms_data&lt;-read.csv(&quot;sms_spam.csv&quot;,stringsAsFactors = FALSE)
head(sms_data)
<em> type
1 ham
2 ham
3 spam
4 ham
5 ham
6 spam
text
1 Go until jurong point, crazy.. Available only in bugis n great world la e buffet... Cine there got amore wat...
2 Ok lar... Joking wif u oni...
3 Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&amp;C's apply 08452810075over18's
4 U dun say so early hor... U c already then say...
5 Nah I don't think he goes to usf, he lives around here though
6 FreeMsg Hey there darling it's been 3 week's now and no word back! I'd like some fun you up for it still? Tb ok! XxX std chgs to send, Â£1.50 to rcv</em></pre>
<h2>What Parameters should be tuned</h2>
<p>Linear SVM tries to find a separating hyper-plane between two classes with maximum gap in-between. A hyper-plane in \(d\)- dimension is a set of points \(x \in \mathbb R^{d}\) satisfying the equation<br>
$$w^{T}x+b=0$$<br>
Let us denote \(h(x)=w^{T}(x)+b\)<br>
Here \(w \) is a \(d\)-dimensional weight vector while \(b\) is a scalar denoting the bias. Both \(w\) and \(b\) are unknown to you. You will try to find and tune both \(w\) and \(b\) such that \(h(x)\) can separate the spams from hams as accurately as possible. I am drawing an arbitrary line to demonstrate a separating hyper-plane using the following code. </p>
<pre>
plot(c(-1,10), c(-1,10), type = &quot;n&quot;, xlab = &quot;x&quot;, ylab = &quot;y&quot;, asp = 1)
abline(a =12 , b = -5, col=3)
text(1,5, &quot;h(x)=0&quot;, col = 2, adj = c(-.1, -.1))
text(2,3, &quot;h(x)>0,Ham&quot;, col = 2, adj = c(-.1, -.1))
text(0,3, &quot;h(x)&lt;0,Spam&quot;, col = 2, adj = c(-.1, -.1))</pre>
<p>This is plot we get:<br>
<a title="" data-rel="lightbox-0" target="_blank" rel="nofollow" href="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2017/03/hyperplane.png?ssl=1"><img sizes="(max-width: 900px) 100vw, 900px" alt="" class="wp-image-5990" src="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2017/03/hyperplane.png?w=450&ssl=1" data-recalc-dims="1"></a></p>
<p>Oh, btw, did you notice that Linear SVM has decision rules. Let \(y\) be an indicator variable which takes the value -1 if the message is spam and 1 if it is a ham. Then, the decision rules are<br>
$$y=-1~iff~h(x)~is~less~than~0$$<br>
$$y=1~iff~h(x)~is~greater~than~0$$<br>
Notice that for any point \(x\) in your data set, \(h(x)\neq 0\) as we want the function \(w^{T}x+b\) to clearly distinguish between spam and ham. This brings us to a important condition.</p>
<h3>Important Condition</h3>
<p>Linear SVM assumes that the two classes are linearly separable that is a hyper-plane can separate out the two classes and the data points from the two classes do not get mixed up. Of course this is not an ideal assumption and how we will discuss it later how linear SVM works out the case of non-linear separability. But for a reader with some experience here I pose a question which is like this Linear SVM creates a discriminant function but so does LDA. Yet, both are different classifiers. Why ? (Hint: LDA is based on Bayes Theorem while Linear SVM is based on the concept of margin. In case of LDA, one has to make an assumption on the distribution of the data per class. For a newbie, please ignore the question. We will discuss this point in details in some other post.)</p>
<h3>Properties of \(w\)</h3>
<p>Consider two points \(a_{1}\) and \(a_{2}\) lying on the hyper-plane defined by \(w^{T}x+b\). Thus, \(h(a_{1})=w^{T}a_{1}+b=0\) and \(h(a_{2})=w^{T}a_{2}+b=0\). Therefore,<br>
$$w^{T}(a_{1}-a_{2})=0$$.<br>
Notice that the vector \(a_{1}-a_{2}\) is lying on the separating hyper-plane defined by \(w^{T}x+b\). Thus, \(w\) is orthogonal to the hyper-plane. </p>
<p>Here it is the plot:<br>
<a title="" data-rel="lightbox-1" target="_blank" rel="nofollow" href="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2017/03/w_proj.png?ssl=1"><img sizes="(max-width: 590px) 100vw, 590px" alt="" class="wp-image-5995" src="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2017/03/w_proj.png?w=450&ssl=1" data-recalc-dims="1"></a></p>
<h3>The Role of \(w\)</h3>
<p>Consider a point \(x_{i}\) and let \(x_{p}\) be the orthogonal projection of \(x_{i}\) onto the hyper-plane. Assume $h(x_{i})>0$ for \(x\).<br>
\(\frac{w}{\vert\vert w\vert\vert}\) is a unit vector in the direction of \(w\). </p>
<p>Here it is the plot:<br>
<a title="" data-rel="lightbox-2" target="_blank" rel="nofollow" href="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2017/03/x_proj_hyperplane.png?ssl=1"><img sizes="(max-width: 784px) 100vw, 784px" alt="" class="wp-image-5996" src="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2017/03/x_proj_hyperplane.png?w=450&ssl=1" data-recalc-dims="1"></a> </p>
<p>Let \(r\) be the distance between \(x_{i}\) and \(x_{p}\). Since \(x_{i}\) is projected on the hyper-plane, there is some loss of information which is calculated as<br>
$$(r=x_{i}-x_{p})$$.</p>
<p>Notice that \(r\) is parallel to the unit vector \(\frac{w}{\vert\vert w\vert\vert}\) and therefore \(r\) can be written as some multiple of \(\frac{w}{\vert\vert w\vert\vert}\). Thus, \(r=c\times \frac{w}{\vert\vert w\vert\vert}\), for some scalar value \(c\). It can be shown that<br>
$$c=\frac{h(x_{i})}{\vert\vert w\vert\vert}$$</p>
<p>Actually, \(c\times \frac{w}{\vert\vert w\vert\vert}\) represents the orthogonal distance of the point \(x_{i}\) from the hyper-plane. Distance has to be positive. \(\frac{w}{\vert\vert w\vert\vert}\) cannot be negative. However, \(c=\frac{h(x)}{\vert\vert w\vert\vert}\). Though, before starting the equations we assumed that \(h(x_{i})\) is positive, but that is not a general case. In general \(c\) can be negative also. Therefore we multiply \(y\) with \(c\). Remember your \(y\) from the decision rules. That is<br>
$$c=y\times \frac{h(x_{i})}{\vert\vert w\vert\vert}$$</p>
<h3>The Concept of Margin </h3>
<p>Linear SVM is based on the concept of margin which is defined as the smallest value of \(c\) for all the \(n\) points in your training data set. That is<br>
$$\delta^{\star}=min\{c~\forall~points~in~the~training~data~set\}$$. All points \(x^{\star}\) which are lying at an orthogonal distance of \(\delta^{\star}\) from the hyper-plane \(w^{T}x+b=0\) are called support vectors.</p>
<h3> Scaling Down the Margin </h3>
<p>Let \(\delta^{\star}=\frac{y^{\star}\times h(x^{\star})}{\vert\vert w\vert\vert}\), where \(x^{\star}\) is a support vector. We want \(\delta^{\star} = \frac{1}{\vert\vert w\vert\vert}\). Clearly, we want to multiply some value \(s\) such that \(s\times y^{\star}\times h(x^{\star})=1\). Therefore, \(s=\frac{1}{y^{\star}\times h(x^{\star})}\). </p>
<h3> Objective Criteria for Linear SVM</h3>
<p>After scaling down, we have the following constraint for SVM:<br>
$$y\times (w^{T}x+b)\geq \frac{1}{\vert\vert w\vert\vert}$$.<br>
Now consider two support vectors, one denoted by \(a_{1}\) on the positive side, while the other \(a_{2}\) on the negative side of the hyper-plane. For the time being let us not use \(y\). Then, we have \(w^{T}a_{1}+b= \frac{1}{\vert\vert w\vert\vert}\) and \(w^{T}a_{2}+b= \frac{-1}{\vert\vert w\vert\vert}\).Thus, \(w^{T}(a_{1}-a_{2})=\frac{2}{\vert\vert w\vert\vert}\).\(w^{T}(a_{1}-a_{2})\) depicts the separation/gap between the support vectors on the either side. We want to maximize this gap \(\frac{2}{\vert\vert w\vert\vert}\). For the purpose, we need to minimize \(\vert\vert w\vert\vert\). Instead,we can minimize \(\frac{\vert\vert w\vert\vert^{2}}{2}\). Formally, we want to solve<br>
$$Minimize_{w,b}\frac{\vert\vert w\vert\vert^{2}}{2}$$<br>
subject to the constraint<br>
$$y_{i}(w^{T}x_{i}+b)\geq \frac{1}{\vert \vert w\vert\vert}~\forall ~x_{i}~in ~Training~Data~set$$.</p>
<p>For linearly inseparable case, we introduce some penalty \(0\leq \xi_{i} \leq 1\) in the objective function and our constraint.<br>
$$Minimize_{w,b}(\frac{\vert\vert w\vert\vert^{2}}{2}+ C\sum_{i=1}^{n}\xi_{i})$$<br>
subject to the constraints<br>
$$(1)~y_{i}(w^{T}x_{i}+b)\geq 1-\xi_{i}~\forall ~x_{i}~in ~Training~Data~set~of~size~n$$ and<br>
$$(2)~\xi_{i}\geq 0~\forall ~n~points~in~the~Training~Data~set$$ </p>
<p>\(C\) is a user defined parameter. </p>
<p> In case you wish to see how \(\xi_{i}\) is used as penalty, please consider the the three figures below. You can also choose to skip them if the above details are okay for you.<br>
<a title="" data-rel="lightbox-3" target="_blank" rel="nofollow" href="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2017/03/Case1.jpg?ssl=1"><img sizes="(max-width: 1024px) 100vw, 1024px" alt="" class="wp-image-5998" src="https://i2.wp.com/datascienceplus.com/wp-content/uploads/2017/03/Case1-1024x420.jpg?w=450&ssl=1" data-recalc-dims="1"></a><a title="" data-rel="lightbox-4" target="_blank" rel="nofollow" href="https://i2.wp.com/datascienceplus.com/wp-content/uploads/2017/03/Case2.jpg?ssl=1"><img sizes="(max-width: 1024px) 100vw, 1024px" alt="" class="wp-image-5999" src="https://i2.wp.com/datascienceplus.com/wp-content/uploads/2017/03/Case2-1024x330.jpg?w=450&ssl=1" data-recalc-dims="1"></a><a title="" data-rel="lightbox-5" target="_blank" rel="nofollow" href="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2017/03/Case31.jpg?ssl=1"><img sizes="(max-width: 1024px) 100vw, 1024px" alt="" class="wp-image-6000" src="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2017/03/Case31-1024x453.jpg?w=450&ssl=1" data-recalc-dims="1"></a> </p>
<h3>Try the Code with R</h3>
<p>Let us now start our coding. The needed code is here. </p>
<pre>
library(tm)
setwd(path to the directory)
print(getwd())
sms_data&lt;-read.csv(&quot;sms_spam.csv&quot;,stringsAsFactors = FALSE)

print(head(sms_data))
sms_data$type&lt;-factor(sms_data$type)


simply_text&lt;-Corpus(VectorSource(sms_data$text))

cleaned_corpus&lt;-tm_map(simply_text, tolower)
cleaned_corpus&lt;-tm_map(cleaned_corpus,removeNumbers)
cleaned_corpus&lt;-tm_map(cleaned_corpus,removeWords,stopwords())
#cleaned_corpus&lt;-tm_map(cleaned_corpus,removePunctuation)
#cleaned_corpus&lt;-tm_map(cleaned_corpus,stripWhitespace)

sms_dtm&lt;-DocumentTermMatrix(cleaned_corpus)
sms_train&lt;-sms_dtm[1:4000]
sms_test&lt;-sms_dtm[4001:5574]
#sms_train&lt;-cleaned_corpus[1:4000]
#sms_test&lt;-cleaned_corpus[4001:5574]

freq_term=(findFreqTerms(sms_dtm,lowfreq=2))
#sms_freq_train&lt;-DocumentTermMatrix(sms_train,  list(dictionary=freq_term))
#sms_freq_test&lt;-DocumentTermMatrix(sms_test,list(dictionary=freq_term))

y&lt;-sms_data$type
y_train&lt;-y[1:4000]
y_test&lt;-y[4001:5574]
library(e1071)
tuned_svm&lt;-tune(svm, train.x=sms_freq_train, train.y = y_train,kernel=&quot;linear&quot;, range=list(cost=10^(-2:2), gamma=c(0.1, 0.25,0.5,0.75,1,2)) )
print(tuned_svm)
adtm.m&lt;-as.matrix(sms_freq_train)
adtm.df&lt;-as.data.frame(adtm.m)
svm_good_model&lt;-svm(y_train~., data=adtm.df, kernel=&quot;linear&quot;,cost=tuned_svm$best.parameters$cost, gamma=tuned_svm$best.parameters$gamma)

adtm.m_test&lt;-as.matrix(sms_freq_test)
adtm.df_test=as.data.frame(adtm.m_test)
y_pred&lt;-predict(svm_good_model,adtm.df_test)
table(y_test,y_pred)

library(gmodels)
CrossTable(y_pred,y_test,prop.chisq = FALSE)
<em>
type
1 ham
2 ham
3 spam
4 ham
5 ham
6 spam
text
1 Go until jurong point, crazy.. Available only in bugis n great world la e buffet... Cine there got amore wat...
2 Ok lar... Joking wif u oni...
3 Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&amp;C's apply 08452810075over18's
4 U dun say so early hor... U c already then say...
5 Nah I don't think he goes to usf, he lives around here though
6 FreeMsg Hey there darling it's been 3 week's now and no word back! I'd like some fun you up for it still? Tb ok! XxX std chgs to send, Â£1.50 to rcv
Parameter tuning of ‘svm’:
- sampling method: 10-fold cross validation - best parameters:
cost gamma
1 0.1
- best performance: 0.01825 Cell Contents
|-------------------------|
| N |
| N / Row Total |
| N / Col Total |
| N / Table Total |
|-------------------------|
Total Observations in Table: 1574 | y_test y_pred | ham | spam | Row Total | -------------|-----------|-----------|-----------|
ham | 1295 | 191 | 1486 | | 0.871 | 0.129 | 0.944 | | 0.952 | 0.897 | | | 0.823 | 0.121 | | -------------|-----------|-----------|-----------|
spam | 66 | 22 | 88 | | 0.750 | 0.250 | 0.056 | | 0.048 | 0.103 | | | 0.042 | 0.014 | | -------------|-----------|-----------|-----------|
Column Total | 1361 | 213 | 1574 | | 0.865 | 0.135 | | -------------|-----------|-----------|-----------|
</em>
</pre>
<p>In the above example we are not using the cleaned corpus. We see that the accuracy/precision of our classifier for ham is 0.871 and recall is 0.95. However for Spam messages, the precision is 0.250, while recall is just 0.103. We found that the usage of cleaned corpus degrades the performance for the SVM more. </p>
<ul></ul>
<p><strong>
<p>Related Post</p>
<p>
<ol>
<li><a title="Permanent Link toHow to add a background image to ggplot2 graphs" target="_blank" rel="nofollow" href="https://datascienceplus.com/how-to-add-a-background-image-to-ggplot2-graphs/">How to add a background image to ggplot2 graphs</a></li>
<li><a title="Permanent Link toStreamline your analyses linking R to SAS: the workfloweR experiment" target="_blank" rel="nofollow" href="https://datascienceplus.com/streamline-your-analyses-linking-r-to-sas/">Streamline your analyses linking R to SAS: the workfloweR experiment</a></li>
<li><a title="Permanent Link toR Programming – Pitfalls to avoid (Part 1)" target="_blank" rel="nofollow" href="https://datascienceplus.com/r-programming-pitfalls-to-avoid-part-1/">R Programming – Pitfalls to avoid (Part 1)</a></li>
<li><a title="Permanent Link toEclipse – an alternative to RStudio – part 2" target="_blank" rel="nofollow" href="https://datascienceplus.com/eclipse-an-alternative-to-rstudio-part-2/">Eclipse – an alternative to RStudio – part 2</a></li>
<li><a title="Permanent Link toEclipse – an alternative to RStudio – part 1" target="_blank" rel="nofollow" href="https://datascienceplus.com/eclipse-an-alternative-to-rstudio-part-1/">Eclipse – an alternative to RStudio – part 1</a></li>
</ol></strong>
<div>
<a target="_blank" rel="nofollow" href="http://feeds.feedburner.com/~ff/datascienceplus?a=nfdRqqwfHi4:ZwO-utlwHp0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/datascienceplus?i=nfdRqqwfHi4:ZwO-utlwHp0:D7DqB2pKExk" border="0"></a> <a target="_blank" rel="nofollow" href="http://feeds.feedburner.com/~ff/datascienceplus?a=nfdRqqwfHi4:ZwO-utlwHp0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/datascienceplus?d=qj6IDK7rITs" border="0"></a> <a target="_blank" rel="nofollow" href="http://feeds.feedburner.com/~ff/datascienceplus?a=nfdRqqwfHi4:ZwO-utlwHp0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/datascienceplus?d=yIl2AUoC8zA" border="0"></a>
</div>
<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://datascienceplus.com/understanding-linear-svm-with-r/"> DataScience+</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/KypgDWenHwM"></a></div>