Spark数据挖掘-深入GraphX(1)

Spark数据挖掘-深入GraphX(1)

1 网络数据集

当图被用来描述系统中的组件之间的交互关系的时候,图可以被用来表示任何系统。图原理提供了通用的语言和一系列工具来表示和分析复杂的系统。简单的说:图由一系列顶点和边组成,每条边连接两个顶点表示这两个顶点之间的某种关系。下面介绍一下本文将会演示的几个有趣的图将要用到的数据:

图名字数据集地址下载文件名描述
邮件交流网络图https://snap.stanford.edu/data/email-Enron.htmlemail-Enron.txt.gzEnron公司158名雇员的电子邮件往来数据构成一个邮件交流网络有向图
食品品味网络图http://yongyeol.com/2011/12/15/paper-flavor-network.htmlingr_comp.zip通过三个食品网站获取得到的每个食品组成成分和每个成分对应的化学合成物构成一个网络
个人社交网络图http://snap.stanford.edu/data/egonets-Gplus.htmlgplus.tar.gz数据中的用户圈子组成一个个人社交网络,数据集还包括个人属性信息

2 GraphX 图形创建方式

在GraphX里面有四种创建一个属性图的方法。每种构建图的方法对数据都有一定的格式要求。下面一一分析。

2.1 利用 Object Graph 的工厂方法创建

Object Graph 是 Class Graph 的伴生对象,它定义了创建 Graph 对象的 apply 方法定义如下:

def apply[VD, ED](
  vertices: RDD[(VertexId, VD)],
  edges: RDD[Edge[ED]],
  defaultVertexAttr: VD = null
  ): Graph[VD, ED]

此方法通过传入顶点:RDD[(VertexId,VD)]和边:RDD[Edge[ED]] 就可以创建一个图。注意参数: defaultVertexAttr 是用来设置那些边中的顶点不在传入的顶点集合当中的顶点的默认属性,所以这个值的类型必须是和传入顶点的属性的类型一样。

2.2 利用 edgeListFile 创建

一个非常常见的场景是:你数据集里的数据表示的是顶点与顶点的关系即只表示边。这种情况下Graphx提供了GraphLoader.edgeListFile函数来自动生成图,函数的定义如下:

def edgeListFile(
  sc: SparkContext,
  path: String,
  canonicalOrientation: Boolean = false,
  numEdgePartitions: Int = -1)
  : Graph[Int, Int]

sc、path 这两个参数不用多说,需要注意的参数解析如下:

  • path 指向包含边的文件或文件夹 要求:文件每一行用两个按照多个空格分割的正整数表示的边,如: scrId dstId,Spark 读取的时候会忽略# 开头的行
  • canonicalOrientation 表示图是否有方向 如果值为true,那么只会加载 srcId > dstId 的边,否则全部加载
  • 加载完所有边之后,自动按照边生成顶点,默认的每个顶点的属性是1
  • numEdgePartitions 边分区个数默认是按照文件分区来划分的,也可以指定

下面看一下关键源码:

val edges = lines.mapPartitionsWithIndex { (pid, iter) =>
  val builder = new EdgePartitionBuilder[Int, Int]
  iter.foreach { line =>
    if (!line.isEmpty && line(0) != '#') {
      val lineArray = line.split("\\s+")
      if (lineArray.length < 2) {
        throw new IllegalArgumentException("Invalid line: " + line)
      }
      val srcId = lineArray(0).toLong
      val dstId = lineArray(1).toLong
      if (canonicalOrientation && srcId > dstId) {
        builder.add(dstId, srcId, 1)
      } else {
        builder.add(srcId, dstId, 1)
      }
    }
  }
}

2.3 利用 fromEdges 创建

这个方法可以理解为edgeListFile方法内部就是调用这个方法。原理就是只根据边: RDD[Edge[ED]] 来生成图,顶点就是由所有构成边的顶点组成,顶点的默认属性用户可以指定,定义如下:

def fromEdges[VD: ClassTag, ED: ClassTag](
    edges: RDD[Edge[ED]],
    defaultValue: VD): Graph[VD, ED]

2.4 利用 fromEdgeTuples 创建

这个方法也可以理解为edgeListFile方法内部就是调用这个方法。原理就是只根据边: RDD[(VertexId, VertexId)] 来生成图,连边的属性都不知道,默认边的属性当然可以设置,顶点就是由所有构成边的顶点组成,顶点的默认属性用户可以指定,定义如下:

