背景介绍 

        机器学习是一种人工智能的分支,它利用统计学计算机科学的方法,让计算机系统通过经验自动改善和学习。机器学习的目标是通过数据分析和模式识别来构建算法和模型,从而让计算机能够自动进行决策和预测。常见的机器学习算法包括:

1.监督学习(Supervised Learning):监督学习是一种通过给定的输入和输出数据来训练模型的方法。该模型可以根据输入数据预测输出值。常见的监督学习算法有线性回归、逻辑回归、决策树、支持向量机和神经网络

2.无监督学习(Unsupervised Learning):无监督学习是一种从无标签数据中发现隐藏模式和结构的方法。该模型可以通过数据的统计特性来进行聚类、降维和关联规则挖掘。常见的无监督学习算法有聚类算法(如K均值聚类和层次聚类)和关联规则挖掘算法(如Apriori算法)

3.强化学习(Reinforcement Learning):强化学习是一种通过试错学习和反馈机制来训练模型的方法。该模型可以在环境中采取行动,并通过观察环境的反馈来调整策略,以最大化预期的奖励。常见的强化学习算法有Q学习和深度强化学习(如深度Q网络)

4.深度学习(Deep Learning):深度学习是一种基于神经网络的机器学习方法。它通过多层的神经网络模型来学习和提取数据的高级特征表示。深度学习在图像识别、语音处理和自然语言处理等领域取得了很大的成功。常见的深度学习算法有卷积神经网络(CNN)和循环神经网络(RNN)。

        这些算法在不同的问题和应用中都有各自的优缺点,选择适合的算法取决于数据的特征、目标任务和可用的资源。机器学习的发展使得计算机系统具备了自动学习和智能决策的能力,推动了人工智能的发展和应用。本博文主要介绍一些机器学习算法的代码实现,具体的原理可以去参考别的资料和博文,主要使用机器学习库scikit-learn来实现。

环境说明

windows10企业版+python3.6.8

scikit-learn==0.20.4

线性回归算法

from sklearn import linear_model, datasets
# 下载数据集
digits = datasets.load_digits()
# 创建线性回归模型
clf = linear_model.LinearRegression()
# 设定训练集
x, y = digits.data[:-1], digits.target[:-1]
# 训练模型
clf.fit(x, y)
# 模型预测
y_pred = clf.predict([digits.data[-1]])
y_true = digits.target[-1]
# 输出结果
print('模型预测值为:', y_pred)
print('样本实际值为:', y_true)

提醒:可以在安装sklearn的路径下查看该工具包自带的数据集,如下:

 支持向量机算法

from sklearn import svm, datasets
# 下载数据集
digits = datasets.load_digits()
# 创建SVM模型
clf = svm.SVC(gamma=0.001, C=100)
# 设定训练集
x, y = digits.data[:-1], digits.target[:-1]
# 训练模型
clf.fit(x, y)
# 模型预测
y_pred = clf.predict([digits.data[-1]])
y_true = digits.target[-1]
# 输出结果
print('模型预测值为:', y_pred[0])
print('样本实际值为:', y_true)

 最近邻算法

from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
# 下载数据集
digits = datasets.load_digits()
# 创建SVM模型
clf = KNeighborsClassifier(n_neighbors=6)
# 设定训练集
x, y = digits.data[:-1], digits.target[:-1]
# 训练模型
clf.fit(x, y)
# 模型预测
y_pred = clf.predict([digits.data[-1]])
y_true = digits.target[-1]
# 输出结果
print('模型预测值为:', y_pred[0])
print('样本实际值为:', y_true)

 逻辑回归算法

from sklearn import datasets
from sklearn.linear_model import LogisticRegression
import warnings
warnings.filterwarnings("ignore")
# 下载数据集
digits = datasets.load_digits()
# 创建SVM模型
#clf = LogisticRegression(solver="liblinear", C=1e5)
clf = LogisticRegression(solver='lbfgs')
# 设定训练集
x, y = digits.data[:-1], digits.target[:-1]
# 训练模型
model = clf.fit(x, y)
train_accuracy = model.score(x, y)
# 模型预测
y_pred = clf.predict([digits.data[-1]])
y_true = digits.target[-1]
# 输出结果
print('train_accuracy:{:.3f}'.format(train_accuracy))
print('模型预测值为:', y_pred[0])
print('样本实际值为:', y_true)

 决策树算法

代码实现1:

