what/why/how

数据处理——确定模型——算法训练——预测分析

 

机器学习——线性回归

 

overfitting  过拟合

regularization   正则化

ridge regression 岭回归

 

 

有这么一个库 scikit-learn,让我们判断用哪一个模型

 

python机器学习

1、KNN

  从训练集中找到和新数据最接近的k条记录

  根据他们的主要分类来决定新数据的类别

 

  要点:

    1.如何判断他们最接近,怎么决定他们的距离(非常决定性能的因素)

    2.按照k个里最邻近的那个还是类别最多的那个还是权重加权的?

 

  例子:手写识别:MNIST train.csv

    0:label(数字具体是什么)

    1-784pixels(灰度值)

  方法:余弦定理——判断他们之间的相似度。

           两个向量,当两个向量夹角比较小的时候,会比较相似,夹角比较大的时候,不相似。

 

python机器学习

 

 

 

# -*- coding: utf-8 -*-
# CopyRight by heibanke

import pandas as pd
import numpy as np
import time

def normalize(x):
    """
    linalg.norm(x), return sum(abs(xi)**2)**0.5
    apply_along_axis(func, axis, x),
    """
    #归一化——公式的被除数
    norms = np.apply_along_axis(np.linalg.norm, 1, x) + 1.0e-7
    return x / np.expand_dims(norms, -1)


#作者自己想到的一个归一化的方法
def normalize2(x):
    """
    linalg.norm(x), return sum(abs(xi)**2)**0.5
    apply_along_axis(func, axis, x),
    """
    norms = np.apply_along_axis(np.mean, 1, x) + 1.0e-7
    return x - np.expand_dims(norms, -1)

    
def nearest_neighbor(norm_func,train_x, train_y, test_x):
    train_x = norm_func(train_x)
    test_x = norm_func(test_x)
    
    # cosine
    #test_x就是测试数据,train_x是训练数据,分别相当于j,i
    corr = np.dot(test_x, np.transpose(train_x))
    argmax = np.argmax(corr, axis=1)
    #然后找一个最大值作为预测值
    preds = train_y[argmax]


    #上边如果采用for循环的形式会更好看一些,但是运行速度会慢一些。
    #采用矩阵的形式会快
    return preds

def validate(preds, test_y):
    count = len(preds)
    #对所有正确的进行sum()求和
    correct = (preds == test_y).sum()
    #然后对争取的的总和除以数据总和
    return float(correct) / count

if __name__=='__main__':
    TRAIN_NUM = 22
    TEST_NUM = 42
    # Read data 42000
    data = pd.read_csv('train.csv')
    train_data = data.values[0:TRAIN_NUM,1:]
    train_label = data.values[0:TRAIN_NUM,0]
    test_data = data.values[TRAIN_NUM:TEST_NUM,1:]
    test_label = data.values[TRAIN_NUM:TEST_NUM,0]
    #这里采用三种方式,一种是公式型的归一化,第二种是减去均值的归一化,第三种没有归一化,直接就是两个向量相关
    norm_funcs = [normalize,normalize2,lambda x:x]
    for norm_f in norm_funcs:
        t = time.time()
        
        preds = nearest_neighbor(norm_f,train_data, train_label, test_data)
        #acc求出来的就是准确率
        acc = validate(preds, test_label)
        print("%s Validation Accuracy: %f, %.2fs" % (norm_f.__name__,acc, time.time() - t))

    我们把TRAIN_NUM = 22

          TEST_NUM = 422200,4200,22042022,42进行设置处理

 

      python机器学习

 

    可见数据量越大,准确率就会越高。

    现在我们用scikit learn的一个库来实现一下。

import pandas as pd
from sklearn.decomposition import PCA
from sklearn.neighbors import KNeighborsClassifier
from sklearn import svm
import time