def fromEdgeTuples[VD](
  rawEdges: RDD[(VertexId, VertexId)],
  defaultValue: VD,
  uniqueEdges: Option[PartitionStrategy] = None)
  : Graph[VD, Int]

其实后面三种方式都是不明确指定顶点,而是通过边来推导出顶点,这非常适合无属性图,比较常用的是第一种和第二种方式。当然也可以自己实现第三种方式的文件读取方式,比如文件中不止两列,还有属性列等等,非常简单。

3 GraphX 图形创建实战

3.1 创建一个双向图

先拿上面数据列表中的第一份数据,数据解压之后的文件名为:Email-Enron.txt,前面十条示例数据如下:

# Directed graph (each unordered pair of nodes is saved once): Email-Enron.txt
# Enron email network (edge indicated that email was exchanged, undirected edges)
# Nodes: 36692 Edges: 367662
# FromNodeId	ToNodeId
0	1
1	0
1	2
1	3

可以发现这个数据集合非常适合上面edgeListFile方法创建图形,代码如下:

val emailGraph = GraphLoader.edgeListFile(sc, projectDir + "Email-Enron.txt")

查看一下图中前面5个顶点和边

emailGraph.vertices.take(5).foreach(println)
(19021,1)
(28730,1)
(23776,1)
(34207,1)
(31037,1)
emailGraph.edges.take(5).foreach(println)
Edge(0,1,1)
Edge(1,0,1)
Edge(1,2,1)
Edge(1,3,1)
Edge(1,4,1)

查看一下是否是双向图(任何两个点只要有连接必须是来回指向),这里只是查看顶点ID为19021的点:

emailGraph.edges.filter(_.srcId == 19021).map(_.dstId).collect().foreach(println)
696
4232
6811
8315
26007
emailGraph.edges.filter(_.dstId == 19021).map(_.srcId).collect().foreach(println)
696
4232
6811
8315
26007

3.2 创建一个二分图

什么是二分图?简单来说:二分图指的是图的顶点分为两个集合,其中任意集合内部顶点不可能有边关联,关联的边顶点一定分布在两个不同的集合之中。详细原理见Wiki百科
本文第二个数据集食物成分和化合物的关系图就是二分图。将下载的数据解压,先来看一下压缩包中每个原始文件前十条数据:

  • 文件1:ingr_info.tsv 从文件名可以知道它是按照制表符分割的文件 表示的是食物原料的信息
下面三列分别表示:原料ID	原料名字	分类
# id	ingredient name	category
0	magnolia_tripetala	flower
1	calyptranthes_parriculata	plant
2	chamaecyparis_pisifera_oil	plant derivative
3	mackerel	fish/seafood
4	mimusops_elengi_flower	flower
5	hyssop	herb
6	buchu	plant
7	black_pepper	spice
8	eryngium_poterium_oil	plant derivative
9	peanut_butter	plant derivative
  • 文件2:comp_info.tsv 这个表示化合物的基础信息
下面三列分别表示:化合物ID	化合物名字	CAS编号
# id	Compound name	CAS number
0	jasmone	488-10-8
1	5-methylhexanoic_acid	628-46-6
2	l-glutamine	56-85-9
3	1-methyl-3-methoxy-4-isopropylbenzene	1076-56-8
4	methyl-3-phenylpropionate	103-25-3
5	3-mercapto-2-methylpentan-1-ol_(racemic)	227456-27-1
6	ethyl-3-hydroxybutyrate	5405-41-4
7	cyclohexyl_butyrate	1551-44-6
8	methyl_dihydrojasmonate	24851-98-7
9	methyl_2-methylthiobutyrate	42075-45-6
  • 文件3:ingr_comp.tsv 这个记录的是 ingredient 和 compound 对应关系
# ingredient id	compound id
1392	906
1259	861
1079	673
22	906
103	906
1005	906
1005	278
1005	171

有了数据之后,如果你盲目的使用第三个文件直接按照上面的第一种方式建图的话,那么就会大错特错。因为第一列的ID和第二列的ID不是表示同一个事物,但是它们有交叉的数值。一个简单的办法就是第二列的值转化为第一列最大值+1之后再加上自身的数值,这样保证两个集合的ID没有交叉。请看下面的代码:

package clebeg.spark.graph

import org.apache.spark.graphx.{EdgeTriplet, VertexId, Edge, Graph}
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}