from sklearn import tree
#特征數據,[身高,鬍鬚] 1-有,0-無
feature = [[178, 1], [155, 0], [180, 1], [164, 0], [168, 1], [152, 0]]
#特征標籤值
label = ['male', 'female', 'male', 'female', 'male', 'female']

def decision_tree_classifier():
    #創建分类器
    clf = tree.DecisionTreeClassifier()
    # 模型训练
    clf = clf.fit(feature, label)
    #預測
    r1 = clf.predict([[158, 0]])
    print('Data[158,0] is label for:', r1)

    r2 = clf.predict([[190, 1]])
    print('Data[190,1] is label for:', r2)

if __name__ == '__main__':
    decision_tree_classifier()

结果如下:

代码实现2: 

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier

# Parameters
n_classes = 3
plot_colors = "bry"
plot_step = 0.02

# Load data
iris = load_iris()

for pairidx, pair in enumerate([[0, 1], [0, 2], [0, 3],
                                [1, 2], [1, 3], [2, 3]]):
    # We only take the two corresponding features
    X = iris.data[:, pair]
    y = iris.target

    # Train
    clf = DecisionTreeClassifier().fit(X, y)

    # Plot the decision boundary
    plt.subplot(2, 3, pairidx + 1)

    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, plot_step),
                         np.arange(y_min, y_max, plot_step))

    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    cs = plt.contourf(xx, yy, Z, cmap=plt.cm.Paired)

    plt.xlabel(iris.feature_names[pair[0]])
    plt.ylabel(iris.feature_names[pair[1]])
    plt.axis("tight")

    # Plot the training points
    for i, color in zip(range(n_classes), plot_colors):
        idx = np.where(y == i)
        plt.scatter(X[idx, 0], X[idx, 1], c=color, label=iris.target_names[i],
                    cmap=plt.cm.Paired)

    plt.axis("tight")

plt.suptitle("Decision surface of a decision tree using paired features")
plt.legend()
plt.show()

K均值算法 

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
#样本500个,特征2个,分4类
X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=15)
plt.scatter(X[:, 0], X[:, 1], color="blue")
plt.show()

colors = ["red", "blue", "green", "yellow"]
for i in range(4):
    plt.scatter(X[y == i, 0], X[y == i, 1], color=colors[i])
plt.show()


#基于这个分布,我们使用KMeans来进行聚类,慢慢猜测有多少个簇
from sklearn.cluster import KMeans
n_cluster = 3
#参数n_clusters指定生成的类簇的个数 。 fit进行拟合,此时已经完成了聚类
kmeans = KMeans(n_clusters=n_cluster,random_state=10).fit(X)#
y_pre = kmeans.labels_ #查看500个数据对应的标签,只有0,1,2三种
y_pre

centers = kmeans.cluster_centers_#获得质心,== n_cluster
centers
colors = ["red","blue","green","yellow"]
for i in range(n_cluster):
    plt.scatter(X[y_pre == i,0],X[y_pre == i,1],color=colors[i])
plt.scatter(centers[:,0],centers[:,1],color="black")
plt.show()

 

层次聚类算法 

'''
@author: MZL
@summary: 无监督聚类学习-层次聚类(hierarchical clustering),自下向上的凝聚和自顶向下的分裂两种方法。
'''
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial.distance import pdist,squareform
from scipy.cluster.hierarchy import linkage
from scipy.cluster.hierarchy import dendrogram
from sklearn.cluster import AgglomerativeClustering
np.random.seed(123)
variables = ['X','Y','Z']
labels=['ID_0','ID_1','ID_2','ID_3','ID_4']
X=np.random.random_sample([5,3])*10
#层次聚类树
df = pd.DataFrame(X,columns=variables,index=labels)
print (df)
#计算距离关联矩阵,两两样本间的欧式距离
#row_dist = pd.DataFrame(squareform(pdist(df,metric='euclidean')),columns=labels,index=labels)
#print (row_dist)
#print (help(linkage))
row_clusters = linkage(pdist(df,metric='euclidean'),method='complete')#使用抽秘籍距离矩阵
#row_clusters = linkage(df.values,method='complete',metric='euclidean')
print (pd.DataFrame(row_clusters,columns=['row label1','row label2','distance','no. of items in clust.'],index=['cluster %d'%(i+1) for i in range(row_clusters.shape[0])]))
#层次聚类树
row_dendr = dendrogram(row_clusters,labels=labels)
plt.tight_layout()
plt.ylabel('Euclidean distance')
plt.show()
#层次聚类热度图
fig =plt.figure(figsize=(8,8))
axd =fig.add_axes([0.09,0.1,0.2,0.6])
row_dendr = dendrogram(row_clusters,orientation='right')
df_rowclust = df.ix[row_dendr['leaves'][::-1]]
axm = fig.add_axes([0.23,0.1,0.6,0.6])
cax = axm.matshow(df_rowclust,interpolation='nearest',cmap='hot_r')
axd.set_xticks([])
axd.set_yticks([])
for i in axd.spines.values():
    i.set_visible(False)