if __name__=='__main__':
    # maximum num is 42000
    TRAIN_NUM = 22000
    TEST_NUM = 42000
    """
    train_data:  训练数据
    train_label: 训练数据的正确输出
    test_data:   测试数据
    test_label:  测试数据的正确输出
    """
    data = pd.read_csv('train.csv')
    train_data = data.values[0:TRAIN_NUM,1:]
    train_label = data.values[0:TRAIN_NUM,0]
    test_data = data.values[TRAIN_NUM:TEST_NUM,1:]
    test_label = data.values[TRAIN_NUM:TEST_NUM,0]


    
    t = time.time()
    # PCA, principal components analysis
    # http://blog.jobbole.com/86905/
    # http://ufldl.stanford.edu/wiki/index.php/%E4%B8%BB%E6%88%90%E5%88%86%E5%88%86%E6%9E%90


    #pca是取协方差的特征值和特征向量,取协方差的一些值作为坐标轴然后去映射
    #计算量比较大
    #思想:把主要成分作为分析依据,不重要的部分作为噪声去除掉

    #如果n_components大于零的整数,则取这么多的特征
    #如果是分数,则自动选择,按照比例选择
    pca = PCA(n_components=0.8)
    train_x = pca.fit_transform(train_data)
    test_x = pca.transform(test_data)

    #knn regression
    #knn回归,我们取k为4,可能说做一个加权,详细还是要看源代码
    neighbor = KNeighborsClassifier(n_neighbors=4)

    #fit是对模型一个训练,训练好的模型就可以直接用了
    neighbor.fit(train_x, train_label)
    #预测
    preds = neighbor.predict(test_x)
    #求准确率
    acc = float((preds == test_label).sum())/len(test_x)
    print("KNN Validation Accuracy: %f, %.2fs" % (acc, time.time() - t))

    # 22000, 96.7%
    


    #svm(Support Vector Machine) regression
    # 统计学习方法
    # PRML

    t = time.time()

    #加了一个白话处理,如果不加的话,svm会差一下,目的是让处理后的数据方差都一致
    pca = PCA(n_components=0.8,whiten=True)
    train_x = pca.fit_transform(train_data)
    test_x = pca.transform(test_data)


    #初始化,kernel核方法,C是惩罚因子
    svc = svm.SVC(kernel='rbf',C=10)
    svc.fit(train_x, train_label)
    preds = svc.predict(test_x)    
    
    acc = float((preds == test_label).sum())/len(test_x)
    print("SVM Validation Accuracy: %f, %.2fs" % (acc, time.time() - t))

    # 22000, 97.8%

    python机器学习

  距离依据很重要。

 

二、非监督学习之k-means

  1、选择k个点作为初始中心

  2、将每个点指派到最近的中心,形成k个簇cluster

  3、重新计算每个簇的中心

  4、如果簇中心发生明显变化或未达到最大迭代次数,则回到step2

 

 

  问题:初始点不对的时候,容易收敛到局部最优值

 

  解决办法:

 

    1、选择k个点作为初始中心——canopy,模拟退火,贝叶斯准则

 

    2、将每个点指派到最近的中心,形成k个簇cluster

 

    3、重新计算每个簇的中心

 

    4、如果簇中心发生了明显的变化或未达到最大迭代次数,则回到step2

 

  例子:给你一幅图像,找出其中最主要的三种颜色,并将图片用三种最主要的颜色表示出来

 

# -*- coding: utf-8 -*-
# https://github.com/ZeevG/python-dominant-image-colour
# commented by heibanke

from PIL import Image
import random
import numpy

class Cluster(object):
    """
    pixels: 主要颜色所依据的像素点
    centroid: 主要颜色的RGB值
    """
    def __init__(self):
        self.pixels = []
        self.centroid = None

    def addPoint(self, pixel):
        self.pixels.append(pixel)

    def setNewCentroid(self):
        """
        通过pixels均值重新计算主要颜色
        """
        R = [colour[0] for colour in self.pixels]
        G = [colour[1] for colour in self.pixels]
        B = [colour[2] for colour in self.pixels]

        R = sum(R) / len(R)
        G = sum(G) / len(G)
        B = sum(B) / len(B)

        self.centroid = (R, G, B)
        self.pixels = []

        return self.centroid