//定义下面的类将 ingredient 和 compount 统一表示 注意父类一定要可以序列化
class FoodNode(val name: String) extends Serializable
case class Ingredient(override val name: String, val cat: String) extends FoodNode(name)
case class Compound(override val name: String, val cas: String) extends FoodNode(name)
/**
  * Created by clebegxie on 2015/11/25.
  */
object Graph1Food {
  val projectDir = "your_data_dir/"
  def main(args: Array[String]) {
    val conf = new SparkConf().setAppName("SparkInAction").setMaster("local[4]")
    val sc = new SparkContext(conf)
    val ingredients: RDD[(VertexId, FoodNode)] = sc.textFile(projectDir + "ingr_info.tsv").filter {
      !_.startsWith("#")
    }.map {
      line =>
        val array = line.split("\t")
        (array(0).toLong, Ingredient(array(1), array(2)))
    }
    //获取得到最大的 ingredient 的ID 并且加1
    val maxIngrId = ingredients.keys.max() + 1
    val compounds: RDD[(VertexId, FoodNode)] = sc.textFile(projectDir + "comp_info.tsv").filter {
      !_.startsWith("#")
    }.map {
      line =>
        val array = line.split("\t")
        (maxIngrId + array(0).toLong, Compound(array(1), array(2)))
    }
    //根据文件 ingr_comp.csv 生成边,注意第二列的所有顶点都要加上 maxIngrId
    val links = sc.textFile(projectDir + "ingr_comp.tsv").filter {
      !_.startsWith("#")
    }.map {
      line =>
        val array = line.split("\t")
        Edge(array(0).toLong, maxIngrId + array(1).toLong, 1)
    }
    //将两个顶点合并
    val vertices = ingredients ++ compounds
    val foodNetWork = Graph(vertices, links)
    //foodNetWork.vertices.take(10).foreach(println)
    //访问一下这个网络前面5条triplet的对应关系
    foodNetWork.triplets.take(5).foreach(showTriplet _ andThen println _)
  }

  def showTriplet(t: EdgeTriplet[FoodNode, Int]): String =
    "The ingredient " ++ t.srcAttr.name ++ " contains " ++ t.dstAttr.name
}

运行结果为:

The ingredient calyptranthes_parriculata contains citral_(neral)
The ingredient chamaecyparis_pisifera_oil contains undecanoic_acid
The ingredient hyssop contains myrtenyl_acetate
The ingredient hyssop contains 4-(2,6,6-trimethyl-cyclohexa-1,3-dienyl)but-2-en-4-one
The ingredient buchu contains menthol

3.3 创建一个人与人之间相似性权重图

数据集是使用上面介绍的Google+提供的个人关系数据,解压之后有792个文件,每一个文件名去掉后缀代表的是网络ID,每个网络ID有6个文件,所以这里有132个个人关系网络。下面以ID为100129275726588145876的网络说明一下每个文件的含义:

  • .edges 记录的是边,即ID对应的用户之间有关联,示例数据为:
116374117927631468606 101765416973555767821
112188647432305746617 107727150903234299458
116719211656774388392 100432456209427807893
117421021456205115327 101096322838605097368
116407635616074189669 113556266482860931616
105706178492556563330 111169963967137030210
107527001343993112621 110877363259509543172
105513412023818293063 115710735637044108808
108736646334864181044 112393248315358692010
108683283643126638695 107111579950257773726
  • .feat 记录的是每个用户ID对应的特征,每个维度上面都是取值为 0 1,示例数据为:
#注意这里只是一行数据
114985346359714431656 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  • .featnames 记录的是上面feat每个维度对应的含义(注意:上面之所以每个维度取值都是 0 1, 是因为这里的特征都是分类变量,并且做了 1 of n 编码),示例数据为:
//从下面的gender可以看出,做了 1 of n 编码
0 gender:1
1 gender:2
2 gender:3
3 institution:
4 institution:AMC Theatres
5 institution:AOL
6 institution:AT&T
7 institution:Aardvark
8 institution:Accenture
9 institution:Adobe Systems

下面之间给出建图代码,代码意图都有注释:

