1. 程式人生 > >LaTeX完整例子_參考文獻、圖、表和公式

LaTeX完整例子_參考文獻、圖、表和公式

\documentclass[UTF8,twoside]{ctexart}

\usepackage{mathtools}
\usepackage[CJKbookmarks=true,colorlinks,linkcolor=blue,anchorcolor=blue,citecolor=green]{hyperref}
\usepackage[top=2cm,bottom=2cm,left=1cm,right=3mm]{geometry}
\usepackage{graphicx}
\usepackage{enumerate}
\usepackage{titlesec}
\usepackage{titletoc}
\usepackage{bm}

\usepackage{nameref}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{fancyhdr}
 \usepackage{lastpage}
\usepackage{everb}   % \colorboxed命令

\newcommand{\HRule}{\rule{\linewidth}{0.5mm}}
\newcommand{\myFunc}{}
\newenvironment{myquote}
  {\begin{quote}\kaishu\zihao{4}}
  {\end{quote}}

\titlecontents{section}
              [3cm]
              {\bf \large}%
              {\contentslabel{2.5em}}%
              {}%
              {\titlerule*[0.5pc]{$\cdot$}\contentspage\hspace*{3cm}}%
\titlecontents{subsection}
              [4cm]
              {\bf \normalsize}%
              {\contentslabel{2.5em}}%
              {}%
              {\titlerule*[0.5pc]{$\cdot$}\contentspage\hspace*{3cm}}%

\begin{document}
\zihao{4}
\begin{titlepage}
\begin{center}
\includegraphics[width=0.3\textwidth]{logobupt}\\[1cm]
\textsc{\LARGE Beijing University of Posts and Telecommunications}\\[1.5cm]
\HRule \\[0.4cm]
{ \huge \bfseries 機器學習之常見演算法思想梳理 \\[0.4cm] }

