Julia 机器学习 ---- 特征提取

1、为什么要特征提取(降维)

以下是在数据集中应用降维的用处:

(1)随着数据维度不断降低,数据存储所需的空间也会随之减少。

(2)低维数据有助于减少计算/训练用时。

(3)一些算法在高维度数据上容易表现不佳,降维可提高算法可用性。

(4)降维可以用删除冗余特征解决多重共线性问题。比如我们有两个变量:“一段时间内在跑步机上的耗时”和“卡路里消耗量”。这两个变量高度相关,在跑步机上花的时间越长,燃烧的卡路里自然就越多。因此,同时存储这两个数据意义不大,只需一个就够了。

(5)降维有助于数据可视化。如前所述,如果数据维度很高,可视化会变得相当困难,而绘制二维三维数据的图表非常简单。

其实通过特征评价去掉一些不必要的特征也属于降维。

2、常用提取算法

降维方法分为线性核非线性降维,非线性降维又分为基于核函数和基于特征值的方法。

线性降维方法:PCA  ICA LDA  LFA  LPP(LE的线性表示)

基于核函数的非线性降维方法:KPCA  KICA  KDA

基于特征值的非线性降维方法(流型学习):ISOMAP  LLE  LE  LPP  LTSA  MVU
 

3、Julia中提供的代码库

MultivariateStats 是一个用于多元统计分析的Julia包。它提供了一套丰富有用的分析技术,如PCA、kernel PCA、CCA、LDA、PLS等。

ScikitLearn.jl 也提供了上面类似的降维函数,但是需要依赖Python的代码包。

 

4、特征提取函数使用说明

这里重点介绍kernel PCA使用方式

4.1、kernel PCA

MultivariateStats 中的 kernel PCA函数接口参数如下:

参数名称

参数描述

默认

kernel

核函数:它接收两个矢量 x 和 y,并返回标量值。

其他常用核函数参考:https://github.com/theogf/KernelFunctions.jl

(x,y)->x'y

solver

解算器的选择:

:eig: 实际使用 函数eigfact,是一个特征值分解函数,函数主要是给出矩阵的特征值和特征向量

:eigs: 实际使用函数eigs (总是用于稀疏数据),函数主要是通过迭代法来求解矩阵特征值和特征向量

:eig

maxoutdim

最大输出尺寸,也就是我们实际需要的维度

min(d, n)

inverse

是否对未预计算的内核执行反变换计算,如果是数据分析,可以不用的

false

β

学习反变换的岭回归的超参数

(前提是:inverse 为 true). 如果是数据分析,可以不用主要用于图像分析

1.0

tol

eigs求解器的收敛性

0.0

maxiter

eigs解算器的最大迭代次数

300

 

常用的核函数为

函数

描述

(x,y)->x'y

线性的