val projectDir = "your_data_dir/"
val id = "100129275726588145876" //只建立这个ID对应的社交关系图
type Feature = breeze.linalg.SparseVector[Int]
def main(args: Array[String]) {
  val conf = new SparkConf().setAppName("SparkInAction").setMaster("local[4]")
  val sc = new SparkContext(conf)
  //通过 .feat 文件读取每个顶点的属性向量
  val featureMap = Source.fromFile(projectDir + id + ".feat").getLines().
  map {
    line =>
      val row = line.split(" ")
      //注意:ID 不能之间当作 Long 型的时候 常常用 hashcode 代替
      val key = abs(row.head.hashCode.toLong)
      val feat = SparseVector(row.tail.map(_.toInt))
      (key, feat)
  }.toMap

  //通过 .edges 文件得到两个用户之间的关系 并且计算他们相同特征的个数
  val edges = sc.textFile(projectDir + id + ".edges").map {
    line =>
      val row = line.split(" ")
      val srcId = abs(row(0).hashCode.toLong)
      val dstId = abs(row(1).hashCode.toLong)
      val srcFeat = featureMap(srcId)
      val dstFeat = featureMap(dstId)
      val numCommonFeats: Int = srcFeat dot dstFeat
      Edge(srcId, dstId, numCommonFeats)
  }

  //利用 fromEdges 建立图
  val egoNetwork = Graph.fromEdges(edges, 1)

  //查看一下具有3个相同特征的用户对
  print(egoNetwork.edges.filter(_.attr == 3).count())
}

这里需要注意下面两个地方:

  • Graphx对应的顶点必须为 Long 型,对于不符合的类型,通常取 HashCode
  • fromEdges 建图只需要已知边即可

个人微信公众号

欢迎关注本人微信公众号,会定时发送关于大数据、机器学习、Java、Linux 等技术的学习文章,而且是一个系列一个系列的发布,无任何广告,纯属个人兴趣。
Clebeg能量集结号