fig.colorbar(cax)
axm.set_xticklabels(['']+list(df_rowclust.columns))
axm.set_yticklabels(['']+list(df_rowclust.index))
plt.show()
 
#凝聚层次聚类,应用对层次聚类树剪枝
ac=AgglomerativeClustering(n_clusters=2,affinity='euclidean',linkage='complete')
labels = ac.fit_predict(X)
print ('cluster labels:%s'%labels)

 

自构建数据集实现层次聚类算法

# coding: utf-8
# 层次聚类
'https://zhuanlan.zhihu.com/p/32438294'
import math
import numpy as np
from sklearn import datasets
from sklearn import cluster

def euler_distance(point1: np.ndarray, point2: list) -> float:
    """
    计算两点之间的欧拉距离,支持多维
    """
    distance = 0.0
    for a, b in zip(point1, point2):
        distance += math.pow(a - b, 2)
    return math.sqrt(distance)

class ClusterNode(object):
    def __init__(self, vec, left=None, right=None, distance=-1, id=None, count=1):
        """
        :param vec: 保存两个数据聚类后形成新的中心
        :param left: 左节点
        :param right:  右节点
        :param distance: 两个节点的距离
        :param id: 用来标记哪些节点是计算过的
        :param count: 这个节点的叶子节点个数
        """
        self.vec = vec
        self.left = left
        self.right = right
        self.distance = distance
        self.id = id
        self.count = count

class Hierarchical(object):
    def __init__(self, k = 1):
        assert k > 0
        self.k = k
        self.labels = None
    def fit(self, x):
        nodes = [ClusterNode(vec=v, id=i) for i,v in enumerate(x)]
        distances = {}
        point_num, future_num = np.shape(x)  # 特征的维度
        self.labels = [ -1 ] * point_num
        currentclustid = -1
        while len(nodes) > self.k:
            min_dist = math.inf
            nodes_len = len(nodes)
            closest_part = None  # 表示最相似的两个聚类
            for i in range(nodes_len - 1):
                for j in range(i + 1, nodes_len):
                    # 为了不重复计算距离,保存在字典内
                    d_key = (nodes[i].id, nodes[j].id)
                    if d_key not in distances:
                        distances[d_key] = euler_distance(nodes[i].vec, nodes[j].vec)
                    d = distances[d_key]
                    if d < min_dist:
                        min_dist = d
                        closest_part = (i, j)
            # 合并两个聚类
            part1, part2 = closest_part
            node1, node2 = nodes[part1], nodes[part2]
            new_vec = [ (node1.vec[i] * node1.count + node2.vec[i] * node2.count ) / (node1.count + node2.count)
                        for i in range(future_num)]
            new_node = ClusterNode(vec=new_vec,
                                   left=node1,
                                   right=node2,
                                   distance=min_dist,
                                   id=currentclustid,
                                   count=node1.count + node2.count)
            currentclustid -= 1
            del nodes[part2], nodes[part1]   # 一定要先del索引较大的
            nodes.append(new_node)
        self.nodes = nodes
        self.calc_label()

    def calc_label(self):
        """
        调取聚类的结果
        """
        for i, node in enumerate(self.nodes):
            # 将节点的所有叶子节点都分类
            self.leaf_traversal(node, i)

    def leaf_traversal(self, node: ClusterNode, label):
        """
        递归遍历叶子节点
        """
        if node.left == None and node.right == None:
            self.labels[node.id] = label
        if node.left:
            self.leaf_traversal(node.left, label)
        if node.right:
            self.leaf_traversal(node.right, label)



iris = datasets.load_iris()
print('使用自编写的层次聚类:')
my = Hierarchical(4)
my.fit(iris.data)
print(np.array(my.labels))
print('\n')
print('使用sklearn的层次聚类:')
# 使用sklearn算法库中的层次聚类
sk = cluster.AgglomerativeClustering(4)
sk.fit(iris.data)
print(sk.labels_)

基于密度的聚类算法(DBSCAN) 

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.cluster import DBSCAN

