社交数据与股票数据的分析与建模
1. 社交数据分类器的训练与评估
在处理社交数据时,我们可以使用一系列函数将数据转换为适合MALLET处理的格式。首先,通过以下代码将数据放入
InstanceList
中:
(defn post-info-instances [post-infos]
(doto (InstanceList. (make-pipe))
(.addThruPipe (post-info-iterator post-infos))))
使用此函数,在REPL中创建
InstanceList
:
user=> (def ilist (n/post-info-instances s))
接着,我们将输入语料划分为测试集和训练集。定义了
split-sets
函数来简化MALLET的
split
方法:
(defn split-sets [test-ratio ilist]
(let [split-on (double-array [test-ratio (- 1.0 test-ratio)])
[test-set training-set] (.split ilist split-on)]
{:test test-set, :training training-set}))
在命令行中使用该函数划分输入:
user=> (def tt-sets (n/split-sets 0.2 ilist))
1.1 训练分类器
我们使用朴素贝叶斯分类器进行训练,定义了包装函数
bayes-train
:
(defn bayes-train [ilist] (.train (NaiveBayesTrainer.) ilist))
在REPL中获取训练好的贝叶斯分类器:
user=> (def bayes (n/bayes-train (:training tt-sets)))
1.2 测试分类器
MALLET提供了
Trial
类来测试分类器,我们定义了工厂函数:
(defn trial [classifier ilist] (Trial. classifier ilist))
在REPL中使用该函数:
user=> (def trial (n/trial bayes (:test tt-sets)))
1.3 评估分类器结果
评估分类器时,需要考虑以下几个因素:
-
精度(Precision)
:表示分类器正确识别为某一类别的比例。通过
getPrecision
方法获取:
user=> (.getPrecision trial "accepted")
0.2837067983289024
-
召回率(Recall)
:指分类器找到所有正样本的百分比。使用
getRecall方法:
user=> (.getRecall trial "accepted")
0.1808716707021792
-
准确率(Accuracy)
:是正确分类的样本数与总样本数的比例。通过
getAccuracy方法获取:
user=> (.getAccuracy trial)
0.73655
-
F1分数
:综合了精度和召回率,范围从0(差)到1(完美)。使用
getF1方法:
user=> (.getF1 trial "accepted")
0.22090788111784712
还可以通过混淆矩阵获取更详细的信息,定义了
confusion-matrix
函数:
(defn confusion-matrix [trial] (str (ConfusionMatrix. trial)))
调用该函数并打印矩阵:
user=> (println (n/confusion-matrix trial))
Confusion Matrix, row=true, column=predicted accuracy=0.73655
label 0 1 |total
0 not 13984 1886 |15870
1 accepted 3383 747 |4130
以下是评估分类器的流程:
graph TD;
A[准备数据] --> B[划分训练集和测试集];
B --> C[训练分类器];
C --> D[测试分类器];
D --> E[评估分类器];
E --> F[获取精度、召回率等指标];
E --> G[获取混淆矩阵];
2. 股票数据的分析与建模
近年来,自动化股票分析备受关注。我们将探索新闻文章与未来股票价格之间的关系,具体步骤如下:
2.1 了解金融数据分析
金融领域一直依赖数据,如收益报表、预测和投资组合管理等。近期,量化金融、高频交易等领域受到广泛关注,这些领域应用统计或机器学习方法处理金融数据。我们将开发一个简单的机器学习系统,结合新闻文章文本和股票价格,为投资者或分析师提供决策信息。
2.2 项目基础设置
- 设置库 :使用Leiningen 2和Stuart Sierra的reloaded插件初始化开发环境和项目。在命令行执行:
lein new reloaded financial
在
project.clj
文件中指定所需的库:
(defproject financial "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/data.xml "0.0.7"]
[org.clojure/data.csv "0.1.2"]
[clj-time "0.6.0"]
[me.raynes/fs "1.4.4"]
[org.encog/encog-core "3.1.0"]
[enclog "0.6.3"]]
:profiles
{:dev {:dependencies [[org.clojure/tools.namespace "0.2.4"]]
:source-paths ["dev"]}})
-
获取数据
:
-
股票数据
:以Dominion Resources, Inc.的历史股票数据为例,其纽约证券交易所代码为D。在Google Finance搜索
NYSE:D,点击左侧菜单的“下载历史价格”,设置日期范围为1995年9月1日至2001年1月1日,下载数据并保存为d-1995-2001.csv。 -
新闻文章数据
:使用Open American National Corpus的新闻部分,该部分包含Slate的文章。访问下载页面
http://www.anc.org/data/oanc/download/,下载数据并解压到项目的d目录。
-
股票数据
:以Dominion Resources, Inc.的历史股票数据为例,其纽约证券交易所代码为D。在Google Finance搜索
2.3 数据准备
对于新闻文章数据,由于OANC以XML格式发布,包含大量注释信息。我们创建了
NewsArticle
记录类型:
(ns financial.types)
(defrecord NewsArticle [title pub-date text])
为了处理OANC的目录结构,定义了以下函数:
(defn list-category-genres [category-dir]
(map #(hash-map :genre % :dirname (io/file category-dir %))
(fs/list-dir category-dir)))
(defn list-genres [oanc-dir]
(mapcat list-category-genres (ls (io/file oanc-dir "data"))))
(defn find-genre-dir [genre oanc-dir]
(->> oanc-dir
list-genres
(filter #(= (:genre %) genre))
first
:dirname))
(defn find-source-data [genre source oanc-dir]
(-> (find-genre-dir genre oanc-dir)
(io/file source)
(fs/find-files #".*\.anc")))
使用这些函数获取Slate文章的元数据和文本文件:
(defn find-slate-files [oanc-dir]
(map #(hash-map :anc % :txt (chext % ".txt"))
(find-source-data "journal" "slate" oanc-dir)))
为了解析XML文件,定义了
find-all
和
content-str
函数:
(defn find-all [xml tag-name]
(lazy-seq
(if (= (:tag xml) tag-name)
(cons xml (mapcat #(find-all % tag-name) (:content xml)))
(mapcat #(find-all % tag-name) (:content xml)))))
(defn content-str [xml]
(apply str (filter string? (:content xml))))
解析日期时,定义了日期格式和相关函数:
(def date-time-format
(time-format/formatter "M/d/yyyy h:mm:ss a"))
(defn parse-pub-date [pub-date-el]
(time-format/parse date-time-format (content-str pub-date-el)))
(defn norm-date [date]
(cond
(= (clj-time/year date) 0)
(clj-time/plus date (clj-time/years 2000))
(< (clj-time/year date) 100)
(clj-time/plus date (clj-time/years 1900))
:else date))
最后,定义了加载文章的函数:
(defn load-article [data-info]
(let [{:keys [anc txt]} data-info
anc-xml (xml/parse (io/reader anc))]
(->NewsArticle (find-title anc-xml)
(find-pub-date anc-xml)
(slurp txt))))
(defn load-text-file [data filename]
(->NewsArticle filename date (slurp filename)))
在REPL中加载所有Slate文章:
user=> (def articles (doall (map oanc/load-article
(oanc/find-slate-files
(io/file "d/OANC-GrAF")))))
user=> (count articles)
4531
以下是处理新闻文章数据的流程:
graph TD;
A[下载OANC数据] --> B[解析目录结构];
B --> C[获取文章元数据和文本文件];
C --> D[解析XML文件];
D --> E[解析日期];
E --> F[加载文章数据];
综上所述,我们完成了社交数据分类器的训练与评估,以及股票数据相关项目的基础设置和新闻文章数据的准备工作。后续可以进一步分析文本和股票价格,使用神经网络学习模式,并尝试预测未来股票价格。
3. 文本分析与股票价格分析
在完成数据准备工作后,接下来要对新闻文章文本和股票价格进行分析。
3.1 文本分析
新闻文章数据已经被整理成
NewsArticle
记录类型,包含标题、发布日期和文本内容。我们可以对文本进行进一步的处理,例如提取关键词、进行情感分析等。不过在当前步骤中,我们重点关注如何将文本转换为适合机器学习模型处理的特征向量。
一种简单的方法是使用词袋模型(Bag of Words),将文本中的每个单词看作一个特征,统计每个单词在文章中出现的频率。在 Clojure 中,可以使用以下步骤实现:
1.
分词
:将文章文本分割成单个的单词。
(defn tokenize [text]
(str/split text #"\W+"))
- 构建词汇表 :收集所有文章中出现的单词,形成一个词汇表。
(defn build-vocabulary [articles]
(->> articles
(map :text)
(map tokenize)
(apply concat)
(distinct)))
- 生成特征向量 :对于每篇文章,根据词汇表统计每个单词的出现频率,生成特征向量。
(defn generate-feature-vector [article vocabulary]
(let [tokens (tokenize (:text article))]
(map #(count (filter (partial = %) tokens)) vocabulary)))
以下是文本分析的流程:
graph TD;
A[文章数据] --> B[分词];
B --> C[构建词汇表];
C --> D[生成特征向量];
3.2 股票价格分析
股票价格数据以 CSV 文件的形式存储,我们需要读取和处理这些数据。可以使用
org.clojure/data.csv
库来读取 CSV 文件。
(require '[clojure.data.csv :as csv]
'[clojure.java.io :as io])
(defn read-stock-data [filename]
(with-open [in-file (io/reader filename)]
(doall
(csv/read-csv in-file))))
读取数据后,可以进行一些基本的统计分析,例如计算每日的价格变化、平均价格等。
(defn calculate-price-changes [stock-data]
(let [prices (map #(Double/parseDouble (nth % 4)) (rest stock-data))]
(map - (rest prices) prices)))
以下是股票价格分析的流程:
graph TD;
A[股票数据文件] --> B[读取数据];
B --> C[统计分析];
C --> D[计算价格变化等];
4. 使用神经网络学习模式
在完成文本和股票价格的分析后,我们可以使用神经网络来学习两者之间的模式。这里使用 Enclog 库,它是 Encog 机器学习库的 Clojure 包装器。
4.1 准备训练数据
将新闻文章的特征向量和对应的股票价格数据组合成训练数据。假设我们已经有了文章的特征向量和股票价格变化数据,可以将它们组合成一个二维数组。
(defn prepare-training-data [articles stock-data vocabulary]
(let [feature-vectors (map #(generate-feature-vector % vocabulary) articles)
price-changes (calculate-price-changes stock-data)]
(map vector feature-vectors price-changes)))
4.2 构建神经网络模型
使用 Enclog 库构建一个简单的前馈神经网络。
(require '[enclog.core :as encog])
(defn build-neural-network [input-size hidden-size output-size]
(encog/neural-network
(encog/input-layer input-size)
(encog/hidden-layer hidden-size)
(encog/output-layer output-size)))
4.3 训练神经网络
使用准备好的训练数据对神经网络进行训练。
(defn train-neural-network [network training-data]
(encog/train network training-data))
以下是使用神经网络学习模式的流程:
graph TD;
A[文章数据和股票数据] --> B[准备训练数据];
B --> C[构建神经网络模型];
C --> D[训练神经网络];
5. 预测未来股票价格
训练好神经网络模型后,就可以使用它来预测未来的股票价格。
5.1 准备测试数据
将新的新闻文章数据转换为特征向量,作为测试数据。
(defn prepare-test-data [new-articles vocabulary]
(map #(generate-feature-vector % vocabulary) new-articles))
5.2 进行预测
使用训练好的神经网络对测试数据进行预测。
(defn predict-stock-prices [network test-data]
(map #(encog/compute network %) test-data))
以下是预测未来股票价格的流程:
graph TD;
A[新的文章数据] --> B[准备测试数据];
B --> C[使用训练好的网络进行预测];
C --> D[得到预测结果];
6. 系统的局限性
虽然我们构建了一个简单的机器学习系统来预测未来股票价格,但这个系统存在一些局限性。
-
数据有限
:使用的新闻文章数据是免费获取的,数量和质量可能有限,无法全面反映市场情况。
-
模型简单
:使用的朴素贝叶斯分类器和简单的神经网络模型可能无法捕捉到复杂的市场动态和股票价格变化规律。
-
特征不足
:仅使用了文本的简单特征和股票价格的基本统计信息,没有考虑其他可能影响股票价格的因素,如公司财务状况、行业趋势等。
在实际应用中,需要进一步改进数据收集方法、优化模型结构和增加特征维度,以提高系统的预测准确性。
综上所述,我们通过一系列步骤完成了从社交数据分类器的训练与评估,到股票数据的分析、建模和预测的过程。虽然系统存在一定的局限性,但为我们提供了一个初步的框架,可以在此基础上进行进一步的研究和改进。
超级会员免费看
1546

被折叠的 条评论
为什么被折叠?