\HRule \\[1.5cm]
\noindent
\begin{minipage}{0.4\textwidth}
\begin{flushleft} \large
\emph{AUTHOR:}\\
\quad {\bf \href{http://www.cnblogs.com/tornadomeet}{tornadomeet}}\footnotemark
\end{flushleft}
\end{minipage}%
\begin{minipage}{0.4\textwidth}
\begin{flushright} \large
\emph{EDITOR:\;\;} \\
{\bf \href{http://blog.csdn.net/u012176591}{金良}}\footnotemark
\end{flushright}
\end{minipage}
  \vfill
  {\Large \today}
\end{center}
\footnotetext[1]{部落格達人,其部落格地址:\url{http://www.cnblogs.com/tornadomeet}}
\footnotetext[2]{北京郵電大學2014屆碩士生,研究方向:服務計算和物聯網,部落格地址:\url{http://blog.csdn.net/u012176591}}
\end{titlepage}
\setcounter{page}{1}
\pagenumbering{Roman}
\pagestyle{fancy}
\fancyhf{}  %清除以前對頁首頁尾的設定
\fancyhead{}
\pagestyle{fancy}
\cfoot{\thepage}
\tableofcontents
\newpage
\setcounter{page}{1}
\pagestyle{fancy}
\pagenumbering{arabic}
\fancyhf{}  %清除以前對頁首頁尾的設定
\pagestyle{fancy}
\fancyhead[RO,LE]{\bfseries 機器學習串串燒}
\fancyhead[LO,RE]{\bfseries BYR~金良}
\fancyfoot[C]{\thepage $\slash$ \pageref{LastPage}}
%\fancyfoot[LE,RO]{\chaptername}
\section{前言}
找工作時(IT行業),除了常見的軟體開發以外,機器學習崗位也可以當作是一個選擇,不少計算機方向的研究生都會接觸這個,如果你的研究方向是機器學習/資料探勘之類,且又對其非常感興趣的話,可以考慮考慮該崗位,畢竟在機器智慧沒達到人類水平之前,機器學習可以作為一種重要手段,而隨著科技的不斷髮展,相信這方面的人才需求也會越來越大。

縱觀IT行業的招聘崗位,機器學習之類的崗位還是挺少的,國內大點的公司裡百度,阿里,騰訊,網易,搜狐,華為(華為的崗位基本都是隨機分配,機器學習等崗位基本面向的是博士)等會有相關職位,另外一些國內的中小型企業和外企也會招一小部分。當然了,其中大部分還是百度北京要人最多,上百人。阿里的演算法崗位很大一部分也是搞機器學習相關的。另外本人有幸簽約了網易杭州研究院的深度學習演算法崗位,打算從事機器學習領域至少5年。非常感謝小易收留了我!

下面是本人在找機器學習崗位工作時,總結的常見機器學習演算法(主要是一些常規分類器)大概流程和主要思想,希望對大家找機器學習崗位時有點幫助。實際上在面試過程中,懂這些演算法的基本思想和大概流程是遠遠不夠的,那些面試官往往問的都是一些公司內部業務中的課題,往往要求你不僅要懂得這些演算法的理論過程,而且要非常熟悉怎樣使用它,什麼場合用它,演算法的優缺點,以及調參經驗等等。說白了,就是既要會點理論,也要會點應用,既要有點深度,也要有點廣度,否則運氣不好的話很容易就被刷掉,因為每個面試官愛好不同。
\section{樸素貝葉斯}
有以下幾個地方需要注意:
\begin{itemize}
  \item 如果給出的特徵向量長度可能不同,這是需要歸一化為通長度的向量(這裡以文字分類為例),比如說是句子單詞的話,則長度為整個詞彙量的長度,對應位置是該單詞出現的次數。
  \item 計算公式如下:\\
  \begin{equation}
  p(c_i|{\bf w})=\frac{p({\bf w}|c_i)p(c_i)}{p({\bf w})}
  \end{equation}
  其中一項條件概率可以通過樸素貝葉斯條件獨立展開。要注意一點就是$p({\bf w}|c_i)$的計算方法,而由樸素貝葉斯的前提假設可知,$p(w_0,w_1,w_2,\ldots,w_N|c_i)=p(w_0|c_i)p(w_1|c_i)p(w_2|c_i)\ldots p(w_N|c_i)$,因此一般有兩種,一種是在類別為$c_i$的那些樣本集中,找到$w_j$出現次數的總和,然後除以該樣本的總和;第二種方法是類別為$c_i$的那些樣本集中,找到$w_j$出現次數的總和,然後除以該樣本中所有特徵出現次數的總和。
  \item 如果$p({\bf w}|c_i)$中的某一項為$0$,則其聯合概率的乘積也可能為$0$,即$2$中公式的分子為$0$,為了避免這種現象出現,一般情況下會將這一項初始化為$1$,當然為了保證概率相等,分母應對應初始化為$2$(這裡因為是$2$類,所以加$2$,如果是$k$類就需要加$k$,術語上叫做{\bf $laplace$光滑}, 分母加$k$的原因是使之滿足全概率公式)。
\end{itemize}
{\color{blue}\bf 樸素貝葉斯的優點}:
\begin{itemize}
\item 對小規模的資料表現很好,適合多分類任務,適合增量式訓練。
\end{itemize}
{\color{blue}\bf 缺點}:
\begin{itemize}
\item 對輸入資料的表達形式很敏感。
\end{itemize}
\section{決策樹}
決策樹中很重要的一點就是選擇一個屬性進行分枝,因此要注意一下資訊增益的計算公式,並深入理解它。\par
資訊熵的計算公式如下:
\begin{equation}
H=-\sum_{i=1}^{n}p(x_i)log_2(p(x_i))
\end{equation}
其中的$n$代表有$n$個分類類別(比如假設是$2$類問題,那麼$n=2$)。分別計算這$2$類樣本在總樣本中出現的概率$p_1$和$p_2$,這樣就可以計算出未選中屬性分枝前的資訊熵。
\par
現在選中一個屬性$x_i$用來進行分枝,此時分枝規則是:如果$x_i=v_x$的話,將樣本分到樹的一個分支;如果不相等則進入另一個分支。很顯然,分支中的樣本很有可能包括$2$ 個類別,分別計算這$2$個分支的熵$H_1$和$H_2$,計算出分枝後的總資訊熵$H’=p_1H_1+p_2H_2$,則此時的資訊增益$\Delta H=H-H'$。以資訊增益為原則,把所有的屬性都測試一邊,選擇一個使增益最大的屬性作為本次分枝屬性。\\
{\color{blue}\bf 決策樹的優點}:
\begin{itemize}
\item 計算量簡單,可解釋性強,比較適合處理有缺失屬性值的樣本,能夠處理不相關的特徵;
\end{itemize}
{\color{blue}\bf 缺點}:
\begin{itemize}
\item 容易過擬合(後續出現了隨機森林,減小了過擬合現象);
\end{itemize}
\section{Logistic迴歸}
\renewcommand{\myFunc}{$Logistic$\;}
\myFunc 是用來分類的,是一種線性分類器,需要注意的地方有:\\
\begin{itemize}
\item \myFunc 函式表示式為:
\begin{equation}
h_{\theta}({\bf x})=g({\bf \theta}^T {\bf x})=\frac{1}{1+\exp{(-{\bf \theta}^T {\bf x})}},{\textrm where\; } g(z)=\frac{1}{1+\exp(-z)}
\end{equation}
其導數形式為:
\begin{equation}
\begin{split}
  g'(z)&= \frac{\mathrm d}{\mathrm d x} \frac{1}{1+\exp(-z)}\\
       &= \frac{1}{\left(1+\exp(-z)\right)^2}\left(\exp(-z)\right)\\
       &= \frac{1}{1+\exp(-z)}\left( 1-\frac{1}{1+\exp(-z)}\right)\\
       &= g(z)(1-g(z))
\end{split}
\end{equation}
\item \myFunc 迴歸方法主要是用最大似然估計來學習的,所以單個樣本的後驗概率為:
\begin{equation}
p(y|x;\theta)=\left(h_{\theta}(x)\right)^y\left(1-h_{\theta}(x)\right)^{1-y}
\end{equation}
到整個樣本的後驗概率:
\begin{equation}
\begin{split}
 L(\theta)   &=p(\vec{y}|\bf{X};\theta)\\
            &=\prod_{i=1}^{m}p\left(y^{(i)}|x^{(i)};\theta\right)\\
            &=\prod_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)\right)^{y^{(i)}}\left(h_{\theta}\left(x^{(i)}\right)\right)^{1-y^{(i)}}
\end{split}
\end{equation}
其中:
\begin{equation}
\begin{split}
P(y=1|x;\theta)&=h_{\theta}(x)\\
P(y=1|x;\theta)&=1-h_{\theta}(x)
\end{split}
\end{equation}
通過對數進一步化簡為:
\begin{equation}
\begin{split}
  \ell(\theta)  &= \log L(\theta)\\
                &=\sum_{i=1}^{m}y^{(i)}\log h\left(x^{(i)}\right)+\left(1-y^{(i)}\right)\log \left(1-h\left(x^{(i)}\right)\right)
\end{split}
\end{equation}
\item 其實它的${\mathrm loss\; function}$為$-\ell(\theta)$,因此我們需使${\mathrm loss\; function}$最小,可採用梯度下降法得到。梯度下降法公式為:
\begin{equation}
\begin{split}
\frac{{\mathrm \partial}}{{\mathrm \partial\theta_{j}}}\ell(\theta) &=\left(y-\frac{1}{g\left(\theta^{T}{\bf x}\right)}-(1-y)\frac{1}{1-g\left(\theta^T{\bf x}\right)}\right)\frac{\partial}{\partial \theta_j}g\left(\theta^T{\bf x}\right)\\
&=\left(y-\frac{1}{g\left(\theta^{T}{\bf x}\right)}-(1-y)\frac{1}{1-g\left(\theta^T{\bf x}\right)}\right)g(\theta^T{\bf x})\left(1-g(\theta^T{\bf x})\right)\frac{\partial}{\partial \theta_j}\\
&=\left(y\left(1-g(\theta^T{\bf x})\right)-\left(1-y\right)g\left(\theta^T{\bf x}\right)\right)x_j\\
&=\left(y-h_{\theta}\left(x\right)\right)x_j\\
\theta_j&:=\theta_j+\alpha\left(y^{(i)}-h_{\theta}\left(x^{(i)}\right)\right)x_j^{(i)}
\end{split}
\end{equation}
\end{itemize}
{\color{blue}\bf Logistic迴歸優點}:
\begin{itemize}
\item 實現簡單;
\item 分類時計算量非常小,速度很快,儲存資源低;
\end{itemize}
{\color{blue}\bf 缺點}:
\begin{itemize}
\item 容易欠擬合,一般準確度不太高
\item 只能處理兩分類問題(在此基礎上衍生出來的softmax可以用於多分類),且必須線性可分;
\end{itemize}

\section{線性迴歸}
線性迴歸才是真正用於迴歸的,而不像$Logistic$\;迴歸是用於分類,其基本思想是用梯度下降法對最小二乘法形式的誤差函式進行優化,當然也可以用$normal\;equation$直接求得引數的解,結果為:
\begin{equation}
\hat{{\bf w}}=\left({\bf X}^T{\bf X}\right)^{-1}{\bf X}^T{\bf y}
\end{equation}
\par 而在${\mathrm LWLR}$(區域性加權線性迴歸)中,引數的計算表示式為:
\begin{equation}
\hat{{\bf w}}=\left({\bf X}^T{\bf W}{\bf X}\right)^{-1}{\bf X}^T{\bf W}{\bf y}
\end{equation}
\par 因為此時優化的是:
\begin{itemize}
  \item {\text Fit} $\theta$ {\text to minimize} $\sum_i w^{(i)}\left(y^{(i)}-\theta^Tx^{(i)}\right)^2$
  \item {\text Output} $\theta^Tx$
\end{itemize}
\par 由此可見LWLR與LR不同,LWLR是一個非引數模型,因為每次進行迴歸計算都要遍歷訓練樣本至少一次。\\
{\bf 線性迴歸優點}:
\begin{itemize}
\item 實現簡單,計算簡單;
\end{itemize}
{\bf 缺點}:
\begin{itemize}
\item 不能擬合非線性資料;\\
\end{itemize}
\section{KNN演算法}
KNN即最近鄰演算法,其主要過程為:
\begin{enumerate}
  \item 計算訓練樣本和測試樣本中每個樣本點的距離(常見的距離度量有歐式距離,馬氏距離等);
  \item 對上面所有的距離值進行排序;
  \item 選前$k$個最小距離的樣本;
  \item 根據這$k$個樣本的標籤進行投票,得到最後的分類類別;
\end{enumerate}
\par 如何選擇一個最佳的$K$值,這取決於資料。一般情況下,在分類時較大的$K$值能夠減小噪聲的影響。但會使類別之間的界限變得模糊。一個較好的$K$值可通過各種啟發式技術來獲取,比如,交叉驗證。另外噪聲和非相關性特徵向量的存在會使$K$近鄰演算法的準確性減小。
\par 近鄰演算法具有較強的一致性結果。隨著資料趨於無限,演算法保證錯誤率不會超過貝葉斯演算法錯誤率的兩倍。對於一些好的$K$值,$K$近鄰保證錯誤率不會超過貝葉斯理論誤差率。
\par {\color{red}注:}馬氏距離一定要先給出樣本集的統計性質,比如均值向量,協方差矩陣等。關於馬氏距離的介紹,這裡引用維基百科的內容
\footnote{http://zh.wikipedia.org/wiki/\%E9\%A9\%AC\%E6\%B0\%8F\%E8\%B7\%9D\%E7\%A6\%BB} 如下:\\
%\noindent \includegraphics[width=1.0\textwidth]{mashijuli}\\[1cm]
\begin{center}
\begin{colorboxed}
\begin{myquote}

  \indent {\bf 馬氏距離}是由印度統計學家馬哈拉諾比斯(P. C. Mahalanobis)提出的,表示資料的協方差距離。它是一種有效的計算兩個未知樣本集的相似度的方法。與歐氏距離不同的是它考慮到各種特性之間的聯絡(例如:一條關於身高的資訊會帶來一條關於體重的資訊,因為兩者是有關聯的)並且是尺度無關的(scale-invariant),即獨立於測量尺度。 對於一個均值為$\mu=\left(\mu_1,\mu_2,\mu_3,\cdots,\mu_p\right)^T$,協方差矩陣為$\Sigma$的多變數向量$x=\left(x_1,x_2,x_3,\cdots,x_p\right)^T$,其馬氏距離為:
  $$D_M(x)=\sqrt{\left(x-\mu\right)^T\Sigma^{-1}\left(x-\mu\right)}$$
  {\bf 馬氏距離}也可以定義為兩個服從同一分佈並且其協方差矩陣為$\Sigma $的隨機變數 $\vec{x}$與 $\vec{y}$的差異程度:
  $$d\left(\vec{x},\vec{y}\right)=\sqrt{\left(\vec{x}-\vec{y}\right)^T\Sigma^{-1}\left(\vec{x}-\vec{y}\right)}$$
  \quad 如果協方差矩陣為單位矩陣,馬氏距離就簡化為歐氏距離;如果協方差矩陣為對角陣,其也可稱為正規化的歐氏距離。
  $$d\left(\vec{x},\vec{y}\right)=\sqrt{\Sigma_{i=1}^{p}\frac{\left(x_i-y_i\right)^2}{\sigma_i^2}}$$
  其中$\sigma_i$是$x_i$的標準差。
\end{myquote}
\end{colorboxed}
\end{center}
{\color{blue} \bf KNN演算法的優點}:
\begin{itemize}
\item 思想簡單,理論成熟,既可以用來做分類也可以用來做迴歸;
\item 可用於非線性分類;
\item 訓練時間複雜度為$O(n)$;
\item 準確度高,對資料沒有假設,對outlier不敏感;
\end{itemize}
{\color{blue} \bf 缺點}:
\begin{itemize}
\item 計算量大;
\item 樣本不平衡問題(即有些類別的樣本數量很多,而其它樣本的數量很少);
\item 需要大量的記憶體;
\end{itemize}

\section{SVM}
要學會如何使用libsvm以及一些引數的調節經驗,另外需要理清楚svm演算法的一些思路:
\begin{enumerate}
\item svm\;中的最優分類面是對所有樣本的幾何裕量最大(為什麼要選擇最大間隔分類器,請從數學角度上說明?網易深度學習崗位面試過程中有被問到。答案就是幾何間隔與樣本的誤分次數間存在關係:\mbox{誤分次數} $ \leq \left(\frac{2R}{\sigma}\right)^2$,其中的分母就是樣本到分類間隔距離,分子中的R是所有樣本中的最長向量值),即:
\begin{equation}
\begin{split}
\max {}_{{\bm \gamma,\omega,b}} \; \gamma  &\\
\qquad  s.t. \quad & {\bf y}^{(i)}\left({\bf \omega}^{T}{\bf x}^{(i)}+{\bf b}\right)\geq \gamma, i=1,\cdots,m\\
&\parallel\negthickspace {\bm \omega} \negthickspace\parallel = 1
\end{split}
\end{equation}
\par 經過一系列推導可得為優化下面原始目標:
\begin{equation}\label{equ:svm1}
  \begin{split}
    \min {}_{{\bf \gamma,\omega,b}}& \;\frac{1}{2}{\parallel\negthickspace {\bf \omega} \negthickspace\parallel }^2\\
    s.t.&\quad {\bf y}^{(i)}\left({\bf \omega}^{T}{\bf x}^{(i)}+{\bf b}\right)\geq \gamma, i=1,\cdots,m
  \end{split}
\end{equation}
\item 下面來看看拉格朗日理論:\\
\begin{equation}
  \begin{split}
    \min{}_{\omega}\quad &f\left(\omega\right)\\
    s.t.&\;g_i\left(\omega\right)\leq 0,i=1,\cdots,k\\
    &\;h_i\left(\omega\right)=0,i=1,\cdots,l
  \end{split}
\end{equation}
\par 為了解決該問題,我們定義如下的拉格朗日一般形式
\begin{equation}
  \begin{split}
    \mathcal{L}\left(\omega,b,\alpha\right)=f\left(\omega\right)+\sum_{i=1}{k}\alpha_ig_i\left(\omega\right)+\sum_{i=1}{l}\beta_ih_i\left(\omega\right)
  \end{split}
\end{equation}
%\noindent \includegraphics[width=1.0\textwidth]{lagran}\\
可以將\eqref{equ:svm1}中的優化目標轉換為拉格朗日的形式(通過各種對偶優化,KKD條件),最後目標函式為:
\begin{equation}\label{equ:svm2}
  \mathcal{L} \left(\omega,b,\alpha\right)=\frac{1}{2}{\parallel\negthickspace {\bf \omega} \negthickspace\parallel }^2-\sum_{i=1}^{m}\alpha_i\left[y^{(i)}\left(\omega^Tx^{(i)}+{\bf b}\right)-1\right]
\end{equation}
我們只需要最小化上述目標函式,其中的$\alpha$為原始優化問題中的不等式約束拉格朗日系數。
\item 對\eqref{equ:svm2}中最後的式子分別$\omega$和$b$求導可得:
\begin{equation}
  \begin{split}
    \omega&=\sum_{i=1}^{m}\alpha_iy^{(i)}x^{(i)}\\
    \frac{\partial}{\partial b}\mathcal{L}\left(\omega,b,\alpha\right) &= \sum_{i=1}^{m}\alpha_{i}y^{(i)}=0
  \end{split}
\end{equation}
由上面第1式子可以知道,如果我們優化出了$\alpha$,則直接可以求出$\omega$了,即模型的引數搞定。而上面第2個式子可以作為後續優化的一個約束條件。
\item 對\eqref{equ:svm2}中最後一個目標函式用對偶優化理論可以轉換為優化下面的目標函式:
\begin{equation}
  \begin{split}
    \max {}_{\alpha}\quad  {\bf W}(\alpha) &= \sum_{i=1}^{m}\alpha_i-\frac{1}{2}\sum_{i,j=1}^my^{(i)}y^{(j)}\alpha_i\alpha_j\langle x^{(i)},y^{(j)} \rangle\\
    s.t.\quad  &\alpha_i \geq 0,i=1,\cdots,m\\
    &\sum_{i=1}^{m}\alpha_iy^{(i)}=0
  \end{split}
\end{equation}
而這個函式可以用常用的優化方法求得$\alpha$,進而求得$\omega$和{\bf b}。
\item 按照道理,svm簡單理論應該到此結束。不過還是要補充一點,即在預測時有:
\begin{equation}
  \begin{split}
    \omega^Tx+b&=\left(\sum_{i=1}^m\alpha_iy^{(i)}x^{(i)}\right)^Tx+b\\
               &=\sum_{i=1}^{m}\alpha_iy^{(i)}\langle x^{(i)},x\rangle+b
  \end{split}
\end{equation}
那個尖括號我們可以用核函式代替,這也是svm經常和核函式扯在一起的原因。
\item 最後是關於鬆弛變數的引入,因此原始的目標優化公式為:
\begin{equation}
  \begin{split}
    \min {}_{\gamma,\omega,b}\;&\frac{1}{2}{\parallel\negthickspace {\bf \omega} \negthickspace\parallel }^2+C\sum_{i=1}{m}\xi_i\\
    s.t.\;&y^{(i)}\left(\omega^Tx^{(i)}+b\right)\geq 1-\xi_i,i=1,\cdots,m\\
    &xi_i \geq 0,i=1,\cdots,m
  \end{split}
\end{equation}
此時對應的對偶優化公式為:
\begin{equation}
  \begin{split}
    \max {}_{\alpha}\; &W\left(\alpha\right)=\sum_{i=1}^m\alpha_i-\frac{1}{2}\sum_{i,j=1}^{m}y^{(i)}y^{(j)}\alpha_i\alpha_j\langle x^{(i)},x^{(j)}\rangle \\
    s.t.\quad &0\leq \alpha_i \leq C,i=1,\cdots,m\\
    &\sum_{i=1}^{m}\alpha_iy^{(i)}=0
  \end{split}
\end{equation}
與前面的相比只是$\alpha$多了個上界。
\end{enumerate}
{\color{blue}SVM演算法優點}:
\begin{itemize}
  \item 可用於線性/非線性分類,也可以用於迴歸;
  \item 低泛化誤差;
  \item 容易解釋;
  \item 計算複雜度較低;
\end{itemize}
{\color{blue}缺點}:
\begin{itemize}
  \item 對引數和核函式的選擇比較敏感;
  \item 原始的SVM只比較擅長處理二分類問題;
\end{itemize}
\section{Boosting}
\renewcommand{\myFunc}{\;Adaboost\;}
主要以\myFunc 為例,首先來看看\myFunc 的流程圖,如圖$\left(\ref{fig:Adaboost}\right)$所示:\\
\begin{figure}[!ht]
    \centering
    \includegraphics[width=0.5\textwidth]{Adaboost.png}
    \caption{Adaboost的流程圖}
    \label{fig:Adaboost}
\end{figure}
\par 從圖$\left(\ref{fig:Adaboost}\right)$中可以看到,在訓練過程中我們需要訓練出多個弱分類器(圖中為3個),每個弱分類器是由不同權重的樣本(圖中為5個訓練樣本)訓練得到(其中第一個弱分類器對應輸入樣本的權值是一樣的),而每個弱分類器對最終分類結果的作用也不同,是通過加權平均輸出的,權值見上圖中三角形裡面的數值。那麼這些弱分類器和其對應的權值是怎樣訓練出來的呢?
\par 下面通過一個例子來簡單說明。
\par 書中(machine learning in action)假設的是5個訓練樣本,每個訓練樣本的維度為2,在訓練第一個分類器時5個樣本的權重各為0.2. 注意這裡樣本的權值和最終訓練的弱分類器組對應的權值$\alpha$是不同的,樣本的權重只在訓練過程中用到,而$\alpha$在訓練過程和測試過程都有用到。
\par 現在假設弱分類器是帶一個節點的簡單決策樹,該決策樹會選擇2個屬性(假設只有2個屬性)的一個,然後計算出這個屬性中的最佳值用來分類。
\par \myFunc 的簡單版本訓練過程如下:
\begin{enumerate}
  \item 訓練第一個分類器,樣本的權值D為相同的均值。通過一個弱分類器,得到這5個樣本(請對應書中的例子來看,依舊是machine learning in action)的分類預測標籤。與給出的樣本真實標籤對比,就可能出現誤差(即錯誤)。如果某個樣本預測錯誤,則它對應的錯誤值為該樣本的權重,如果分類正確,則錯誤值為0. 最後累加5個樣本的錯誤率之和,記為$\varepsilon$ 。
  \item 通過$\varepsilon$ 來計算該弱分類器的權重$\alpha$ ,公式如下:
  \begin{equation}
    \alpha=\frac{1}{2}\ln\left(\frac{1-\varepsilon}{\varepsilon}\right)
  \end{equation}
  \item 通過$\alpha$ 來計算訓練下一個弱分類器樣本的權重$ D $,如果對應樣本分類正確,則減小該樣本的權重,公式為:
  \begin{equation}
    D_i^{(t+1)}=\frac{D_i^{(t)}e^{-\alpha}}{Sum(D)}
  \end{equation}
  如果樣本分類錯誤,則增加該樣本的權重,公式為:
  \begin{equation}
    D_i^{(t+1)}=\frac{D_i^{(t)}e^{\alpha}}{Sum(D)}
  \end{equation}
  \item 迴圈步驟1,2,3來繼續訓練多個分類器,只是其$ D $值不同而已。\\
  測試過程如下:\\
  輸入一個樣本到訓練好的每個弱分類中,則每個弱分類都對應一個輸出標籤,然後該標籤乘以對應的$\alpha$,最後求和得到值的符號即為預測標籤值。
\end{enumerate}
{\color{blue}Boosting演算法的優點}:
\begin{itemize}
  \item 低泛化誤差;
  \item 容易實現,分類準確率較高,沒有太多引數可以調;
\end{itemize}
{\color{blue}缺點}:
\begin{itemize}
  \item 對outlier比較敏感;
\end{itemize}
\section{聚類}
根據聚類思想劃分:
\begin{enumerate}
  \item 基於劃分的聚類:\\
  K-means, k-medoids(每一個類別中找一個樣本點來代表),CLARANS.\\
  k-means是使下面的表示式值最小:
  \begin{equation}
    V=\sum_{i=1}^{k}\sum_{x_j\in S_i}\left(x_j-\mu_i\right)^2
  \end{equation}
  {\color{blue}k-means演算法的優點}:
  \begin{itemize}
    \item k-means演算法是解決聚類問題的一種經典演算法,演算法簡單、快速。
    \item 對處理大資料集,該演算法是相對可伸縮的和高效率的,因為它的複雜度大約是$O(nkt)$,其中$n$是所有物件的數目,$k$是簇的數目,$t$ 是迭代的次數。通常$k\ll n$。這個演算法通常區域性收斂。
    \item 演算法嘗試找出使平方誤差函式值最小的$k$個劃分。當簇是密集的、球狀或團狀的,且簇與簇之間區別明顯時,聚類效果較好。
  \end{itemize}
  {\color{blue}缺點}:
    \begin{itemize}
    \item $k-$平均方法只有在簇的平均值被定義的情況下才能使用,且對有些分類屬性的資料不適合。
    \item 要求使用者必須事先給出要生成的簇的數目$k$。
    \item 對初值敏感,對於不同的初始值,可能會導致不同的聚類結果。
    \item 不適合於發現非凸面形狀的簇,或者大小差別很大的簇。
    \item 對於``噪聲"和孤立點資料敏感,少量的該類資料能夠對平均值產生極大影響。
  \end{itemize}
  \item 基於層次的聚類:\\ 自底向上的凝聚方法,比如AGNES。\\ 自上向下的分裂方法,比如DIANA。
  \item 基於密度的聚類:\\ DBSACN,OPTICS,BIRCH(CF-Tree),CURE.
  \item 基於網格的方法:\\ STING, WaveCluster.
  \item 基於模型的聚類:\\ EM,SOM,COBWEB.
\end{enumerate}
\par 以上這些演算法的簡介可參考\href{http://baike.baidu.com/view/31801.htm}{聚類(百度百科)}。
\section{推薦系統}
\par 推薦系統的實現主要分為兩個方面:基於內容的實現和協同濾波的實現。
\begin{enumerate}
\item 基於內容的實現:
\par 不同人對不同電影的評分這個例子,可以看做是一個普通的迴歸問題,因此每部電影都需要提前提取出一個特徵向量(即x值),然後針對每個使用者建模,即每個使用者打的分值作為y值,利用這些已有的分值y和電影特徵值x就可以訓練迴歸模型了(最常見的就是線性迴歸)。這樣就可以預測那些使用者沒有評分的電影的分數。(值得注意的是需對每個使用者都建立他自己的迴歸模型)
\par 從另一個角度來看,也可以是先給定每個使用者對某種電影的喜好程度(即權值),然後學出每部電影的特徵,最後採用迴歸來預測那些沒有被評分的電影。
\par 當然還可以是同時優化得到每個使用者對不同型別電影的熱愛程度以及每部電影的特徵。具體可以參考\href{https://www.coursera.org/course/ml}{Ng在coursera 上的ml教程}\footnote{https://www.coursera.org/course/ml}:
\item 基於協同濾波的實現:
\par 協同濾波(CF)可以看做是一個分類問題,也可以看做是矩陣分解問題。協同濾波主要是基於每個人自己的喜好都類似這一特徵,它不依賴於個人的基本資訊。比如剛剛那個電影評分的例子中,預測那些沒有被評分的電影的分數只依賴於已經打分的那些分數,並不需要去學習那些電影的特徵。
\end{enumerate}
\par SVD將矩陣分解為三個矩陣的乘積,公式如下所示:
\begin{equation}
  Data_{m\times n} = U_{m\times m}\Sigma_{m\times n}V_{n\times n}^T
\end{equation}
\par 中間的矩陣$\Sigma$為對角矩陣,對角元素的值為Data矩陣的奇異值(注意奇異值和特徵值是不同的),且已經從大到小排列好了。即使去掉特徵值小的那些特徵,依然可以很好的重構出原始矩陣。如圖$\left(\ref{fig:recommendation}\right)$所示:
\begin{figure}[!ht]
    \centering
    \includegraphics[width=0.6\textwidth]{recommendation.png}
    \caption{SVD矩陣分解示意圖}
    \label{fig:recommendation}
\end{figure}
\par 其中更深的顏色代表去掉小特徵值重構時的三個矩陣。
\par m代表商品的個數,n代表使用者的個數,則U矩陣的每一行代表商品的屬性,現在通過降維U矩陣(取深色部分)後,每一個商品的屬性可以用更低的維度表示(假設為k 維)。這樣當新來一個使用者的商品推薦向量X,則可以根據公式$X'q\times U1\times {\textrm inv}(S1)$得到一個k維的向量,然後在$V’$中尋找最相似的那一個使用者(相似度測量可用餘弦公式等),根據這個使用者的評分來推薦(主要是推薦新使用者未打分的那些商品)。具體例子可以參考網頁:\href{http://blog.csdn.net/wuyanyi/article/details/7964883}{SVD在推薦系統中的應用}。
\par 另外關於SVD分解後每個矩陣的實際含義可以參考google吳軍的《數學之美》一書(不過個人感覺吳軍解釋UV兩個矩陣時好像弄反了,不知道大家怎樣認為)。或者參考《machine learning in action》其中的svd章節。
\section{pLSA}
\par pLSA由LSA發展過來,而早期LSA的實現主要是通過SVD分解。pLSA的模型圖如圖$\left(\ref{fig:pLSA}\right)$所示::
\begin{figure}[!ht]
    \centering
    \includegraphics[width=0.5\textwidth]{pLSA.png}
    \caption{pLSA模型示意圖}
    \label{fig:pLSA}
\end{figure}
\par 公式中的意義如下:
\begin{enumerate}
  \item 以$P\left(d_i\right)$的概率選中文件$d_i$;
  \item 以$P\left(z_k|d_i\right)$的概率選中主題$z_k$;
  \item 以$P\left(\omega_j|z_k\right)$的概率產生一個單詞$d_i$;
\end{enumerate}
\par 我們可以觀察到的資料就是$\left(d_i,\omega_j\right)$對,而$z_k$是隱含變數,$\left(d_i,\omega_j\right)$的聯合分佈為
\begin{equation}
P\left(d_i,\omega_j\right)=P\left(d_i\right)P\left(\omega_j|d_i\right),P\left(\omega_j|d_i\right)=\sum_{k=1}^{K}P\left(\omega_j|z_k\right)P\left(z_k|d_i\right)
\end{equation}
\par 具體可以參考\href{http://bcmi.sjtu.edu.cn/ds/download.html}{2010龍星計劃:機器學習中對應的主題模型那一講}。
\section{LDA}
\par 主題模型,如圖$\left(\ref{fig:LDA}\right)$所示:
\begin{figure}[!ht]
\centering
\includegraphics[width=0.5\textwidth]{LDA.jpg}
\caption{概率圖}
\label{fig:LDA}
\end{figure}
\par 和\;pLSA\;不同的是\;LDA\;中假設了很多先驗分佈,且一般引數的先驗分佈都假設為\;Dirichlet\;分佈,其原因是共軛分佈時先驗概率和後驗概率的形式相同。
\section{GDBT}
\par \;GBDT(Gradient Boosting Decision Tree)\; 又叫 \;MART(Multiple Additive Regression Tree)\;,好像在阿里內部用得比較多(所以阿里演算法崗位面試時可能會問到),它是一種迭代的決策樹演算法,該演算法由多棵決策樹組成,所有樹的輸出結果累加起來就是最終答案。它在被提出之初就和SVM一起被認為是泛化能力\;(generalization)\;較強的演算法。近些年更因為被用於搜尋排序的機器學習模型而引起大家關注。
\par \;GBDT\;是迴歸樹,不是分類樹。其核心就在於,每一棵樹是從之前所有樹的殘差中來學習的。為了防止過擬合,和\;Adaboosting\;一樣,也加入了\;boosting\; 這一項。
\par 關於\;GDBT\; 的介紹可以可以參考:\href{http://hi.baidu.com/hehehehello/item/96cc42e45c16e7265a2d64ee}{GBDT(MART) 迭代決策樹入門教程|簡介}。
\section{Regularization}
\par 作用是(網易電話面試時有問到):
\begin{enumerate}
  \item 數值上更容易求解;
  \item 特徵數目太大時更穩定;
  \item 控制模型的複雜度,光滑性。複雜性越小且越光滑的目標函式泛化能力越強。而加入規則項能使目標函式複雜度減小,且更光滑。
  \item 減小引數空間;引數空間越小,複雜度越低。
  \item 係數越小,模型越簡單,而模型越簡單則泛化能力越強(Ng巨集觀上給出的解釋)。
  \item 可以看出是權值的高斯先驗。
\end{enumerate}
\section{異常檢測}
\par 可以估計樣本的密度函式,對於新樣本直接計算其密度,如果密度值小於某一閾值,則表示該樣本異常。而密度函式一般採用多維的高斯分佈。如果樣本有n維,則每一維的特徵都可以看作是符合高斯分佈的,即使這些特徵可視化出來不太符合高斯分佈,也可以對該特徵進行數學轉換讓其看起來像高斯分佈,比如說$x=\log(x+c),x=x^{(\frac{1}{c})}$等。異常檢測的演算法流程如下:\\[2mm]
{\bf Anomaly detection algorithm}\\
\begin{enumerate}
  \item {\bf Choose features that you think might be indicative of anomalous examples.}
  \item {\bf Fit parameters} $\mu_1,\cdots,\mu_n,\sigma_1^2,\cdots,\sigma_n^2$
  \begin{equation}
    \begin{split}
      \mu_j&=\frac{1}{m}\sum_{i=1}^{m}x_j^{(i)}\\
      \sigma_j^2&=\frac{1}{m}\sum_{i=1}^{m}\left(x_j^{(i)}-\mu_j\right)^2
    \end{split}
  \end{equation}
  \item {\bf Given new example} ${\bf x}$,{\bf compute }$p(x)$:
  \begin{equation}
    \begin{split}
      p(x)=\prod_{j=1}^{n}p\left(x_j;\mu_j,\sigma_j^2\right)=\prod_{j=1}^{n}\frac{1}{\sqrt{2\pi}\sigma_j}\exp\left(-\frac{\left(x_j-\mu_j\right)^2}{2\sigma_j^2}\right)\\
      {\bf Anomaly \; if\; } p\left(x\right) < \varepsilon
    \end{split}
  \end{equation}
\end{enumerate}
\par 其中的$\varepsilon$ 也是通過交叉驗證得到的,也就是說在進行異常檢測時,前面的p(x)的學習是用的無監督,後面的引數$\varepsilon$學習是用的有監督。那麼為什麼不全部使用普通有監督的方法來學習呢(即把它看做是一個普通的二分類問題)?主要是因為在異常檢測中,異常的樣本數量非常少而正常樣本數量非常多,因此不足以學習到好的異常行為模型的引數,因為後面新來的異常樣本可能完全是與訓練樣本中的模式不同。
\par 另外,上面是將特徵的每一維看成是相互獨立的高斯分佈,其實這樣的近似並不是最好的,但是它的計算量較小,因此也常被使用。更好的方法應該是將特徵擬合成多維高斯分佈,這時有特徵之間的相關性,但隨之計算量會變複雜,且樣本的協方差矩陣還可能出現不可逆的情況(主要在樣本數比特徵數小,或者樣本特徵維數之間有線性關係時)。
\par 上面的內容可以參考Ng的{\color{blue}https://www.coursera.org/course/ml}
\section{EM演算法}
\par 有時候因為樣本的產生和隱含變數有關(隱含變數是不能觀察的),而求模型的引數時一般採用最大似然估計,由於含有了隱含變數,所以對似然函式引數求導是求不出來的,這時可以採用EM演算法來求模型的引數的(對應模型引數個數可能有多個),EM演算法一般分為2步:
\begin{itemize}
\item E步:選取一組引數,求出在該引數下隱含變數的條件概率值;
\item M步:結合E步求出的隱含變數條件概率,求出似然函式下界函式(本質上是某個期望函式)的最大值。
\end{itemize}
\par 重複上面2步直至收斂。
\par 公式如下所示:
\begin{equation}
  \begin{split}
    {\mathrm {(E\negthickspace-\negthickspace step)\quad For\; each\; }}i ,&{\mathrm set}\\
    &Q_i\left(z^{(i)}\right):=p\left(z^{(i)}|x^{(i)};\theta\right)\\
   \mathrm{(M\negthickspace-\negthickspace step)}\quad \mathrm{Set}\qquad\quad&\\
    &\theta := \arg\max_\theta\sum_i\sum_{z^{(i)}}\log \frac{p\left(x^{(i)},z^{(i)};\theta\right)}{Q_i\left(z^{(i)}\right)}
  \end{split}
\end{equation}
\par M步公式中下界函式的推導過程:
\begin{equation}
  \begin{split}
    \sum_i\log p\left(x^{(i)};\theta\right)&=\sum_i\log\sum_{z^{(i)}}p\left(x^{(i)},z^{(i)};\theta\right)\\
    &=\sum_i\log\sum_{z^{(i)}}Q_i\left(z^{(i)}\right)\frac{p\left(x^{(i)},z^{(i)};\theta\right)}{Q_i\left(z^{(i)}\right)}\\
    &\geq \sum_i\sum_{z^{(i)}}Q_i\left(z^{(i)}\right)\log \frac{p\left(x^{(i)},z^{(i)};\theta\right)}{Q_i\left(z^{(i)}\right)}
  \end{split}
\end{equation}
\par EM演算法一個常見的例子就是GMM模型,每個樣本都有可能由k個高斯產生,只不過由每個高斯產生的概率不同而已,因此每個樣本都有對應的高斯分佈(k箇中的某一個),此時的隱含變數就是每個樣本對應的某個高斯分佈。
\par GMM的E步公式如下(計算每個樣本對應每個高斯的概率):
\begin{equation}
  \begin{split}
    {\textrm (E\negthickspace-\negthickspace step)For\;each\;}&i,j,{\textrm \;set}\\
    &\omega_j^{(i)}:=p\left(z^{(i)}=j|x^{(i)};\phi,\mu,\Sigma\right)
  \end{split}
\end{equation}
\par 更具體的計算公式為:
\begin{equation}
  p\left(z^{(i)}=j|x^{(i)};\phi,\mu,\Sigma\right)=\frac{p\left(x^{(i)}|z^{(i)}=j;\mu,\Sigma\right)p\left(z^{(i)}=j;\phi\right)}{\sum_{l=1}^{k}p\left(x^{(i)}|z^{(i)}=l;\mu,\Sigma\right)p\left(z^{(i)}=l;\phi\right)}
\end{equation}
\par M步公式如下(計算每個高斯的比重,均值,方差這3個引數):
\begin{equation}
\begin{split}
  {\mathrm (M\negthickspace-\negthickspace step)\;}&{\mathrm Update\;the\;parameters: }\\
  &\phi_j:=\frac{1}{m}\sum_{i=1}^{m}\omega_j^{(i)},\\
  &\mu_j:= \frac{\sum_{i=1}^{m}\omega_j^{(i)}x^{(i)}}{\sum_{i=1}^{m}\omega_j^{(i)}},\\
  &\Sigma_j:=\frac{\sum_{i=1}^{m}\omega_j^{(i)}\left(x^{(i)}-\mu_j\right)\left(x^{(i)}-\mu_j\right)^T}{\sum_{i=1}^{m}\omega_j^{(i)}}
\end{split}
\end{equation}
\par 關於EM演算法可以參考Ng的\href{http://cs229.stanford.edu/}{cs229課程資料} 或者網易公開課:\href{http://v.163.com/special/opencourse/machinelearning.html}{斯坦福大學公開課 :機器學習課程}。
\section{Apriori}
\par Apriori是關聯分析中比較早的一種方法,主要用來挖掘那些頻繁項集合。其思想是:
\begin{enumerate}
\item 如果一個專案集合不是頻繁集合,那麼任何包含它的專案集合也一定不是頻繁集合;
\item 如果一個專案集合是頻繁集合,那麼它的任何非空子集也是頻繁集合;
\end{enumerate}
\par Aprioir需要掃描專案表多遍,從一個專案開始掃描,捨去掉那些不是頻繁的專案,得到的集合稱為L,然後對L中的每個元素進行自組合,生成比上次掃描多一個專案的集合,該集合稱為C,接著又掃描去掉那些非頻繁的專案,重複…
\par 看下面這個例子:
\par 元素專案表格如表$\left(\ref{tab:xiangmuyuansu}\right)$所示。
\begin{table}
  \centering
  \Large  %表內的字型大小
  \caption{A simple list of transactions from a natural foods grocery store called Hole Foods}
  \label{tab:xiangmuyuansu}
  \begin{tabular}{c|l}
    \hline
    Transaction number&items\\
    \hline
    0&soy milk,lettuce\\
    1&lettuce,diapers,wine,chard\\
    2&soy milk,diapers,wine,orange juice\\
    3&lettuce,soy milk,diapers,wine\\
    4&lettuce,soy milk,diapers,orange juice\\
    \hline
  \end{tabular}
\end{table}
\par 如果每個步驟不去掉非頻繁專案集,則其掃描過程的樹形結構如圖$\left(\ref{fig:Aprioir_2}\right)$所示。
\begin{figure}[!ht]
  \centering
  \includegraphics[width=0.5\textwidth]{Apriorior_2.png}
  \caption{樹形結構}
  \label{fig:Aprioir_2}
\end{figure}
\par 在其中某個過程中,可能出現非頻繁的專案集,將其去掉(用陰影表示),如圖$\left(\ref{fig:Aprioir_3}\right)$所示。
\begin{figure}[!ht]
\centering
\includegraphics[width=0.5\textwidth]{Apriorior_3.png}
\caption{非頻繁的專案集示意圖}
\label{fig:Aprioir_3}
\end{figure}
\par 上面的內容主要參考的是《Machine Learning in Action》這本書。
\section{FP Growth}
\par FP Growth\;是一種比\;Apriori\;更高效的頻繁項挖掘方法,它只需要掃描專案表2次。其中第1次掃描獲得當個專案的頻率,去掉不符合支援度要求的項,並對剩下的項排序。第2遍掃描是建立一顆\;FP-Tree(frequent-patten tree)\;。
\par 接下來的工作就是在FP-Tree上進行挖掘。
\par 比如說有如表$\left(\ref{tab:FPxiangmu}\right)$所示的表:
\begin{table}
  \centering
  \Large  %表內的字型大小
  \caption{專案表}
  \label{tab:FPxiangmu}
  \begin{tabular}{lcc}
    \hline
     TID&Items bought&(Ordered)frequent items\\
    \hline
    100&f,a,c,d,g,i,m,p&f,c,a,m,p\\
    200&a,b,c,f,l,m,o&f,c,a,b,m\\
    300&b,f,h,j,o&f,b\\
    400&b,c,k,s,p&c,b,p\\
    500&a,f,c,e,l,p,m,n&f,c,a,m,p\\
    \hline
  \end{tabular}
\end{table}
\par 它所對應的FP\_Tree如圖$\left(\ref{fig:FP_tree}\right)$所示。
\begin{figure}[!ht]
\centering
\includegraphics[width=0.7\textwidth]{FP_2.png}
\caption{FP\_tree}
\label{fig:FP_tree}
\end{figure}
\par 然後從頻率最小的單項P開始,找出P的條件模式基,用構造FP\_Tree同樣的方法來構造P的條件模式基的FP\_Tree,在這棵樹上找出包含P的頻繁項集。
\par 依次從m,b,a,c,f的條件模式基上挖掘頻繁項集,有些項需要遞迴的去挖掘,比較麻煩,比如m節點,具體的過程可以參考部落格:
\href{http://blog.sina.com.cn/s/blog_68ffc7a40100uebg.html}{Frequent Pattern 挖掘之二 FP Growth演算法},裡面講得很詳細。
\newpage
\addcontentsline{toc}{section}{參考文獻} %向目錄中新增條目,以章的名義
\nocite{ML12,ZUIJINLIN14,MASHIJULI13,JULEI13,COURSERA,MATH14,SVD12,LONGXING10,GBDT12,ANDREW,STANFU,FP11,FAN03}
\bibliographystyle{plain}
\bibliography{RefDBase}
\newpage
\addcontentsline{toc}{section}{程式設計程式碼} %向目錄中新增條目,以章的名義
\appendix
\section{程式程式碼}
\definecolor{mygreen}{rgb}{0,0.6,0}
\definecolor{mygray}{rgb}{0.5,0.5,0.5}
\definecolor{mymauve}{rgb}{0.58,0,0.82}

\lstset{ %  %breakatwhitespace=true,         % sets if automatic breaks should only happen at whitespace
  %breaklines=true,                 % sets automatic line breaking
  backgroundcolor=\color{lightgray},   % choose the background color; you must add \usepackage{color} or \usepackage{xcolor}
  basicstyle=\small,
  captionpos=t, % t(top) or b(bottom)                   % sets the caption-position to bottom
  commentstyle=\color{mygreen},    % comment style
  deletekeywords={...},            % if you want to delete keywords from the given language
  escapeinside={\%*}{*)},          % if you want to add LaTeX within your code
  extendedchars=true,              % lets you use non-ASCII characters; for 8-bits encodings only, does not work with UTF-8
  %frame=single,                    % adds a frame around the code
  keepspaces=true,                 % keeps spaces in text, useful for keeping indentation of code (possibly needs columns=flexible)
  keywordstyle=\color{blue},       % keyword style
  %language=Python,                 % the language of the code
  morekeywords={*,...},            % if you want to add more keywords to the set
  numbers=left,                    % where to put the line-numbers; possible values are (none, left, right)
  numbersep=5pt,                   % how far the line-numbers are from the code
  numberstyle=\tiny\color{mygray}, % the style that is used for the line-numbers
  rulecolor=\color{black},         % if not set, the frame-color may be changed on line-breaks within not-black text (e.g. comments (green here))
  showspaces=false,                % show spaces everywhere adding particular underscores; it overrides 'showstringspaces'
  showstringspaces=false,          % underline spaces within strings only
  showtabs=false,                  % show tabs within strings adding particular underscores
  stepnumber=1,                    % the step between two line-numbers. If it's 1, each line will be numbered
  stringstyle=\color{orange},     % string literal style
  tabsize=2,                       % sets default tabsize to 2 spaces
  %title=myPython.py                   % show the filename of files included with \lstinputlisting; also try caption instead of title
}
\subsection{氣泡排序程式碼}
\begin{lstlisting}[language={[ANSI]C},title={bubbleSort.c}]
#include <iostream>
#define LENGTH 8
using namespace std;
//測試用的程式碼,bubbleSort函式
int main() {
	int temp,number[LENGTH]={95,45,15,78,84,51,24,12};
	for(int i=0;i<LENGTH;i++)
		for(int j=0;j<LENGTH-1-i;j++)
			if(number[j]>number[j+1]) {
				temp=number[j];
				number[j]=number[j+1];
				number[j+1]=temp;
			} //if end
	for(int i=0;i<LENGTH;i++) cout<<number[i]<<" ";
	cout<<endl;
}//main end
\end{lstlisting}
\subsection{Python程式碼}
\lstinputlisting[language=Python, title=myPython.py]{myPython.py}
\end{document}