#matplotlib inline
X1, y1=datasets.make_circles(n_samples=5000, factor=.6,
                                      noise=.05)
X2, y2 = datasets.make_blobs(n_samples=1000, n_features=2, centers=[[1.2,1.2]], cluster_std=[[.1]],
               random_state=9)

X = np.concatenate((X1, X2))
#展示样本数据分布
plt.scatter(X[:, 0], X[:, 1], marker='o')
plt.show()
#eps和min_samples 需要进行调参
y_pred = DBSCAN(eps = 0.1, min_samples = 10).fit_predict(X)
#分类结果
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

人工神经网络算法 

import numpy as np
import matplotlib.pyplot as plt
import math

a = np.array([0.05, 0.1])  # a1,a2的输入值
weight1 = np.array([[0.15, 0.25], [0.2, 0.3]])  # a1对b1,b2的权重,a2对b1,b2的权重
weight2 = np.array([[0.4, 0.5], [0.45, 0.55]])  # b1对c1,c2的权重,b2对c1,c2的权重
target = np.array([0.01, 0.99])
d1 = 0.35  # 输入层的偏置(1)的权重
d2 = 0.6  # 隐藏层的偏置(1)的权重
β = 0.5  # 学习效率

# 一:前向传播

# 计算输入层到隐藏层的输入值,得矩阵netb1,netb2
netb = np.dot(a, weight1) + d1

# 计算隐藏层的输出值,得到矩阵outb1,outb2
m = []
for i in range(len(netb)):
    outb = 1.0 / (1.0 + math.exp(-netb[i]))
    m.append(outb)
m = np.array(m)

# 计算隐藏层到输出层的输入值,得矩阵netc1,netc2
netc = np.dot(m, weight2) + d2

# 计算隐藏层的输出值,得到矩阵outc1,outc2
n = []
for i in range(len(netc)):
    outc = 1.0 / (1.0 + math.exp(-netc[i]))
    n.append(outc)
n = np.array(n)

# 二:反向传播
count = 0  # 计数
e = 0  # 误差
E = []  # 统计误差
# 梯度下降
while True:
    count += 1

    # 总误差对w1-w4的偏导
    pd1 = (
          -(target[0] - n[0]) * n[0] * (1 - n[0]) * weight2[0][0] - (target[1] - n[1]) * n[1] * (1 - n[1]) * weight2[0][
              1]) * m[0] * (1 - m[0]) * a[0]
    pd2 = (
          -(target[0] - n[0]) * n[0] * (1 - n[0]) * weight2[0][0] - (target[1] - n[1]) * n[1] * (1 - n[1]) * weight2[0][
              1]) * m[0] * (1 - m[0]) * a[1]
    pd3 = (
          -(target[0] - n[0]) * n[0] * (1 - n[0]) * weight2[1][0] - (target[1] - n[1]) * n[1] * (1 - n[1]) * weight2[0][
              1]) * m[0] * (1 - m[0]) * a[0]
    pd4 = (
          -(target[0] - n[0]) * n[0] * (1 - n[0]) * weight2[1][1] - (target[1] - n[1]) * n[1] * (1 - n[1]) * weight2[0][
              1]) * m[0] * (1 - m[0]) * a[1]
    weight1[0][0] = weight1[0][0] - β * pd1
    weight1[1][0] = weight1[1][0] - β * pd2
    weight1[0][1] = weight1[0][1] - β * pd3
    weight1[1][1] = weight1[1][1] - β * pd4

    # 总误差对w5-w8的偏导
    pd5 = -(target[0] - n[0]) * n[0] * (1 - n[0]) * m[0]
    pd6 = -(target[0] - n[0]) * n[0] * (1 - n[0]) * m[1]
    pd7 = -(target[1] - n[1]) * n[1] * (1 - n[1]) * m[0]
    pd8 = -(target[1] - n[1]) * n[1] * (1 - n[1]) * m[1]
    weight2[0][0] = weight2[0][0] - β * pd5
    weight2[1][0] = weight2[1][0] - β * pd6
    weight2[0][1] = weight2[0][1] - β * pd7
    weight2[1][1] = weight2[1][1] - β * pd8

    netb = np.dot(a, weight1) + d1
    m = []
    for i in range(len(netb)):
        outb = 1.0 / (1.0 + math.exp(-netb[i]))
        m.append(outb)
    m = np.array(m)
    netc = np.dot(m, weight2) + d2
    n = []
    for i in range(len(netc)):
        outc = 1.0 / (1.0 + math.exp(-netc[i]))
        n.append(outc)
    n = np.array(n)

    # 计算总误差
    for j in range(len(n)):
        e += (target[j] - n[j]) ** 2 / 2
    E.append(e)
    # 判断
    if e < 0.0000001:
        break
    else:
        e = 0