(x,y)->(x'y+c)^d

多项式的

(x,y)->exp(-γ*norm(x-y)^2.0)

径向基函数 (RBF)。径向基函数是一个取值仅仅依赖于离原点距离的实值函数,也就是Φ(x)=Φ(‖x‖),比如高斯函数

 

代码示例

这里提供一个较为完整的数据分析流程

 

using MultivariateStats
using DataFrames,CSV
using Statistics
using LinearAlgebra
using Plots
using Clustering
using Query
using Parsers
import Query:@from


# download("http://samplecsvs.s3.amazonaws.com/Sacramentorealestatetransactions.csv","houses.csv")
houses = DataFrame(CSV.File(joinpath(dirname(pathof(DataFrames)),"D:/houses.csv")));

#####数据清洗-特征相关性分析,这里简单过滤下。
#(1) 像street、city、zip 、latitude 和 longitude 都是地理位置信息相关的。
#  其中street、city、zip其实都太好量化,虽然zip是个数值,但是这个数值是没有
#  规律无法使用欧式距离来衡量,所以我这里选择经纬度:latitude 和 longitude
#(2) 分类问题,type字段其实是一个分类,数据被分为4类,Residential,Condo,Multi-Family,Unknown
# (3) sale_date 转成毫秒,或者 可以扩展其他的特征,比如月份 ,年份等,可能月份更好一点。可惜的是我们只有5月份的数据,索性不用了。
# unique(houses[!,:type])
# occursin("a","Condo,Residential,Multi-Family")

function newType(type::AbstractString)
    if type === "Residential"
        return 1.0
    elseif type === "Condo"
        return 2.0
    elseif type === "Multi-Family"
        return 3.0
    end
end

# function parseDate(date::String)
#     diffDate = DateTime(2000, 01, 01)
#     parseDate =Parsers.parse(DateTime, string("2008-05-",date[9:10]), Parsers.Options(dateformat="m/d/yyyy I:M:S.s p"))
#     return (parseDate-diffDate).value
# end

newHouses = @from i in houses begin
    @let newType = newType(i.type)
    # @let neSaleDate = parseDate(string(i.sale_date))
    @where i.sq__ft > 0 && (i.type ==="Residential" || i.type ==="Condo"|| i.type ==="Multi-Family" )
    @select {i.beds,i.baths,i.sq__ft,i.price,type=newType,i.latitude,i.longitude }
    @collect DataFrame
end

#### sq__ft,i.price,i.latitude,i.longitude这几个的特征值比较大,为了消除各个特征向量的差异性,对数据做标准化
#使用Z标准化,并把数据变成浮点数
mapcols(x -> x*1.0, newHouses)
function zscore(df::DataFrame)
    h_mean = map(mean,eachcol(df[!,1:end]))
    h_sdt  = map(std,eachcol(df[!,1:end]))
    h,c = size(df[!,1:end])
    for col in 1:c
        mean_v=h_mean[col]
        std_v = h_sdt[col]
        println(mean_v)
        for hex in 1:h
            @inbounds df[hex,col] = (df[hex,col]-mean_v)/std_v
        end
    end
end

zscore(newHouses)

#####现在也没有特别好的算法来判断矩阵是线性还是非线性,我这里通过图来分析是否是线性数据,
#直观上看,如果特征变量之间没有线性关系,大概率是非线性的数据,
plot(size=(500,500),leg=false)
x = newHouses[:sq__ft]
y = newHouses[:price]
scatter(x,y)

x = newHouses[:latitude]
y = newHouses[:longitude]
scatter(x,y)


#### 未降维之前 kmean 算法分析下
features = collect(Float64,Matrix(newHouses[:, 1:end])');
features
result = kmeans(features, 2)
scatter([newHouses.sq__ft], [newHouses.price], marker_z=result.assignments,
                color=:lightrainbow, legend=false)

### 核PCA降维(如果是线性数据可以使用PCA,这两种常用的降维算法,适用与不同的矩阵)
# fh = disallowmissing(newHouses)
# 核PCA适合处理非线性数据,首先需要判断数据是属于线性的还是非线性的
# 如果各个特征向量之间的差异比较大,可以先做数据的标准化。

#线性函数降维 (x,y)->x'y 也是默认的核函数
thisMtrix = Matrix{Float64}(newHouses[:,:])'
x = thisMtrix
# train a kernel PCA model
M = fit(KernelPCA, x; maxoutdim=2, inverse=true)
# apply kernel PCA model to testing set
Yte = transform(M, x)
# reconstruct testing observations (approximately)
# Xr = reconstruct(M, Yte)

result = kmeans(Yte, 3)
scatter(Yte[1,:], Yte[2,:], marker_z=result.assignments,
                color=:lightrainbow, legend=false)

f_result = fuzzy_cmeans(Yte, 3, 2, maxiter=50, display=:iter)

这里有两张图可以对降维前后数据分析效果做对比:

降维前对 sq__ft (面积),price(价格)作图分析:

降维后作图分析,明显更加直观

 

其他函数待续。。。。

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

October-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值