转载于:https://my.oschina.net/u/1244232/blog/535697

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 非常感谢您的提问。关于数据挖掘工具Spark的使用练习,我可以给您一些简单的介绍。 Spark是一种基于内存的分布式计算框架,可以用于大规模数据处理和分析。它提供了许多机器学习算法的实现,包括分类、回归、聚类、推荐等。在使用Spark进行机器学习时,可以使用其机器学习库MLlib。 为了练习Spark的机器学习功能,您可以选择一些数据集进行实验。例如,可以使用UCI机器学习库中的数据集,如鸢尾花数据集、波士顿房价数据集等。您可以使用Spark的API来读取这些数据集,并使用MLlib中的算法进行训练和预测。 在使用Spark进行机器学习时,需要注意一些问题。首先,需要对数据进行预处理,包括数据清洗、特征选择、特征缩放等。其次,需要选择合适的算法和参数,以达到最好的性能。最后,需要进行模型评估和调优,以提高模型的准确性和泛化能力。 希望这些信息对您有所帮助。如果您有其他问题,欢迎随时联系我。 ### 回答2: Spark是目前最流行,也是最强大的开源大数据处理框架之一,其在数据挖掘、机器学习等应用领域也有广泛的应用。本篇文章将深入探讨Spark中的机器学习工具——ml。 ml是Spark Machine Learning Library的简称,是Spark的核心机器学习API。它提供了一些基于分布式数据处理的机器学习算法,如线性回归、逻辑回归、决策树、随机森林、聚类等,以及各种数学工具和可视化工具。 首先我们需要了解一下Spark中机器学习的基本概念——管道。管道是一个机器学习工作流的逻辑组件,将数据流组装为一个完整的处理流程,并使得数据在流中顺序流动。Spark的管道API可以让机器学习工程师构建机器学习工作流的模型。同时,管道还具有容错性,可以在集群中处理海量数据,不容易出错。 首先我们来看一个管道的例子,该管道基于线性回归模型: 1.从数据源读入数据,如.csv、.parquet、.json文件或HDFS上的目录或数据源 2.对数据进行预处理,比如过滤、特征提取、缩放等 3.将预处理后的数据集拆分成训练、验证和测试三部分 4.使用管道API中提供的机器学习算法进行模型训练 5.使用验证集对模型进行验证 6.使用测试集对模型进行测试 7.对模型进行调优,提高其预测准确性 如果您对机器学习算法比较熟悉,那么通过Spark的ml库能够更加方便地构建机器学习管道。在这里,我们将介绍几个ml库中的常用算法。 首先是线性回归算法。线性回归是一种用于建立两种或两种以上变量之间的关系的统计学方法。尤其是当数据集显然是线性的时,它是一种常用的建模方法。在Spark的ml库中,线性回归可以通过LinearRegression类的方法进行训练和预测。例如: from pyspark.ml.regression import LinearRegression training = spark.read.format("libsvm").load("data/mllib/sample_linear_regression_data.txt") lr = LinearRegression(maxIter=10, regParam=0.3, elasticNetParam=0.6) # Fit the model lrModel = lr.fit(training) # Print the coefficients and intercept for linear regression print("Coefficients: %s" % str(lrModel.coefficients)) print("Intercept: %s" % str(lrModel.intercept)) 同样,逻辑回归是另一种常见的机器学习算法,其可用于二分类或多分类问题。在Spark的ml库中,逻辑回归的实现可以通过LogisticRegression类。例如: from pyspark.ml.classification import LogisticRegression training = spark.read.format("libsvm").load("data/mllib/sample_libsvm_data.txt") lr = LogisticRegression(maxIter=10, regParam=0.3, elasticNetParam=0.8) # Fit the model lrModel = lr.fit(training) # Print the coefficients and intercept for logistic regression print("Coefficients: %s" % str(lrModel.coefficients)) print("Intercept: %s" % str(lrModel.intercept)) 三、随机森林。随机森林是一个使用多个决策树进行分类或回归的集合算法。在Spark的ml库中,随机森林的实现可以通过RandomForestClassifier和RandomForestRegressor类。例如: from pyspark.ml.classification import RandomForestClassifier training = spark.read.format("libsvm").load("data/mllib/sample_libsvm_data.txt") rf = RandomForestClassifier(numTrees=10, maxDepth=5, seed=42) model = rf.fit(training) 输入数据通常都是高维的,管道工具也提供了gemetries变换的API,其中包括提取特征和转换特征向量。这些工具可以很方便地将数据转换为矩阵进行机器学习。使用特征转换器,我们可以创建一个用于管道的PipelineModel,用于数据预处理之后的机器学习模型预测。例如: from pyspark.ml.feature import PCA, VectorAssembler from pyspark.ml import Pipeline assembler = VectorAssembler(inputCols=["pca_features"], outputCol="features") pca = PCA(k=2, inputCol="features", outputCol="pca_features") pipeline = Pipeline(stages=[assembler, pca]) model = pipeline.fit(df) result = model.transform(df) print(result.select("features", "pca_features").show()) 总之,在Spark ml库中,提供了多种机器学习算法的实现工具,让我们只需要通过API即可完成机器学习流程。此外,Spark提高了算法的预测速度和准确性,并支持在分布式集群上进行机器学习,适用于处理大规模的数据集,并有效地处理各种任务。 ### 回答3: Spark是一个开源的基于内存计算的大数据处理框架,在数据挖掘领域也有着广泛的应用。MLlib是Spark的机器学习库,提供了大量可扩展的机器学习算法和工具。本次数据挖掘工具--Spark使用练习--ML(二)主要涉及如下内容: 1. 数据预处理 在机器学习任务中,数据预处理是非常重要的一步。Spark提供了一系列的数据处理API,例如读取数据、数据清洗、数据转换等。本次实践选择了UCI机器学习库中的Iris数据集,并使用Spark的API对数据进行了清洗和转换。 2. 特征提取 在机器学习建模过程中,特征提取是非常重要的一步。特征提取可以将原始数据转换成适合机器学习算法处理的形式。Spark提供了多种特征提取方法,例如TF-IDF、Word2Vec、PCA等。本次实践选择了PCA对数据进行了特征提取。 3. 模型训练和验证 Spark提供了多种机器学习算法,在本次实践中使用了K-Means聚类算法。K-Means是一种无监督学习算法,用于将数据分成K个不同的组。聚类算法的评估通常使用轮廓系数(Silhouette Coefficient)进行评估,在本次实践中也使用了该指标进行了模型的评估。 4. 模型应用 本次实践使用K-Means算法对Iris数据集进行了聚类分析,并将聚类结果进行了可视化展示。该实践展示了如何使用Spark的机器学习库进行数据挖掘和分析。 总之,通过本次实践学习,我们可以更深入地理解和掌握Spark数据挖掘领域的应用。在实践中需要注意的是,不同的机器学习算法适用于不同的数据集和问题,需要根据实际情况进行选择和应用。同时,也需要注意数据预处理和特征提取等环节对最终模型的影响。只有在充分理解和掌握这些基础知识的基础上,才能进行更加高效、准确和实用的数据挖掘工作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值