print(count)
print(e)
print(n)
plt.plot(range(len(E)), E, label='error')
import numpy as np
import matplotlib.pyplot as plt
import math
a=np.array([0.05,0.1])           #a1,a2的输入值
weight1=np.array([[0.15,0.25],[0.2,0.3]])   #a1对b1,b2的权重,a2对b1,b2的权重
weight2=np.array([[0.4,0.5],[0.45,0.55]])     #b1对c1,c2的权重,b2对c1,c2的权重
target=np.array([0.01,0.99])
d1=0.35   #输入层的偏置(1)的权重
d2=0.6    #隐藏层的偏置(1)的权重
β=0.5    #学习效率

#一:前向传播

#计算输入层到隐藏层的输入值,得矩阵netb1,netb2
netb=np.dot(a,weight1)+d1

#计算隐藏层的输出值,得到矩阵outb1,outb2
m=[]
for i in range(len(netb)):
    outb=1.0 / (1.0 + math.exp(-netb[i]))
    m.append(outb)
m=np.array(m)

#计算隐藏层到输出层的输入值,得矩阵netc1,netc2
netc=np.dot(m,weight2)+d2

#计算隐藏层的输出值,得到矩阵outc1,outc2
n=[]
for i in range(len(netc)):
    outc=1.0 / (1.0 + math.exp(-netc[i]))
    n.append(outc)
n=np.array(n)

#二:反向传播
count=0 #计数
e=0     #误差
E=[]    #统计误差
#梯度下降
while True:
  count+=1

  #总误差对w1-w4的偏导
  pd1=(-(target[0]-n[0])*n[0]*(1-n[0])*weight2[0][0]-(target[1]-n[1])*n[1]*(1-n[1])*weight2[0][1])*m[0]*(1-m[0])*a[0]
  pd2=(-(target[0]-n[0])*n[0]*(1-n[0])*weight2[0][0]-(target[1]-n[1])*n[1]*(1-n[1])*weight2[0][1])*m[0]*(1-m[0])*a[1]
  pd3=(-(target[0]-n[0])*n[0]*(1-n[0])*weight2[1][0]-(target[1]-n[1])*n[1]*(1-n[1])*weight2[0][1])*m[0]*(1-m[0])*a[0]
  pd4=(-(target[0]-n[0])*n[0]*(1-n[0])*weight2[1][1]-(target[1]-n[1])*n[1]*(1-n[1])*weight2[0][1])*m[0]*(1-m[0])*a[1]
  weight1[0][0]=weight1[0][0]-β*pd1
  weight1[1][0]=weight1[1][0]-β*pd2
  weight1[0][1]=weight1[0][1]-β*pd3
  weight1[1][1]=weight1[1][1]-β*pd4

  #总误差对w5-w8的偏导
  pd5=-(target[0]-n[0])*n[0]*(1-n[0])*m[0]
  pd6=-(target[0]-n[0])*n[0]*(1-n[0])*m[1]
  pd7=-(target[1]-n[1])*n[1]*(1-n[1])*m[0]
  pd8=-(target[1]-n[1])*n[1]*(1-n[1])*m[1]
  weight2[0][0]=weight2[0][0]-β*pd5
  weight2[1][0]=weight2[1][0]-β*pd6
  weight2[0][1]=weight2[0][1]-β*pd7
  weight2[1][1]=weight2[1][1]-β*pd8

  netb=np.dot(a,weight1)+d1
  m=[]
  for i in range(len(netb)):
    outb=1.0 / (1.0 + math.exp(-netb[i]))
    m.append(outb)
  m=np.array(m)
  netc=np.dot(m,weight2)+d2
  n=[]
  for i in range(len(netc)):
    outc=1.0 / (1.0 + math.exp(-netc[i]))
    n.append(outc)
  n=np.array(n)

  #计算总误差
  for j in range(len(n)):
    e += (target[j]-n[j])**2/2
  E.append(e)
  #判断
  if e<0.0000001:
    break
  else:
      e=0
print(count)
print(e)
print(n)
plt.plot(range(len(E)),E,label='error')
plt.legend()
plt.xlabel('time')
plt.ylabel('error')
plt.show()
plt.legend()
plt.xlabel('time')
plt.ylabel('error')
plt.show()

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