class Kmeans(object):

    def __init__(self, k=3, max_iterations=5, min_distance=5.0, size=400):
        """
        k: 主要颜色的分类个数
        max_iterations: 最大迭代次数
        min_distance: 当新的颜色和老颜色的距离小于该最小距离时,提前终止迭代
        size: 用于计算的图像大小
        """
        self.k = k
        self.max_iterations = max_iterations
        self.min_distance = min_distance
        self.size = (size, size)

    def run(self, image):
        self.image = image
        #生成缩略图,节省运算量
        self.image.thumbnail(self.size)
        self.pixels = numpy.array(image.getdata(), dtype=numpy.uint8)
        self.clusters = [None]*self.k
        self.oldClusters = None
        #在图像中随机选择k个像素作为初始主要颜色
        randomPixels = random.sample(self.pixels, self.k)

        for idx in range(self.k):
            self.clusters[idx] = Cluster()
            self.clusters[idx].centroid = randomPixels[idx]

        iterations = 0

        #开始迭代
        while self.shouldExit(iterations) is False:
            self.oldClusters = [cluster.centroid for cluster in self.clusters]
            print iterations

            #对pixel和self.clusters中的主要颜色分别计算距离,将pixel加入到离它最近的主要颜色所在的cluster中
            for pixel in self.pixels:
                self.assignClusters(pixel)
            #对每个cluster中的pixels,重新计算新的主要颜色
            for cluster in self.clusters:
                cluster.setNewCentroid()

            iterations += 1

        return [cluster.centroid for cluster in self.clusters]

    def assignClusters(self, pixel):
        shortest = float('Inf')
        for cluster in self.clusters:
            distance = self.calcDistance(cluster.centroid, pixel)
            if distance < shortest:
                shortest = distance
                nearest = cluster
        nearest.addPoint(pixel)

    def calcDistance(self, a, b):
        result = numpy.sqrt(sum((a - b) ** 2))
        return result

    def shouldExit(self, iterations):

        if self.oldClusters is None:
            return False
        #计算新的中心和老的中心之间的距离
        for idx in range(self.k):
            dist = self.calcDistance(
                numpy.array(self.clusters[idx].centroid),
                numpy.array(self.oldClusters[idx])
            )
            if dist < self.min_distance:
                return True

        if iterations <= self.max_iterations:
            return False

        return True

    # The remaining methods are used for debugging
    def showImage(self):
        """
        显示原始图像
        """
        self.image.show()

    def showCentroidColours(self):
        """
        显示主要颜色
        """
        for cluster in self.clusters:
            image = Image.new("RGB", (200, 200), cluster.centroid)
            image.show()

    def showClustering(self):
        """
        将原始图像的像素完全替换为主要颜色后的效果
        """
        localPixels = [None] * len(self.image.getdata())

        for idx, pixel in enumerate(self.pixels):
                shortest = float('Inf')
                for cluster in self.clusters:
                    distance = self.calcDistance(
                        cluster.centroid,
                        pixel
                    )
                    if distance < shortest:
                        shortest = distance
                        nearest = cluster

                localPixels[idx] = nearest.centroid

        w, h = self.image.size
        localPixels = numpy.asarray(localPixels)\
            .astype('uint8')\
            .reshape((h, w, 3))

        colourMap = Image.fromarray(localPixels)
        return colourMap
    
if __name__=="__main__":
    from PIL import Image
    import os
    
    k_image=Kmeans(k=3) #默认参数
    path = './pics/'
    fp = open('file_color.txt','w')
    for filename in os.listdir(path):
        print path+filename
        try:
            color = k_image.run(Image.open(path+filename))
            
            #把图像用三种主要颜色显示出来
            w_image = k_image.showClustering()
            w_image.save(path+'mean_'+filename,'jpeg')
            fp.write('The color of '+filename+' is '+str(color)+'\n')
        except:
            print "This file format is not support"
    fp.close()

  处理前的图片:

  python机器学习

 

 

  处理后的图片:

  python机器学习

 

相关文章:

  • 2021-11-09
  • 2021-12-25
  • 2021-07-06
  • 2021-06-21
  • 2022-01-02
  • 2021-10-23
  • 2021-08-01
猜你喜欢
  • 2022-12-23
  • 2021-08-18
  • 2021-06-06
  • 2022-01-07
  • 2021-04-30
相关资源
相似解决方案