diff --git a/Documentation.pdf b/Documentation.pdf new file mode 100644 index 0000000000..9aa0b245a8 Binary files /dev/null and b/Documentation.pdf differ diff --git a/Project Progress Report.pdf b/Project Progress Report.pdf new file mode 100644 index 0000000000..c76c70fde2 Binary files /dev/null and b/Project Progress Report.pdf differ diff --git a/Project Proposal.pdf b/Project Proposal.pdf new file mode 100644 index 0000000000..f369792d51 Binary files /dev/null and b/Project Proposal.pdf differ diff --git a/README.md b/README.md index a7b40d2cc8..310313eac8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,15 @@ -# CourseProject +# Enhancing and Extending Metapy versioning and functionality -Please fork this repository and paste the github link of your fork on Microsoft CMT. Detailed instructions are on Coursera under Week 1: Course Project Overview/Week 9 Activities. +Where are respective files placed? + +Project Progress Report: This can be found in the root directory of the project within a file labeled: Project Progress Report.pdf + +Source Code: + The source code for the core functionality can be found at: /metapy/src/nltk_additions.py + The respective test code for the core functionality can be found at: /metapy/src/nltk_test.py + +Documentation: Detailed documentation can be found in the root directory of the project within a file labeled: Documentation.pdf + +Software Tutorial Link: + +Software Tutorial Presentation Link: \ No newline at end of file diff --git a/metapy/CMakeLists.txt b/metapy/CMakeLists.txt new file mode 100644 index 0000000000..9a8fef42fa --- /dev/null +++ b/metapy/CMakeLists.txt @@ -0,0 +1,70 @@ +cmake_minimum_required(VERSION 3.2.0) + +project(metapy) + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + +set(METAPY_PYTHON_VERSION "" CACHE STRING + "Python version to use for compiling the extension") + +add_subdirectory(deps/meta EXCLUDE_FROM_ALL) + +if (NOT PYTHON_INCLUDE_DIRS) + if (NOT ${METAPY_PYTHON_VERSION} STREQUAL "") + list(APPEND Python_ADDITIONAL_VERSIONS ${METAPY_PYTHON_VERSION}) + find_package(PythonLibs ${METAPY_PYTHON_VERSION} EXACT) + if (NOT PythonLibs_FOUND) + find_package(PythonLibs ${METAPY_PYTHON_VERSION} REQUIRED) + endif() + else() + find_package(PythonLibs REQUIRED) + endif() +else() + message("-- Using manual Python include dirs: ${PYTHON_INCLUDE_DIRS}") +endif() + +include_directories(${PYTHON_INCLUDE_DIRS}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/deps/pybind11/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +add_library(metapy SHARED src/metapy_analyzers.cpp + src/metapy_classify.cpp + src/metapy_embeddings.cpp + src/metapy_index.cpp + src/metapy_learn.cpp + src/metapy_sequence.cpp + src/metapy_stats.cpp + src/metapy_parser.cpp + src/metapy_topics.cpp + src/metapy.cpp) +target_link_libraries(metapy meta-index meta-classify meta-ranker + meta-sequence meta-sequence-analyzers meta-greedy-tagger meta-parser + meta-parser-analyzers meta-embeddings meta-topics) + +# don't add a "lib" prefix to the metapy shared library +set_target_properties(metapy PROPERTIES PREFIX "") + +if (APPLE) + # OS X stupid fixes + # (see http://pybind11.readthedocs.org/en/latest/cmake.html) + set_target_properties(metapy PROPERTIES + MACOSX_RPATH "." + LINK_FLAGS "-undefined dynamic_lookup " + SUFFIX ".so") +endif() + +if (WIN32) + set_target_properties(metapy PROPERTIES SUFFIX ".pyd") + target_link_libraries(metapy ${PYTHON_LIBRARY}) + target_compile_definitions(metapy PUBLIC -DMS_WIN64) + + # fix for std::_hypot has not been declared + target_compile_definitions(metapy PUBLIC -D_hypot=hypot) +endif() + +install(TARGETS metapy DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/dist/metapy) diff --git a/metapy/LICENSE.mit b/metapy/LICENSE.mit new file mode 100644 index 0000000000..a4742a0159 --- /dev/null +++ b/metapy/LICENSE.mit @@ -0,0 +1,18 @@ +Copyright (c) 2016 Sean Massung, Chase Geigle + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/metapy/LICENSE.ncsa b/metapy/LICENSE.ncsa new file mode 100644 index 0000000000..5a1e3c5324 --- /dev/null +++ b/metapy/LICENSE.ncsa @@ -0,0 +1,29 @@ +Copyright (c) 2016 Sean Massung, Chase Geigle +All rights reserved. + +Developed by: MeTA Team + University of Illinois at Urbana-Champaign + https://meta-toolkit.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimers. Redistributions in binary +form must reproduce the above copyright notice, this list of conditions and the +following disclaimers in the documentation and/or other materials provided with +the distribution. Neither the names of MeTA, University of Illinois, nor the +names of its contributors may be used to endorse or promote products derived +from this Software without specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. diff --git a/metapy/MANIFEST.in b/metapy/MANIFEST.in new file mode 100644 index 0000000000..7e520961df --- /dev/null +++ b/metapy/MANIFEST.in @@ -0,0 +1,16 @@ +# Licenses +include LICENSE.mit +include LICENSE.ncsa + +# Build system +include CMakeLists.txt + +# Dependencies +recursive-include deps ** + +# metapy source code +recursive-include src ** +recursive-include include ** + +# metapy package +recursive-include dist/metapy ** diff --git a/metapy/README.md b/metapy/README.md new file mode 100644 index 0000000000..e2436d3120 --- /dev/null +++ b/metapy/README.md @@ -0,0 +1,61 @@ +# metapy: (experimental) Python bindings for [MeTA][meta] + +[![Build Status](https://travis-ci.org/meta-toolkit/metapy.svg?branch=master)](https://travis-ci.org/meta-toolkit/metapy) + +[![Windows Build Status](https://ci.appveyor.com//api/projects/status/github/meta-toolkit/metapy?svg=true&branch=master)](https://ci.appveyor.com/project/skystrife/metapy) + +This project provides Python (2.7 and 3.x are supported) bindings for the +MeTA toolkit. They are still very much under construction, but the goal is +to make it seamless to use MeTA's components within any Python application +(e.g., a Django or Flask web app). + +This project is made possible by the excellent [pybind11][pybind11] +library. + +## Getting Started (the easy way) + +```bash +# Ensure your pip is up to date +pip install --upgrade pip + +# install metapy! +pip install metapy +``` + +This should work on Linux, OS X, and Windows with pretty much any recent +Python version >= 2.7. On Linux, make sure to update your `pip` to version +8.1 so you can install from a binary package---this will save you a lot of +time. + +## Getting Started (the hard way) + +You will, of course, need Python installed. You will also need its headers +to be installed as well, so look for a `python-dev` or similar package for +your system. Beyond that, you'll of course need to satisfy the requirements +for [building MeTA itself][build-guide]. + +This repository should have everything you need to get started. You should +ensure that you've fetched all of the submodules first, though: + +```bash +git submodule update --init --recursive +``` + +Once that's done, you should be able to build the library like so: + +```bash +mkdir build +cd build +cmake .. -DCMAKE_BUILD_TYPE=Release +make +``` + +You can force building against a specific version of Python if you happen +to have multiple versions installed by specifying +`-DMETAPY_PYTHON_VERSION=x.y` when invoking `cmake`. + +The module should be written to `metapy.so` in the build directory. + +[meta]: https://meta-toolkit.org +[pybind11]: https://github.com/pybind/pybind11 +[build-guide]: https://meta-toolkit.org/setup-guide.html diff --git a/metapy/examples/query_runner.py b/metapy/examples/query_runner.py new file mode 100644 index 0000000000..ca2b421f23 --- /dev/null +++ b/metapy/examples/query_runner.py @@ -0,0 +1,55 @@ +""" +Mimics MeTA's query-runner program. +""" + +import math +import sys +import time + +import metapy + +class PL2Ranker(metapy.index.RankingFunction): + """ + Create a new ranking function in Python that can be used in MeTA + """ + def __init__(self, c_param=0.5): + self.c = c_param + super(PL2Ranker, self).__init__() + + def score_one(self, sd): + lda = sd.num_docs / sd.corpus_term_count + tfn = sd.doc_term_count * math.log2(1.0 + self.c * sd.avg_dl / + sd.doc_size) + if lda < 1 or tfn <= 0: + return 0.0 + numerator = tfn * math.log2(tfn * lda) \ + + math.log2(math.e) * (1.0 / lda - tfn) \ + + 0.5 * math.log2(2.0 * math.pi * tfn) + return sd.query_term_weight * numerator / (tfn + 1.0) + +if __name__ == '__main__': + + if len(sys.argv) != 4: + print("Usage: {} config.toml queries.txt start_query".format(sys.argv[0])) + sys.exit(1) + + cfg = sys.argv[1] + idx = metapy.index.make_inverted_index(cfg) + + query_path = sys.argv[2] + query_num = int(sys.argv[3]) + start_time = time.time() + with open(query_path) as query_file: + pl2 = PL2Ranker() + for line in query_file: + query = metapy.index.Document() + query.content(line.strip()) + res_num = 1 + for doc in pl2.score(idx, query, 1000): + docno = idx.metadata(doc[0]).get('name') + print("{}\t_\t{}\t{}\t{}\tMeTA".format( query_num, docno, + res_num, doc[1])) + res_num += 1 + query_num += 1 + + print("Elapsed: {} seconds".format(round(time.time() - start_time, 4))) diff --git a/metapy/get-release.py b/metapy/get-release.py new file mode 100755 index 0000000000..454277d707 --- /dev/null +++ b/metapy/get-release.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +from __future__ import print_function + +from clint.textui import progress +import requests +import sys + +if len(sys.argv) != 2: + print("Usage: {} release-tag".format(sys.argv[0])) + sys.exit(1) + +baseurl = 'https://api.github.com/repos/meta-toolkit/metapy/releases/tags' + +r = requests.get('{}/{}'.format(baseurl, sys.argv[1])) + +if r.status_code != 200: + print("Error: {}".format(r.status_code)) + print(r.text) + sys.exit(1) + +json = r.json() + +print("Found release {} tagged by {}".format(json['tag_name'], + json['author']['login'])) + +for asset in json['assets']: + url = asset['browser_download_url'] + name = asset['name'] + print("Fetching {}...".format(name)) + + r = requests.get(url, stream=True) + if r.status_code != 200: + print("Error fetching {}: {}".format(name, r.status_code)) + print(r.text) + sys.exit(1) + + with open('dist/{}'.format(name), 'wb') as f: + total_length = int(r.headers.get('content-length')) + for chunk in progress.bar(r.iter_content(chunk_size = 4096), + expected_size = total_length / 4096 + 1): + if chunk: + f.write(chunk) + f.flush() + +print("Done!") diff --git a/metapy/include/metapy_analyzers.h b/metapy/include/metapy_analyzers.h new file mode 100644 index 0000000000..e06405b704 --- /dev/null +++ b/metapy/include/metapy_analyzers.h @@ -0,0 +1,13 @@ +/** + * @file metapy_analyzers.h + * @author Chase Geigle + */ + +#ifndef METAPY_ANALYZERS_H_ +#define METAPY_ANALYZERS_H_ + +#include +#include + +void metapy_bind_analyzers(pybind11::module& m); +#endif diff --git a/metapy/include/metapy_classify.h b/metapy/include/metapy_classify.h new file mode 100644 index 0000000000..32a19f0377 --- /dev/null +++ b/metapy/include/metapy_classify.h @@ -0,0 +1,14 @@ +/** + * @file metapy_classify.h + * @author Chase Geigle + */ + +#ifndef METAPY_CLASSIFY_H_ +#define METAPY_CLASSIFY_H_ + +#include +#include + +void metapy_bind_classify(pybind11::module& m); + +#endif diff --git a/metapy/include/metapy_embeddings.h b/metapy/include/metapy_embeddings.h new file mode 100644 index 0000000000..d03fa31d03 --- /dev/null +++ b/metapy/include/metapy_embeddings.h @@ -0,0 +1,14 @@ +/** + * @file metapy_embeddings.h + * @author Chase Geigle + */ + +#ifndef METAPY_EMBEDDINGS_H_ +#define METAPY_EMBEDDINGS_H_ + +#include +#include + +void metapy_bind_embeddings(pybind11::module& m); + +#endif diff --git a/metapy/include/metapy_identifiers.h b/metapy/include/metapy_identifiers.h new file mode 100644 index 0000000000..3c53d602eb --- /dev/null +++ b/metapy/include/metapy_identifiers.h @@ -0,0 +1,59 @@ +/** + * @file metapy_identifiers.h + * @author Chase Geigle + * + * Provides a caster to/from meta::util::identifier for pybind11. + */ + +#ifndef METAPY_IDENTIFIERS_H_ +#define METAPY_IDENTIFIERS_H_ + +#include +#include + +#include "meta/meta.h" + +namespace pybind11 +{ +namespace detail +{ + +template +struct identifier_caster +{ + using underlying_type = typename Type::underlying_type; + using type_conv = make_caster; + + PYBIND11_TYPE_CASTER(Type, _("id[") + type_conv::name() + _("]")); + + bool load(handle src, bool convert) + { + type_conv conv; + if (!conv.load(src, convert)) + return false; + value = Type{(underlying_type)conv}; + return true; + } + + static handle cast(const Type& src, return_value_policy policy, + handle parent) + { + return type_conv::cast(static_cast(src), policy, + parent); + } +}; + +template +struct type_caster> + : identifier_caster> +{ +}; + +template +struct type_caster> + : identifier_caster> +{ +}; +} +} +#endif diff --git a/metapy/include/metapy_index.h b/metapy/include/metapy_index.h new file mode 100644 index 0000000000..09ec959dfe --- /dev/null +++ b/metapy/include/metapy_index.h @@ -0,0 +1,91 @@ +/** + * @file metapy_index.h + * @author Chase Geigle + * + */ + +#ifndef METAPY_INDEX_H_ +#define METAPY_INDEX_H_ + +#include +#include + +#include "meta/index/ranker/ranker.h" +#include "meta/util/optional.h" +#include "metapy_identifiers.h" + +namespace pybind11 +{ +namespace detail +{ +// add conversion for meta::index::search_result +// see: pybind11/cast.h +template <> +struct type_caster +{ + using type = std::pair; + + // Python -> C++ + bool load(handle src, bool convert) + { + value = meta::util::nullopt; + make_caster conv; + if (!conv.load(src, convert)) + return false; + + auto pr = static_cast(conv); + value = meta::index::search_result{pr.first, pr.second}; + return true; + } + + // C++ -> Python + static handle cast(const meta::index::search_result& sr, + return_value_policy policy, handle parent) + { + auto o1 = reinterpret_steal( + make_caster::cast(sr.d_id, policy, parent)); + auto o2 = reinterpret_steal( + make_caster::cast(sr.score, policy, parent)); + + if (!o1 || !o2) + return handle(); + + tuple result(2); + PyTuple_SET_ITEM(result.ptr(), 0, o1.release().ptr()); + PyTuple_SET_ITEM(result.ptr(), 1, o2.release().ptr()); + return result.release(); + } + + static PYBIND11_DESCR name() + { + return type_descr(_("SearchResult")); + } + + static handle cast(const meta::index::search_result* sr, + return_value_policy policy, handle parent) + { + return cast(*sr, policy, parent); + } + + operator meta::index::search_result*() + { + return &*value; + } + + operator meta::index::search_result&() + { + return *value; + } + + template + using cast_op_type = pybind11::detail::cast_op_type; + + protected: + meta::util::optional value; +}; +} +} + +void metapy_bind_index(pybind11::module& m); + +#endif diff --git a/metapy/include/metapy_learn.h b/metapy/include/metapy_learn.h new file mode 100644 index 0000000000..8bcbff345b --- /dev/null +++ b/metapy/include/metapy_learn.h @@ -0,0 +1,33 @@ +/** + * @file metapy_learn.h + * @author Chase Geigle + */ + +#ifndef METAPY_LEARN_H_ +#define METAPY_LEARN_H_ + +#include +#include + +template +DatasetView make_sliced_dataset_view(const DatasetView& dv, + pybind11::slice slice) +{ + std::size_t start, stop, step, slicelength; + if (!slice.compute(dv.size(), &start, &stop, &step, &slicelength)) + throw pybind11::error_already_set{}; + + std::vector indices(slicelength); + auto it = dv.begin() + start; + for (std::size_t i = 0; i < slicelength; ++i) + { + indices[i] = it->id; + it += step; + } + + return DatasetView{dv, std::move(indices)}; +} + +void metapy_bind_learn(pybind11::module& m); + +#endif diff --git a/metapy/include/metapy_parser.h b/metapy/include/metapy_parser.h new file mode 100644 index 0000000000..7304ddbfe4 --- /dev/null +++ b/metapy/include/metapy_parser.h @@ -0,0 +1,14 @@ +/** + * @file metapy_parser.h + * @author Chase Geigle + */ + +#ifndef METAPY_PARSER_H_ +#define METAPY_PARSER_H_ + +#include +#include + +void metapy_bind_parser(pybind11::module& m); + +#endif diff --git a/metapy/include/metapy_probe_map.h b/metapy/include/metapy_probe_map.h new file mode 100644 index 0000000000..bf3bf3e8c3 --- /dev/null +++ b/metapy/include/metapy_probe_map.h @@ -0,0 +1,81 @@ +/** + * @file metapy_probe_map.h + * @author Chase Geigle + * + * Provides a caster from hashing::probe_map for pybind11. + */ + +#ifndef METAPY_PROBE_MAP_H_ +#define METAPY_PROBE_MAP_H_ + +#include +#include + +#include "meta/hashing/probe_map.h" + +namespace pybind11 +{ +namespace detail +{ + +// add conversion for hashing::probe_map +// @see pybind11/stl.h +template +struct probe_map_caster +{ + using type = Type; + using key_conv = type_caster::type>; + using value_conv = type_caster::type>; + + bool load(handle src, bool convert) + { + dict d{src, true}; + if (!d.check()) + return false; + make_caster kconv; + make_caster vconv; + value.clear(); + for (auto it : d) + { + if (!kconv.load(it.first.ptr(), convert) + || !vconv.load(it.second.ptr(), convert)) + return false; + value.emplace((Key)kconv, (Value)vconv); + } + return true; + } + + static handle cast(const type& src, return_value_policy policy, + handle parent) + { + dict d; + for (const auto& kv : src) + { + auto key = reinterpret_steal( + make_caster::cast(kv.key(), policy, parent)); + auto value = reinterpret_steal( + make_caster::cast(kv.value(), policy, parent)); + if (!key || !value) + return handle{}; + d[key] = value; + } + return d.release(); + } + + PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + + value_conv::name() + _(">")); +}; + +template +struct type_caster> + : probe_map_caster, + Key, Value> +{ +}; +} +} + +#endif diff --git a/metapy/include/metapy_sequence.h b/metapy/include/metapy_sequence.h new file mode 100644 index 0000000000..3689e5a520 --- /dev/null +++ b/metapy/include/metapy_sequence.h @@ -0,0 +1,14 @@ +/** + * @file metapy_sequence.h + * @author Chase Geigle + */ + +#ifndef METAPY_SEQUENCE_H_ +#define METAPY_SEQUENCE_H_ + +#include +#include + +void metapy_bind_sequence(pybind11::module& m); + +#endif diff --git a/metapy/include/metapy_stats.h b/metapy/include/metapy_stats.h new file mode 100644 index 0000000000..efffafe124 --- /dev/null +++ b/metapy/include/metapy_stats.h @@ -0,0 +1,145 @@ +/** + * @file metapy_stats.h + * @author Chase Geigle + */ + +#ifndef METAPY_STATS_H_ +#define METAPY_STATS_H_ + +#include +#include + +#include "meta/stats/multinomial.h" + +/** + * Wrapper class for stats::multinomial for Python. This makes it so we + * don't have to bind stats::multinomial multiple times for each T we want + * to use. Instead, we just need to convert it to a py_multinomial at the + * return site in the python binding function. + */ +class py_multinomial +{ + public: + template + py_multinomial(const meta::stats::multinomial& dist) + : concept_{meta::make_unique>(dist)} + { + // nothing + } + + void increment(pybind11::object obj, double count) + { + concept_->increment(obj, count); + } + + void decrement(pybind11::object obj, double count) + { + concept_->decrement(obj, count); + } + + double counts(pybind11::object obj) const + { + return concept_->counts(obj); + } + + double counts() const + { + return concept_->counts(); + } + + uint64_t unique_events() const + { + return concept_->unique_events(); + } + + void each_seen_event(std::function fun) const + { + concept_->each_seen_event(fun); + } + + void clear() + { + concept_->clear(); + } + + double probability(pybind11::object obj) const + { + return concept_->probability(obj); + } + + private: + class multinomial_concept + { + public: + virtual ~multinomial_concept() = default; + virtual void increment(pybind11::object obj, double count) = 0; + virtual void decrement(pybind11::object obj, double count) = 0; + virtual double counts(pybind11::object obj) const = 0; + virtual double counts() const = 0; + virtual uint64_t unique_events() const = 0; + virtual void each_seen_event( + std::function fun) const = 0; + virtual void clear() = 0; + virtual double probability(pybind11::object obj) const = 0; + }; + + template + class multinomial_impl : public multinomial_concept + { + public: + multinomial_impl(const meta::stats::multinomial& dist) : dist_{dist} + { + // nothing + } + + void increment(pybind11::object obj, double count) override + { + dist_.increment(obj.cast(), count); + } + + void decrement(pybind11::object obj, double count) override + { + dist_.decrement(obj.cast(), count); + } + + double counts(pybind11::object obj) const override + { + return dist_.counts(obj.cast()); + } + + double counts() const override + { + return dist_.counts(); + } + + uint64_t unique_events() const override + { + return dist_.unique_events(); + } + + void each_seen_event( + std::function fun) const override + { + dist_.each_seen_event( + [&](const T& event) { fun(pybind11::cast(event)); }); + } + + void clear() override + { + dist_.clear(); + } + + double probability(pybind11::object obj) const override + { + return dist_.probability(obj.cast()); + } + + private: + meta::stats::multinomial dist_; + }; + + std::unique_ptr concept_; +}; + +void metapy_bind_stats(pybind11::module& m); +#endif diff --git a/metapy/include/metapy_topics.h b/metapy/include/metapy_topics.h new file mode 100644 index 0000000000..0aa9a1e653 --- /dev/null +++ b/metapy/include/metapy_topics.h @@ -0,0 +1,83 @@ +/** + * @file metapy_topics.h + * @author Sean Massung + */ + +#ifndef METAPY_TOPICS_H_ +#define METAPY_TOPICS_H_ + +#include +#include + +#include "meta/topics/topic_model.h" +#include "metapy_identifiers.h" + +namespace pybind11 +{ +namespace detail +{ +namespace metapy +{ +template +struct prob_caster +{ + PYBIND11_TYPE_CASTER(TupleType, _("Probability")); + + bool load(handle src, bool convert) + { + if (!isinstance(src)) + return false; + + const auto seq = reinterpret_borrow(src); + if (seq.size() != 2) + return false; + + if (!first.load(seq[0], convert) || !second.load(seq[1], convert)) + return false; + value.tid = (Identifier)first; + value.probability = (double)second; + return true; + } + + static handle cast(const TupleType& src, return_value_policy& policy, + handle& parent) + { + auto id = reinterpret_steal( + make_caster::cast(src.tid, policy, parent)); + auto prob = reinterpret_steal( + make_caster::cast(src.probability, policy, parent)); + + if (!id || !prob) + return handle(); + + tuple result(2); + PyTuple_SET_ITEM(result.ptr(), 0, id.release().ptr()); + PyTuple_SET_ITEM(result.ptr(), 1, prob.release().ptr()); + return result.release(); + } + + protected: + make_caster first; + make_caster second; +}; +} + +// add conversion for meta::topics::term_prob +template <> +struct type_caster + : metapy::prob_caster +{ +}; + +// add conversion for meta::topics::topic_prob +template <> +struct type_caster + : metapy::prob_caster +{ +}; +} +} + +void metapy_bind_topics(pybind11::module& m); + +#endif diff --git a/metapy/make-release.sh b/metapy/make-release.sh new file mode 100755 index 0000000000..4113092559 --- /dev/null +++ b/metapy/make-release.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -eo pipefail + +version=$(git describe --tags) + +confirm() { + read -r -p "${1:-Are you sure? [y/N]} " response + case $response in + [yY][eE][sS]|[yY]) + true + ;; + *) + false + ;; + esac +} + +echo "Releasing metapy-${version}..." +confirm || exit 1 + +echo "Creating source distribution..." +python setup.py sdist --formats=gztar + +echo "Fetching wheels from GitHub release..." +python get-release.py ${version} + +echo "Uploading to PyPI..." +twine upload -s dist/*.{gz,whl} + +echo "Done!" diff --git a/metapy/setup.py b/metapy/setup.py new file mode 100644 index 0000000000..2e6f6e85e8 --- /dev/null +++ b/metapy/setup.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python +from __future__ import print_function + +import contextlib +import os +import platform +import shutil +import subprocess +import sys +import tempfile + +from setuptools import setup, Extension +from setuptools.command import build_ext, bdist_egg, develop +from distutils.spawn import find_executable +from distutils import log, sysconfig +from distutils.command import build + +VERSION = "0.2.13" + +# See: +# http://stackoverflow.com/questions/3223604/how-to-create-a-temporary-directory-and-get-the-path-file-name-in-python +@contextlib.contextmanager +def cd(newdir, cleanup=lambda: True): + previdr = os.getcwd() + os.chdir(os.path.expanduser(newdir)) + try: + yield + finally: + os.chdir(previdr) + cleanup() + +@contextlib.contextmanager +def tempdir(): + dirpath = tempfile.mkdtemp() + def cleanup(): + # see http://stackoverflow.com/questions/2656322/shutil-rmtree-fails-on-windows-with-access-is-denied + def onerror(func, path, exc_info): + import stat + if not os.access(path, os.W_OK): + os.chmod(path, stat.S_IWUSR) + func(path) + else: + raise + + shutil.rmtree(dirpath, onerror=onerror) + with cd(dirpath, cleanup): + yield dirpath + +# Based on https://github.com/symengine/symengine.py/blob/master/setup.py +class CMakeBuildExt(build.build): + user_options = build.build.user_options + \ + [('icu-root=', None, "Path to ICU root"), + ('generator=', None, "CMake build generator")] + + def initialize_options(self): + build.build.initialize_options(self) + self.icu_root = None + self.generator = 'MSYS Makefiles' if platform.system() == 'Windows' else None + + def cmake_build(self): + src_dir = os.path.dirname(os.path.realpath(__file__)) + + cmake_exe = find_executable("cmake") + if not cmake_exe: + raise EnvironmentError("Could not find cmake executable") + + py_version = "{}.{}".format(sys.version_info[0], sys.version_info[1]) + cmake_cmd = [cmake_exe, src_dir, "-DCMAKE_BUILD_TYPE=Release", + "-DMETA_STATIC_UTF=On", "-DBUILD_STATIC_ICU=On"] + + cmake_cmd.append("-DPYTHON_INCLUDE_DIRS={}".format(sysconfig.get_python_inc())) + if platform.system() == 'Windows': + libpython = "libpython{}{}.a".format(sys.version_info[0], + sys.version_info[1]) + libpython_path = os.path.join(sysconfig.get_python_inc(), + '..', 'libs', libpython) + cmake_cmd.append("-DPYTHON_LIBRARY={}".format(libpython_path)) + + if self.icu_root: + cmake_cmd.extend(["-DICU_ROOT={}".format(self.icu_root)]) + + if self.generator: + cmake_cmd.extend(["-G{}".format(self.generator)]) + + with tempdir() as dirpath: + print("Build directory: {}".format(os.getcwd())) + if subprocess.call(cmake_cmd) != 0: + raise EnvironmentError("CMake invocation failed") + + if subprocess.call([cmake_exe, "--build", "."]) != 0: + raise EnvironmentError("CMake build failed") + + if subprocess.call([cmake_exe, "--build", ".", "--target", + "install"]) != 0: + raise EnvironmentError("CMake install failed") + + # Make dummy __init__.py + initpy = os.path.join(src_dir, "dist", "metapy", "__init__.py") + + with open(initpy, "w") as f: + f.write("from .metapy import *\n") + f.write('__version__ = "{}"\n'.format(VERSION)) + + # Copy over extra DLLs on Windows + if platform.system() == 'Windows': + dlls = ['libwinpthread-1.dll', 'libgcc_s_seh-1.dll', 'libstdc++-6.dll', 'zlib1.dll'] + for dll in dlls: + shutil.copyfile(os.path.join("c:", os.sep, "msys64", "mingw64", "bin", dll), + os.path.join(src_dir, "dist", "metapy", dll)) + + def run(self): + self.cmake_build() + return build.build.run(self) + +class DummyBuildExt(build_ext.build_ext): + def __init__(self, *args, **kwargs): + build_ext.build_ext.__init__(self, *args, **kwargs) + + def run(self): + # do nothing; cmake already built the extension + pass + +class DummyBDistEgg(bdist_egg.bdist_egg): + def __init__(self, *args, **kwargs): + bdist_egg.bdist_egg.__init__(self, *args, **kwargs) + + def run(self): + self.run_command("build") + return bdist_egg.bdist_egg.run(self) + +class DummyDevelop(develop.develop): + def __init__(self, *args, **kwargs): + develop.develop.__init__(self, *args, **kwargs) + + def run(self): + self.run_command("build") + return develop.develop.run(self) + +def clean_dist(): + src_dir = os.path.dirname(os.path.realpath(__file__)) + + dist_dir = os.path.join(src_dir, "dist", "metapy") + if os.path.exists(dist_dir): + log.info("Deleting distribution directory {}".format(dist_dir)) + shutil.rmtree(dist_dir) + + os.makedirs(dist_dir) + +clean_dist() + +setup(name = 'metapy', + version = VERSION, + description = 'Python bindings for MeTA', + author = 'Chase Geigle', + author_email = 'geigle1@illinois.edu', + url = 'https://github.com/meta-toolkit/metapy', + license = 'MIT', + packages = ['metapy'], + package_dir = { '': 'dist' }, + include_package_data = True, + cmdclass = { + 'build': CMakeBuildExt, + 'build_ext': DummyBuildExt, + 'bdist_egg': DummyBDistEgg, + 'develop': DummyDevelop + }, + zip_safe = False, + ext_modules = [Extension('metapy', [])], + ext_package='metapy', + classifiers = [ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: MIT License', + 'License :: OSI Approved :: University of Illinois/NCSA Open Source License', + 'Operating System :: POSIX :: Linux', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Scientific/Engineering', + 'Topic :: Scientific/Engineering :: Artificial Intelligence', + 'Topic :: Scientific/Engineering :: Information Analysis', + 'Topic :: Text Processing', + 'Topic :: Text Processing :: Filters', + 'Topic :: Text Processing :: General', + 'Topic :: Text Processing :: Indexing', + 'Topic :: Text Processing :: Linguistic', + ], + keywords = [ + 'NLP', 'natural language processing', + 'IR', 'information retrieval', + 'CL', 'computational lingusitics', + 'parsing', 'tagging', 'tokenizing', 'syntax', 'lingustics', + 'natural language', 'text mining', 'text analysis' + ]) diff --git a/metapy/src/metapy.cpp b/metapy/src/metapy.cpp new file mode 100644 index 0000000000..64c23378d2 --- /dev/null +++ b/metapy/src/metapy.cpp @@ -0,0 +1,76 @@ +/** + * @file metapy.cpp + * @author Chase Geigle + * + * This file defines the metapy module and bindings for the MeTA API. It + * does not attempt to be completely comprehensive at this time (though + * that is an eventual goal), but it aims to provide at least enough of an + * API surface so that interactive web demos can be made. + */ + +#include "metapy_analyzers.h" +#include "metapy_classify.h" +#include "metapy_embeddings.h" +#include "metapy_index.h" +#include "metapy_learn.h" +#include "metapy_parser.h" +#include "metapy_sequence.h" +#include "metapy_stats.h" +#include "metapy_topics.h" + +#include "meta/logging/logger.h" +#include "meta/parser/analyzers/tree_analyzer.h" +#include "meta/sequence/analyzers/ngram_pos_analyzer.h" + +namespace py = pybind11; + +PYBIND11_PLUGIN(metapy) +{ + py::module m{"metapy", "MeTA toolkit python bindings"}; + + meta::sequence::register_analyzers(); + meta::parser::register_analyzers(); + + metapy_bind_index(m); + metapy_bind_analyzers(m); + metapy_bind_learn(m); + metapy_bind_classify(m); + metapy_bind_sequence(m); + metapy_bind_parser(m); + metapy_bind_embeddings(m); + metapy_bind_stats(m); + metapy_bind_topics(m); + + // printing::progress makes this really difficult to reason about. + // Progress updating occurs from a separate thread. This is fine, + // except that we need to use the Python stderr here instead of the + // usual std::cerr. In order to do that, we need the GIL. We run into + // problems when the current thread holds the GIL and then the progress + // thread attempts to acquire it. So, **any function that uses progress + // reporting must release the GIL before being invoked**! + m.def("log_to_stderr", []() { + // separate logging for progress output + meta::logging::add_sink( + {[](const std::string& line) { + py::gil_scoped_acquire gil; + py::module::import("sys").attr("stderr").attr("write")(line); + }, + []() {}, + [](const meta::logging::logger::log_line& ll) { + return ll.severity() + == meta::logging::logger::severity_level::progress; + }, + [](const meta::logging::logger::log_line& ll) { + return " " + ll.str(); + }}); + + meta::logging::add_sink( + {[](const std::string& line) { + py::gil_scoped_acquire gil; + py::module::import("sys").attr("stderr").attr("write")(line); + }, + []() {}, meta::logging::logger::severity_level::trace}); + }); + + return m.ptr(); +} diff --git a/metapy/src/metapy_analyzers.cpp b/metapy/src/metapy_analyzers.cpp new file mode 100644 index 0000000000..dbe060a18e --- /dev/null +++ b/metapy/src/metapy_analyzers.cpp @@ -0,0 +1,477 @@ +/** + * @file metapy_analyzers.cpp + * @author Chase Geigle + * + * This file defines the metapy.analyzers submodule and creates bindings for + * that part of the MeTA API. + */ + +#include +#include +#include + +#include +#include + +#include "metapy_analyzers.h" +#include "metapy_identifiers.h" +#include "metapy_probe_map.h" + +#include "cpptoml.h" +#include "meta/analyzers/all.h" +#include "meta/analyzers/filters/all.h" +#include "meta/analyzers/token_stream.h" +#include "meta/analyzers/tokenizers/character_tokenizer.h" +#include "meta/analyzers/tokenizers/icu_tokenizer.h" +#include "meta/corpus/document.h" +#include "meta/parallel/thread_pool.h" +#include "meta/parser/analyzers/featurizers/all.h" +#include "meta/parser/analyzers/tree_analyzer.h" +#include "meta/sequence/analyzers/ngram_pos_analyzer.h" +#include "meta/util/algorithm.h" + +namespace py = pybind11; +using namespace meta; + +/** + * This class is a "trampoline" class to bounce functions back to Python + * if they are overloaded there rather than in C++ directly. + */ +class py_token_stream + : public util::clonable +{ + public: + virtual std::string next() override + { + PYBIND11_OVERLOAD_PURE(std::string, analyzers::token_stream, next, ); + return ""; + } + + /** + * Determines whether there are more tokens available in the + * stream. + */ + virtual operator bool() const override + { +#if PY_MAJOR_VERSION < 3 + PYBIND11_OVERLOAD_PURE_NAME(bool, analyzers::token_stream, + "__nonzero__", operator bool,); +#else + PYBIND11_OVERLOAD_PURE_NAME(bool, analyzers::token_stream, + "__bool__", operator bool,); +#endif + return false; + } + + /** + * Sets the content for the stream. + * @param content The string content to set + */ + virtual void set_content(std::string&& content) override + { + PYBIND11_OVERLOAD_PURE(void, analyzers::token_stream, set_content, + std::move(content)); + } +}; + +/** + * This class holds a token_stream that was defined in Python, but was + * created using C++. + * + * This is where stuff gets weird. We want our tokenizer_factory to return + * std::unique_ptr when invoked with an id and a config + * group. The problem is that we don't have a good way to get a unique_ptr + * out of Python code if the token stream is defined there, since that + * basically entails having Python relinquish ownership of something, which + * it isn't apt to do. + * + * Instead, what we do is have a separate class that can wrap an object + * created by invoking Python code directly from C++. This doesn't give us + * a unique_ptr, but we can enforce that ourselves directly. The object + * will down convert nicely to a token_stream through pybind11's casting + * utilities, since it is still a token_stream derivative at heart. We just + * can't get at its unique_ptr. We store a py::object to keep the reference + * count > 0, and then a token_stream* that we do all of the actual work + * with. We have to override all of the virtual functions again, but that + * isn't too much work. + * + * Since we're not using the PYBIND11_OVERLOAD functions anymore (since + * this object isn't the one registered with Python), we have to be careful + * with the GIL. Each function here acquires the GIL immediately before + * doing anything else so that hitting Python is safely behind the lock. + * This means things are going to be a lot slower, of course, but it's the + * only way I can think of for doing this safely for now. + * + * We also want to be able to clone token_streams, since that's how we set + * up the pipeline replicas across all of the threads. We can do that by + * providing a copy constructor that calls into Python by invoking + * `copy.deepcopy(obj)` to copy our current Python object. + * + * Finally, our destructor is weird since we want to decrement the object's + * reference count while still inside the GIL. + */ +class cpp_created_py_token_stream + : public util::clonable +{ + public: + cpp_created_py_token_stream(py::object obj) + : obj_{obj}, stream_{obj_.cast()} + { + // nothing + } + + cpp_created_py_token_stream(const cpp_created_py_token_stream& other) + { + py::gil_scoped_acquire acq; + auto deepcopy = py::module::import("copy").attr("deepcopy"); + obj_ = deepcopy.cast()(other.obj_); + stream_ = obj_.cast(); + } + + virtual std::string next() override + { + py::gil_scoped_acquire acq; + return stream_->next(); + } + + virtual operator bool() const override + { + py::gil_scoped_acquire acq; + return *stream_; + } + + virtual void set_content(std::string&& content) override + { + py::gil_scoped_acquire acq; + stream_->set_content(std::move(content)); + } + + ~cpp_created_py_token_stream() + { + py::gil_scoped_acquire acq; + obj_.release().dec_ref(); + } + + private: + py::object obj_; + token_stream* stream_; +}; + +/** + * Registers a Python object with a factory. + * + * There are two major assumptions here. First, we assume that the *Class* + * object passed here has an "id" property, just like we assume the MeTA + * classes do in C++. + * + * We have to do a bit of trickery here, though. The factories typically + * map util::string_view to creation functions. This is fine in the C++ + * code, since every id ends up being a static C string somewhere in the + * data segment. But here, the ids are in Python and are dynamically + * allocated. To save ourselves headache and prevent UB, we have a static + * function level cache here to store the strings we've added to the + * factories so that the util::string_view will be valid. + * + * There's probably a better way of doing this, but this currently works. + */ +template +void py_factory_register(py::object cls, FactoryType& factory, + CreationFunction&& c_fun) +{ + static std::vector ids; + static std::mutex mut; + util::string_view id; + { + std::lock_guard lock{mut}; + ids.push_back(cls.attr("id").cast()); + id = ids.back(); + } + std::cerr << "filter_factory adding " << id << std::endl; + factory.add(id, c_fun); +} + +class py_analyzer : public util::clonable +{ + virtual void tokenize(const corpus::document& doc, + analyzers::featurizer& counts) override + { + PYBIND11_OVERLOAD_PURE(void, analyzers::analyzer, tokenize, doc, + counts); + } +}; + +template +void make_token_stream(TokenStream& next, const analyzers::token_stream& prev, + Args... args) +{ + new (&next) TokenStream(prev.clone(), args...); +} + +template +py::object ngram_analyze(NGramAnalyzer& ana, const corpus::document& doc) +{ + if (ana.n_value() == 1) + return py::cast(ana.template analyze(doc)); + + auto ngrams = ana.template analyze(doc); + + py::dict ret; + for (const auto& kv : ngrams) + { + const auto& key = kv.key(); + + using iterator = decltype(key.begin()); + + py::tuple newkey{ana.n_value()}; + uint64_t idx = 0; + util::for_each_token(key.begin(), key.end(), "_", + [&](iterator first, iterator last) { + if (first != last) + newkey[idx++] = py::str({first, last}); + }); + ret[newkey] = py::cast(kv.value()); + } + + return ret; +} + +/** + * A visitor class for converting a TOML configuration group to a Python + * dictionary. We use this to convert TOML tables to keyword arguments for + * token_streams defined in Python. + */ +class py_toml_visitor +{ + public: + template + void visit(const cpptoml::value& v, py::object& obj) + { + obj = py::cast(v.get()); + } + + void visit(const cpptoml::table& table, py::object& obj) + { + obj = py::dict(); + auto dict = obj.cast(); + + for (const auto& pr : table) + { + auto key = py::cast(pr.first); + py::object value; + pr.second->accept(*this, value); + dict[key] = value; + } + } + + void visit(const cpptoml::array& arr, py::object& obj) + { + obj = py::list(); + auto lst = obj.cast(); + for (const auto& val : arr) + { + py::object value; + val->accept(*this, value); + lst.append(value); + } + } + + void visit(const cpptoml::table_array& tarr, py::object& obj) + { + obj = py::list(); + auto lst = obj.cast(); + for (const auto& table : tarr) + { + py::object value; + table->accept(*this, value); + lst.append(value); + } + } +}; + +class py_token_stream_iterator +{ + analyzers::token_stream& stream_; + py::object ref_; + + public: + py_token_stream_iterator(analyzers::token_stream& stream, py::object ref) + : stream_(stream), ref_(ref) + { + // nothing + } + + std::string next() + { + if (!stream_) + throw py::stop_iteration(); + return stream_.next(); + } +}; + +void metapy_bind_analyzers(py::module& m) +{ + using namespace analyzers; + + auto m_ana = m.def_submodule("analyzers"); + + py::class_ ts_base{m_ana, "TokenStream"}; + ts_base.def(py::init<>()) + .def("next", + [](token_stream& ts) { + if (!ts) + throw py::stop_iteration(); + return ts.next(); + }) + .def("set_content", + [](token_stream& ts, std::string str) { + ts.set_content(std::move(str)); + }) + .def("__bool__", [](token_stream& ts) { return static_cast(ts); }) + .def("__iter__", + [](py::object ts) { + return py_token_stream_iterator(ts.cast(), ts); + }) + .def("__deepcopy__", + [](token_stream& ts, py::dict&) { return ts.clone(); }); + + py::class_(ts_base, "Iterator") + .def("__iter__", + [](py_token_stream_iterator& it) -> py_token_stream_iterator& { + return it; + }) + .def("__next__", &py_token_stream_iterator::next); + + // tokenizers + py::class_{m_ana, "CharacterTokenizer", + ts_base} + .def(py::init<>()); + + py::class_{m_ana, "ICUTokenizer", ts_base}.def( + py::init(), + "Creates a tokenizer using the UTF text segmentation standard", + // hack around g++ 4.8 ambiguous overloaded operator= + py::arg_t{"suppress_tags", false}); + // py::arg("suppress_tags") = false); + + // filters + py::class_{m_ana, "AlphaFilter", ts_base}.def( + "__init__", &make_token_stream); + + py::class_{m_ana, "EmptySentenceFilter", + ts_base} + .def("__init__", &make_token_stream); + + py::class_{m_ana, "EnglishNormalizer", ts_base} + .def("__init__", &make_token_stream); + + py::class_{m_ana, "ICUFilter", ts_base}.def( + "__init__", + &make_token_stream); + + py::class_{m_ana, "LengthFilter", ts_base}.def( + "__init__", + &make_token_stream, + py::arg("source"), py::arg("min"), py::arg("max")); + + py::class_ list_filter{m_ana, "ListFilter", ts_base}; + py::enum_{list_filter, "Type"} + .value("Accept", filters::list_filter::type::ACCEPT) + .value("Reject", filters::list_filter::type::REJECT); + list_filter.def("__init__", + &make_token_stream); + + py::class_{m_ana, "LowercaseFilter", ts_base} + .def("__init__", &make_token_stream); + + py::class_{m_ana, "Porter2Filter", ts_base}.def( + "__init__", &make_token_stream); + + py::class_{m_ana, "PennTreebankNormalizer", + ts_base} + .def("__init__", &make_token_stream); + + py::class_{m_ana, "SentenceBoundaryAdder", + ts_base} + .def("__init__", &make_token_stream); + + // analyzers + py::class_ analyzer_base{m_ana, + "Analyzer"}; + analyzer_base.def(py::init<>()) + .def("analyze", &analyzer::analyze) + .def("featurize", &analyzer::analyze); + + py::class_{m_ana, "NGramWordAnalyzer", analyzer_base} + .def("__init__", + [](ngram_word_analyzer& ana, uint16_t n, const token_stream& ts) { + new (&ana) ngram_word_analyzer(n, ts.clone()); + }) + .def("analyze", &ngram_analyze) + .def("featurize", &ngram_analyze); + + py::class_{m_ana, "NGramPOSAnalyzer", analyzer_base} + .def("__init__", + [](ngram_pos_analyzer& ana, uint16_t n, const token_stream& ts, + const std::string& crf_prefix) { + py::gil_scoped_release rel; + new (&ana) ngram_pos_analyzer(n, ts.clone(), crf_prefix); + }) + .def("analyze", &ngram_analyze) + .def("featurize", &ngram_analyze); + + py::class_ py_tree_feat{m_ana, "TreeFeaturizer"}; + py_tree_feat.def("tree_tokenize", &tree_featurizer::tree_tokenize); + + py::class_{m_ana, "BranchFeaturizer", py_tree_feat}.def( + py::init<>()); + py::class_{m_ana, "DepthFeaturizer", py_tree_feat}.def( + py::init<>()); + py::class_{m_ana, "SemiSkeletonFeaturizer", + py_tree_feat} + .def(py::init<>()); + py::class_{m_ana, "SkeletonFeaturizer", py_tree_feat} + .def(py::init<>()); + py::class_{m_ana, "SubtreeFeaturizer", py_tree_feat} + .def(py::init<>()); + py::class_{m_ana, "TagFeaturizer", py_tree_feat}.def( + py::init<>()); + + py::class_{m_ana, "TreeAnalyzer", analyzer_base} + .def("__init__", + [](tree_analyzer& ana, const token_stream& ts, + const std::string& tagger_prefix, + const std::string& parser_prefix) { + py::gil_scoped_release rel; + new (&ana) + tree_analyzer(ts.clone(), tagger_prefix, parser_prefix); + }) + .def("add", [](tree_analyzer& ana, const tree_featurizer& featurizer) { + ana.add(featurizer.clone()); + }); + + py::class_{m_ana, "MultiAnalyzer", analyzer_base}; + + m_ana.def("load", [](const std::string& filename) { + py::gil_scoped_release rel; + auto config = cpptoml::parse_file(filename); + return analyzers::load(*config); + }); + + m_ana.def("register_filter", [](py::object cls) { + py_factory_register(cls, filter_factory::get(), + [=](std::unique_ptr source, + const cpptoml::table& cfg) { + py::gil_scoped_acquire acq; + + py::dict kwargs; + py_toml_visitor vtor; + cfg.accept(vtor, kwargs); + PyDict_DelItemString(kwargs.ptr(), "type"); + + return make_unique( + cls(source->clone(), **kwargs)); + }); + }); +} diff --git a/metapy/src/metapy_classify.cpp b/metapy/src/metapy_classify.cpp new file mode 100644 index 0000000000..0f13b08433 --- /dev/null +++ b/metapy/src/metapy_classify.cpp @@ -0,0 +1,602 @@ +/** + * @file metapy_classify.cpp + * @author Chase Geigle + */ + +#include +#include +#include +#include + +#include "cpptoml.h" +#include "meta/classify/binary_dataset_view.h" +#include "meta/classify/classifier/all.h" +#include "meta/classify/kernel/all.h" +#include "meta/index/ranker/ranker_factory.h" +#include "meta/learn/dataset.h" +#include "meta/learn/loss/loss_function_factory.h" +#include "meta/logging/logger.h" +#include "meta/util/iterator.h" +#include "metapy_classify.h" +#include "metapy_identifiers.h" +#include "metapy_learn.h" + +namespace py = pybind11; +using namespace meta; + +template +class py_binary_classifier : public ClassifierBase +{ + public: + double predict(const learn::feature_vector& instance) const override + { + PYBIND11_OVERLOAD_PURE(double, ClassifierBase, predict, instance); + return 0; + } + + void save(std::ostream& /* os */) const override + { + throw std::runtime_error{ + "cannot serialize python-defined binary classifiers"}; + } +}; + +class py_online_binary_classifier + : public py_binary_classifier +{ + public: + void train(dataset_view_type docs) override + { + PYBIND11_OVERLOAD_PURE(void, classify::online_binary_classifier, train, + docs); + } + + void train_one(const feature_vector& doc, bool label) override + { + PYBIND11_OVERLOAD_PURE(void, classify::online_binary_classifier, + train_one, doc, label); + } +}; + +template +class py_classifier : public ClassifierBase +{ + public: + class_label classify(const learn::feature_vector& instance) const override + { + PYBIND11_OVERLOAD_PURE(class_label, ClassifierBase, classify, instance); + return "[none]"_cl; + } + + void save(std::ostream& /* os */) const override + { + throw std::runtime_error{ + "cannot serialize python-defined multiclass classifiers"}; + } +}; + +class py_online_classifier : public py_classifier +{ + public: + void train(dataset_view_type docs) override + { + PYBIND11_OVERLOAD_PURE(void, classify::online_classifier, train, docs); + } + + void train_one(const feature_vector& doc, const class_label& lbl) override + { + PYBIND11_OVERLOAD_PURE(void, classify::online_classifier, train_one, + doc, lbl); + } +}; + +class py_kernel : public classify::kernel::kernel +{ + public: + double operator()(const learn::feature_vector& first, + const learn::feature_vector& second) const override + { + PYBIND11_OVERLOAD_PURE_NAME(double, classify::kernel::kernel, + "__call__", operator(), first, second); + return 0; + } + + void save(std::ostream& /* os */) const override + { + throw std::runtime_error{"cannot serialize python-defined kernels"}; + } +}; + +/** + * This class holds a binary_classifier that was created by invoking + * Python code. + * + * We need to be able to supply a function to the ensemble methods (e.g. + * one_vs_all) that creates a std::unique_ptr from a + * binary_dataset_view. We can't get std::unique_ptrs from Python code + * directly. Instead, we grab a reference to the py::object that Python + * created for us, and make a unique_ptr to this class that contains it and + * just forwards the calls to the classifier by converting that py::object + * to a binary_classifier reference. + */ +class cpp_created_py_binary_classifier + : public classify::online_binary_classifier +{ + public: + cpp_created_py_binary_classifier(py::object cls) : cls_{cls} + { + // nothing + } + + double predict(const learn::feature_vector& instance) const override + { + return cls_.cast().predict(instance); + } + + void save(std::ostream& os) const override + { + cls_.cast().save(os); + } + + void train(classify::binary_dataset_view bdv) override + { + cls_.cast().train(bdv); + } + + void train_one(const learn::feature_vector& instance, bool label) override + { + cls_.cast().train_one(instance, + label); + } + + private: + py::object cls_; +}; + +void metapy_bind_classify(py::module& m) +{ + auto pydset = (py::object)m.attr("learn").attr("Dataset"); + auto pydset_view = (py::object)m.attr("learn").attr("DatasetView"); + auto m_classify = m.def_submodule("classify"); + + // binary datasets/views + py::class_{m_classify, "BinaryDataset", pydset} + .def("__init__", + [](classify::binary_dataset& dset, + const std::shared_ptr& fidx, + std::function labeler) { + py::gil_scoped_release release; + new (&dset) classify::binary_dataset(fidx, labeler); + }) + .def("__init__", + [](classify::binary_dataset& dset, + const std::shared_ptr& fidx, + const std::vector& docs, + std::function labeler) { + py::gil_scoped_release release; + new (&dset) classify::binary_dataset(fidx, docs, labeler); + }) + .def("__init__", + [](classify::binary_dataset& dset, py::list& data, + std::size_t total_features, py::function& featurizer, + py::function& labeler) { + new (&dset) classify::binary_dataset( + data.begin(), data.end(), total_features, + [&](py::handle obj) { + return py::cast( + featurizer(obj)); + }, + [&](py::handle obj) { + return py::cast(labeler(obj)); + }); + }) + .def("label", &classify::binary_dataset::label) + .def("__getitem__", + [](const classify::binary_dataset& dset, int64_t offset) { + std::size_t idx = offset >= 0 + ? static_cast(offset) + : dset.size() + offset; + if (idx >= dset.size()) + throw py::index_error(); + return *(dset.begin() + idx); + }) + .def("__getitem__", + [](const classify::binary_dataset& bdset, py::slice slice) { + classify::binary_dataset_view bdv{bdset}; + return make_sliced_dataset_view(bdv, slice); + }, + py::keep_alive<0, 1>()); + + py::class_{m_classify, "BinaryDatasetView", + pydset_view} + .def(py::init(), + py::keep_alive<0, 1>()) + .def("__getitem__", + [](const classify::binary_dataset_view& dv, int64_t offset) { + std::size_t idx = offset >= 0 + ? static_cast(offset) + : dv.size() + offset; + if (idx >= dv.size()) + throw py::index_error(); + return *(dv.begin() + idx); + }) + .def("__getitem__", + [](const classify::binary_dataset_view& bdv, py::slice slice) { + return make_sliced_dataset_view(bdv, slice); + }, + py::keep_alive<0, 1>()); + + py::implicitly_convertible(); + + // multiclass datasets/views + py::class_{m_classify, "MulticlassDataset", + pydset} + .def("__init__", + [](classify::multiclass_dataset& dset, + const std::shared_ptr& fidx) { + py::gil_scoped_release release; + new (&dset) classify::multiclass_dataset(fidx); + }) + .def("__init__", + [](classify::multiclass_dataset& dset, + const std::shared_ptr& fidx, + const std::vector& docs) { + py::gil_scoped_release release; + new (&dset) classify::multiclass_dataset(fidx, docs); + }) + .def("__init__", + [](classify::multiclass_dataset& dset, py::list& data, + std::size_t total_features, py::function& featurizer, + py::function& labeler) { + new (&dset) classify::multiclass_dataset( + data.begin(), data.end(), total_features, + [&](py::handle obj) { + return py::cast( + featurizer(obj)); + }, + [&](py::handle obj) { + return py::cast(labeler(obj)); + }); + }) + .def("label", + [](const classify::multiclass_dataset& dset, + const learn::instance& inst) { return dset.label(inst); }) + .def("total_labels", &classify::multiclass_dataset::total_labels) + .def("label_id_for", &classify::multiclass_dataset::label_id_for) + .def("label_for", &classify::multiclass_dataset::label_for) + .def("__getitem__", + [](const classify::multiclass_dataset& dset, int64_t offset) { + std::size_t idx = offset >= 0 + ? static_cast(offset) + : dset.size() + offset; + if (idx >= dset.size()) + throw py::index_error(); + return *(dset.begin() + idx); + }) + .def("__getitem__", + [](const classify::multiclass_dataset& dset, py::slice slice) { + classify::multiclass_dataset_view mdv{dset}; + return make_sliced_dataset_view(mdv, slice); + }, + py::keep_alive<0, 1>()); + + py::class_{ + m_classify, "MulticlassDatasetView", pydset_view} + .def(py::init(), + py::keep_alive<0, 1>()) + .def("__getitem__", + [](const classify::multiclass_dataset_view& dv, int64_t offset) { + std::size_t idx = offset >= 0 + ? static_cast(offset) + : dv.size() + offset; + if (idx >= dv.size()) + throw py::index_error(); + return *(dv.begin() + idx); + }) + .def("__getitem__", + [](const classify::multiclass_dataset_view& mdv, py::slice slice) { + return make_sliced_dataset_view(mdv, slice); + }, + py::keep_alive<0, 1>()) + .def("total_labels", &classify::multiclass_dataset_view::total_labels) + .def("label", &classify::multiclass_dataset_view::label) + .def("labels", + [](const classify::multiclass_dataset_view& self) { + return py::make_iterator(self.labels_begin(), + self.labels_end()); + }, + py::keep_alive<0, 1>()) + .def("create_even_split", + [](const classify::multiclass_dataset_view& mdv) { + return mdv.create_even_split(); + }, + py::keep_alive<0, 1>()); + + py::implicitly_convertible(); + + // confusion matrix + py::class_{m_classify, "ConfusionMatrix"} + .def(py::init<>()) + .def("add", &classify::confusion_matrix::add, py::arg("predicted"), + py::arg("actual"), py::arg("num_times") = 1) + .def("add_fold_accuracy", + &classify::confusion_matrix::add_fold_accuracy) + .def("fold_accuracy", &classify::confusion_matrix::fold_accuracy) + .def("print_stats", + [](const classify::confusion_matrix& matrix) { + std::stringstream ss; + matrix.print_stats(ss); + py::print(ss.str()); + }) + .def("__str__", + [](const classify::confusion_matrix& matrix) { + std::stringstream ss; + matrix.print(ss); + return ss.str(); + }) + .def("print", + [](py::object self) { py::print(self.attr("__str__")()); }) + .def("print_result_pairs", + [](const classify::confusion_matrix& matrix) { + std::stringstream ss; + matrix.print_result_pairs(ss); + py::print(ss.str()); + }) + .def("predictions", &classify::confusion_matrix::predictions) + .def("accuracy", &classify::confusion_matrix::accuracy) + .def("f1_score", + [](const classify::confusion_matrix& matrix) { + return matrix.f1_score(); + }) + .def("f1_score", + [](const classify::confusion_matrix& matrix, + const class_label& lbl) { return matrix.f1_score(lbl); }) + .def("precision", + [](const classify::confusion_matrix& matrix) { + return matrix.precision(); + }) + .def("precision", + [](const classify::confusion_matrix& matrix, + const class_label& lbl) { return matrix.precision(lbl); }) + .def("recall", + [](const classify::confusion_matrix& matrix) { + return matrix.recall(); + }) + .def("recall", + [](const classify::confusion_matrix& matrix, + const class_label& lbl) { return matrix.recall(lbl); }) + .def(py::self + py::self) + .def(py::self += py::self) + .def_static("mcnemar_significant", + &classify::confusion_matrix::mcnemar_significant); + + // kernels + auto m_kernel = m_classify.def_submodule("kernel"); + py::class_ pykernel{m_classify, + "Kernel"}; + pykernel.def("__call__", &classify::kernel::kernel::operator()); + + py::class_{m_kernel, "Polynomial", pykernel} + .def(py::init(), + py::arg("power") = classify::kernel::polynomial::default_power, + py::arg("c") = classify::kernel::polynomial::default_c) + .def_property_readonly_static( + "id", + [](py::object /* self */) { + return classify::kernel::polynomial::id.to_string(); + }) + .def_readonly_static("default_power", + &classify::kernel::polynomial::default_power) + .def_readonly_static("default_c", + &classify::kernel::polynomial::default_c); + + py::class_{m_kernel, "RadialBasis", + pykernel} + .def(py::init(), py::arg("gamma")) + .def_property_readonly_static("id", [](py::object /* self */) { + return classify::kernel::radial_basis::id.to_string(); + }); + + py::class_{m_kernel, "Sigmoid", pykernel} + .def(py::init(), py::arg("alpha"), py::arg("c")) + .def_property_readonly_static("id", [](py::object /* self */) { + return classify::kernel::sigmoid::id.to_string(); + }); + + // binary classifiers + py::class_> pybincls{ + m_classify, "BinaryClassifier"}; + pybincls.def("classify", &classify::binary_classifier::classify) + .def("predict", &classify::binary_classifier::predict); + + py::class_ + py_online_bincls{m_classify, "OnlineBinaryClassifier", pybincls}; + py_online_bincls.def("train", &classify::online_binary_classifier::train) + .def("train_one", &classify::online_binary_classifier::train_one); + + py::class_{m_classify, "SGD", py_online_bincls} + .def_property_readonly_static( + "id", + [](py::object /* self */) { return classify::sgd::id.to_string(); }) + .def_readonly_static("default_gamma", &classify::sgd::default_gamma) + .def_readonly_static("default_max_iter", + &classify::sgd::default_max_iter) + .def("__init__", + [](classify::sgd& cls, classify::binary_dataset_view training, + const std::string& loss_id, + learn::sgd_model::options_type options, double gamma, + std::size_t max_iter, bool calibrate) { + // release the GIL before training the classifier; this + // allows other threads inside an ensemble method to train + // simultaneiously + py::gil_scoped_release rel; + new (&cls) classify::sgd( + training, learn::loss::make_loss_function(loss_id), + options, gamma, max_iter, calibrate); + }, + py::arg("training"), py::arg("loss_id"), + py::arg("options") = learn::sgd_model::options_type{}, + py::arg("gamma") = classify::sgd::default_gamma, + py::arg("max_iter") = classify::sgd::default_max_iter, + py::arg("calibrate") = true); + + // multiclass classifiers + py::class_> pycls{m_classify, + "Classifier"}; + pycls.def("classify", &classify::classifier::classify) + .def("test", &classify::classifier::test); + + py::class_ py_online_cls{ + m_classify, "OnlineClassifier", pycls}; + py_online_cls.def("train", &classify::online_classifier::train) + .def("train_one", &classify::online_classifier::train_one); + + py::class_{m_classify, "DualPerceptron", pycls} + .def("__init__", + [](classify::dual_perceptron& cls, + classify::multiclass_dataset_view training, + const classify::kernel::kernel& kernel, double alpha, + double gamma, double bias, uint64_t max_iter) { + std::stringstream ss; + kernel.save(ss); + + new (&cls) classify::dual_perceptron( + std::move(training), classify::kernel::load_kernel(ss), + alpha, gamma, bias, max_iter); + }, + py::arg("training"), py::arg("kernel"), + py::arg("alpha") = classify::dual_perceptron::default_alpha, + py::arg("gamma") = classify::dual_perceptron::default_gamma, + py::arg("bias") = classify::dual_perceptron::default_bias, + py::arg("max_iter") = classify::dual_perceptron::default_max_iter) + .def_readonly_static("default_alpha", + &classify::dual_perceptron::default_alpha) + .def_readonly_static("default_gamma", + &classify::dual_perceptron::default_gamma) + .def_readonly_static("default_bias", + &classify::dual_perceptron::default_bias) + .def_readonly_static("default_max_iter", + &classify::dual_perceptron::default_max_iter); + + py::class_{m_classify, "KNN", pycls}.def( + "__init__", + [](classify::knn& cls, classify::multiclass_dataset_view training, + std::shared_ptr idx, uint16_t k, + const index::ranker& ranker, bool weighted) { + std::stringstream ss; + ranker.save(ss); + + new (&cls) classify::knn(std::move(training), std::move(idx), k, + index::load_ranker(ss), weighted); + }, + py::arg("training"), py::arg("inv_idx"), py::arg("k"), + py::arg("ranker"), py::arg("weighted") = false); + + py::class_{m_classify, "LogisticRegression", + pycls} + .def(py::init(), + py::arg("training"), + py::arg("options") = learn::sgd_model::options_type{}, + py::arg("gamma") = classify::sgd::default_gamma, + py::arg("max_iter") = classify::sgd::default_max_iter) + .def("predict", &classify::logistic_regression::predict); + + py::class_{m_classify, "NaiveBayes", pycls} + .def(py::init(), + py::arg("training"), + py::arg("alpha") = classify::naive_bayes::default_alpha, + py::arg("beta") = classify::naive_bayes::default_beta) + .def_readonly_static("default_alpha", + &classify::naive_bayes::default_alpha) + .def_readonly_static("default_beta", + &classify::naive_bayes::default_beta); + + py::class_{m_classify, "NearestCentroid", pycls} + .def(py::init>(), + py::arg("training"), py::arg("inv_idx")); + + py::class_{m_classify, "OneVsAll", py_online_cls}.def( + "__init__", + [](classify::one_vs_all& ova, classify::multiclass_dataset_view mdv, + py::object cls, py::kwargs kwargs) { + + auto creator = [=](const classify::binary_dataset_view& bdv) { + // must acquire the GIL before calling back into Python + // code to construct the classifier + py::gil_scoped_acquire acq; + return make_unique( + cls(bdv, **kwargs)); + }; + + // release the GIL so that it can be re-acquired in the threads + // that are spawned to create the sub-classifiers + py::gil_scoped_release rel; + new (&ova) classify::one_vs_all(std::move(mdv), std::move(creator)); + }); + + py::class_{m_classify, "OneVsOne", py_online_cls}.def( + "__init__", + [](classify::one_vs_one& ovo, classify::multiclass_dataset_view mdv, + py::object cls, py::kwargs kwargs) { + + auto creator = [=](const classify::binary_dataset_view& bdv) { + // must acquire the GIL before calling back into Python + // code to construct the classifier + py::gil_scoped_acquire acq; + return make_unique( + cls(bdv, **kwargs)); + }; + + // release the GIL so that it can be re-acquired in the threads + // that are spawned to create the sub-classifiers + py::gil_scoped_release rel; + new (&ovo) classify::one_vs_one(std::move(mdv), std::move(creator)); + }); + + py::class_{m_classify, "Winnow", pycls} + .def(py::init(), + py::arg("training"), py::arg("m") = classify::winnow::default_m, + py::arg("gamma") = classify::winnow::default_gamma, + py::arg("max_iter") = classify::winnow::default_max_iter) + .def_readonly_static("default_m", &classify::winnow::default_m) + .def_readonly_static("default_gamma", &classify::winnow::default_gamma) + .def_readonly_static("default_max_iter", + &classify::winnow::default_max_iter); + + // utility functions + m_classify.def( + "cross_validate", + [](std::function creator, + classify::multiclass_dataset_view mdv, std::size_t k, + bool even_split) { + struct creator_type + { + py::object cls_; + std::function& + creator_; + + creator_type(std::function& creator) + : creator_(creator) + { + // nothing + } + + classify::classifier* + operator()(const classify::multiclass_dataset_view& mdv) + { + cls_ = creator_(mdv); + return cls_.cast(); + } + } maker(creator); + + return classify::cross_validate(maker, mdv, k, even_split); + }, + py::arg("creator"), py::arg("mdv"), py::arg("k"), + py::arg("even_split") = false); +} diff --git a/metapy/src/metapy_embeddings.cpp b/metapy/src/metapy_embeddings.cpp new file mode 100644 index 0000000000..457542323c --- /dev/null +++ b/metapy/src/metapy_embeddings.cpp @@ -0,0 +1,71 @@ +/** + * @file metapy_parser.cpp + * @author Chase Geigle + * + * This file defines the metapy.parser submodule and creates bindings for + * that part of the MeTA API. + */ + +#include +#include +#include +#include + +#include "cpptoml.h" +#include "meta/embeddings/word_embeddings.h" +#include "metapy_embeddings.h" +#include "metapy_identifiers.h" + +namespace py = pybind11; +using namespace meta; + +void metapy_bind_embeddings(py::module& m) +{ + auto m_emb = m.def_submodule("embeddings"); + + using namespace py::literals; + + py::class_{m_emb, "WordEmbeddings"} + .def("at", + [](embeddings::word_embeddings& self, const std::string& term) { + auto emb = self.at(term); + + return py::make_tuple(emb.tid, + py::array(emb.v.size(), emb.v.begin())); + }) + .def("term", [](embeddings::word_embeddings& self, + std::size_t tid) { return self.term(tid).to_string(); }) + .def("top_k", + [](embeddings::word_embeddings& self, + py::array_t + query, + std::size_t k) { + util::array_view avquery{query.data(), + query.size()}; + auto scores = self.top_k(avquery, k); + + std::vector result; + result.reserve(scores.size()); + + std::transform( + scores.begin(), scores.end(), std::back_inserter(result), + [](const embeddings::scored_embedding& se) { + return py::make_tuple( + se.e.tid, py::array(se.e.v.size(), se.e.v.begin()), + se.score); + }); + return result; + }, + "query"_a, "k"_a = 100) + .def("vector_size", &embeddings::word_embeddings::vector_size); + + m_emb.def("load_embeddings", [](const std::string& filename) { + auto config = cpptoml::parse_file(filename); + auto embed_cfg = config->get_table("embeddings"); + if (!embed_cfg) + throw embeddings::word_embeddings_exception{ + "missing [embeddings] configuration in " + filename}; + + return embeddings::load_embeddings(*embed_cfg); + }); +} diff --git a/metapy/src/metapy_index.cpp b/metapy/src/metapy_index.cpp new file mode 100644 index 0000000000..193e1ec4b5 --- /dev/null +++ b/metapy/src/metapy_index.cpp @@ -0,0 +1,408 @@ +/** + * @file metapy_index.cpp + * @author Chase Geigle + * + * This file defines the metapy.index submodule and creates bindings for + * that part of the MeTA API. + */ + +#include + +#include +#include +#include + +#include "metapy_identifiers.h" +#include "metapy_index.h" + +#include "cpptoml.h" +#include "meta/index/eval/ir_eval.h" +#include "meta/index/forward_index.h" +#include "meta/index/inverted_index.h" +#include "meta/index/make_index.h" +#include "meta/index/ranker/all.h" +#include "meta/index/ranker/ranker_factory.h" +#include "meta/index/score_data.h" + +namespace py = pybind11; + +using namespace meta; + +class py_ranking_function : public index::ranking_function +{ + public: + using index::ranking_function::ranking_function; + + float score_one(const meta::index::score_data& sd) override + { + PYBIND11_OVERLOAD_PURE(float, index::ranking_function, score_one, sd); + return 0.0f; + } + + void save(std::ostream&) const override + { + throw std::runtime_error{"cannot serialize python-defined rankers"}; + } +}; + +class py_lm_ranker : public index::language_model_ranker +{ + public: + using index::language_model_ranker::language_model_ranker; + + float smoothed_prob(const index::score_data& sd) const override + { + PYBIND11_OVERLOAD_PURE(float, index::language_model_ranker, + smoothed_prob, sd); + return 0.0f; + } + + float doc_constant(const index::score_data& sd) const override + { + PYBIND11_OVERLOAD_PURE(float, index::language_model_ranker, + doc_constant, sd); + return 0.0f; + } + + void save(std::ostream&) const override + { + throw std::runtime_error{"cannot serialize python-defined rankers"}; + } +}; + +void metapy_bind_index(py::module& m) +{ + py::module m_idx = m.def_submodule("index"); + + py::class_{m_idx, "Document"} + .def(py::init(), + py::arg("d_id") = doc_id{0}, + py::arg("label") = class_label{"[NONE]"}) + .def("label", [](const corpus::document& doc) { return doc.label(); }, + "Gets the label for the document") + .def("label", [](corpus::document& doc, + const class_label& label) { doc.label(label); }, + "Sets the label for the document") + .def("content", + [](const corpus::document& doc) { return doc.content(); }, + "Gets the content of the document") + .def( + "content", + [](corpus::document& doc, const std::string& content, + const std::string& encoding) { doc.content(content, encoding); }, + "Sets the content of the document", py::arg("content"), + py::arg("encoding") = std::string{"utf-8"}) + .def("encoding", + [](const corpus::document& doc) { return doc.encoding(); }, + "Gets the encoding for the document's content") + .def("encoding", + [](corpus::document& doc, const std::string& encoding) { + doc.encoding(encoding); + }, + "Sets the encoding for the document's content") + .def("id", &corpus::document::id) + .def("contains_content", &corpus::document::contains_content); + + py::class_{m_idx, "Metadata"}.def( + "get", + [](corpus::metadata& md, const std::string& name) -> py::object { + using field_type = corpus::metadata::field_type; + + py::object ret; + const auto& schema = md.schema(); + + // find the entry for this field name if it exists + for (uint64_t i = 0; i < schema.size(); ++i) + { + if (schema[i].name == name) + { + switch (schema[i].type) + { + case field_type::SIGNED_INT: + { + auto val = md.get(name); + if (val) + return py::cast(*val); + break; + } + + case field_type::UNSIGNED_INT: + { + auto val = md.get(name); + if (val) + return py::cast(*val); + break; + } + + case field_type::DOUBLE: + { + auto val = md.get(name); + if (val) + return py::cast(*val); + break; + } + + case field_type::STRING: + { + auto val = md.get(name); + if (val) + return py::cast(*val); + break; + } + } + + return py::cast(nullptr); + } + } + + return py::cast(nullptr); + }, + "Returns the metadata value for a given field name"); + + py::class_>{ + m_idx, "DiskIndex"} + .def("index_name", &index::disk_index::index_name) + .def("num_docs", &index::disk_index::num_docs) + .def("docs", &index::disk_index::docs) + .def("doc_size", &index::disk_index::doc_size) + .def("label", &index::disk_index::label) + .def("lbl_id", &index::disk_index::lbl_id) + .def("class_label_from_id", &index::disk_index::class_label_from_id) + .def("num_labels", &index::disk_index::num_labels) + .def("class_labels", &index::disk_index::class_labels) + .def("metadata", [](index::disk_index& idx, + doc_id d_id) { return idx.metadata(d_id); }, + "Extract the metadata for a document", py::keep_alive<0, 1>()) + .def("unique_terms", + [](const index::disk_index& idx) { return idx.unique_terms(); }) + .def("unique_terms", [](const index::disk_index& idx, + doc_id did) { return idx.unique_terms(did); }) + .def("get_term_id", &index::disk_index::get_term_id) + .def("term_text", &index::disk_index::term_text); + + py::class_>{m_idx, "InvertedIndex"} + .def("tokenize", &index::inverted_index::tokenize) + .def("doc_freq", &index::inverted_index::doc_freq) + .def("term_freq", &index::inverted_index::term_freq) + .def("total_corpus_terms", &index::inverted_index::total_corpus_terms) + .def("total_num_occurences", + &index::inverted_index::total_num_occurences) + .def("avg_doc_length", &index::inverted_index::avg_doc_length); + + m_idx.def("make_inverted_index", + [](const std::string& filename) { + py::gil_scoped_release rel; + auto config = cpptoml::parse_file(filename); + return index::make_index(*config); + }, + "Builds or loads an inverted index from disk"); + + py::class_>{m_idx, "ForwardIndex"} + .def("liblinear_data", &index::forward_index::liblinear_data) + .def("tokenize", &index::forward_index::tokenize); + + m_idx.def("make_forward_index", [](const std::string& filename) { + py::gil_scoped_release rel; + auto config = cpptoml::parse_file(filename); + return index::make_index(*config); + }); + + py::class_ rank_base{m_idx, "Ranker"}; + rank_base + .def("score", + [](index::ranker& ranker, index::inverted_index& idx, + const corpus::document& query, uint64_t num_results, + const index::ranker::filter_function_type& filter) { + return ranker.score(idx, query, num_results, filter); + }, + "Scores the documents in the inverted index with respect to the " + "query using this ranker", + py::arg("idx"), py::arg("query"), py::arg("num_results") = 10, + py::arg("filter") + = std::function([](doc_id) { return true; })) + .def("score", + [](index::ranker& ranker, index::inverted_index& idx, + std::unordered_map& query, + uint64_t num_results, + const index::ranker::filter_function_type& filter) { + return ranker.score(idx, query.begin(), query.end(), + num_results, filter); + + }, + py::arg("idx"), py::arg("query"), py::arg("num_results") = 10, + py::arg("filter") + = std::function([](doc_id) { return true; })) + .def("score", + [](index::ranker& ranker, index::inverted_index& idx, + std::vector>& query, + uint64_t num_results, + const index::ranker::filter_function_type& filter) { + return ranker.score(idx, query.begin(), query.end(), + num_results, filter); + }, + py::arg("idx"), py::arg("query"), py::arg("num_results") = 10, + py::arg("filter") + = std::function([](doc_id) { return true; })); + + py::class_{m_idx, "ScoreData"} + .def(py::init()) + .def_property_readonly( + "idx", + [](index::score_data& sd) -> index::inverted_index& { + return sd.idx; + }) + .def_readwrite("avg_dl", &index::score_data::avg_dl) + .def_readwrite("num_docs", &index::score_data::num_docs) + .def_readwrite("total_terms", &index::score_data::total_terms) + .def_readwrite("query_length", &index::score_data::query_length) + .def_readwrite("t_id", &index::score_data::t_id) + .def_readwrite("query_term_weight", + &index::score_data::query_term_weight) + .def_readwrite("doc_count", &index::score_data::doc_count) + .def_readwrite("corpus_term_count", + &index::score_data::corpus_term_count) + .def_readwrite("d_id", &index::score_data::d_id) + .def_readwrite("doc_term_count", &index::score_data::doc_term_count) + .def_readwrite("doc_size", &index::score_data::doc_size) + .def_readwrite("doc_unique_terms", + &index::score_data::doc_unique_terms); + + py::class_ rf_base{ + m_idx, "RankingFunction", rank_base}; + + rf_base.def(py::init<>()) + .def("score_one", &index::ranking_function::score_one); + + py::class_ lm_rank_base{ + m_idx, "LanguageModelRanker", rf_base}; + lm_rank_base.def(py::init<>()); + + py::class_{m_idx, "AbsoluteDiscount", + lm_rank_base} + .def(py::init(), + py::arg("delta") = index::absolute_discount::default_delta); + + py::class_{m_idx, "DirichletPrior", lm_rank_base} + .def(py::init(), + py::arg("mu") = index::dirichlet_prior::default_mu); + + py::class_{m_idx, "JelinekMercer", lm_rank_base}.def( + py::init(), + py::arg("lambda") = index::jelinek_mercer::default_lambda); + + py::class_{m_idx, "PivotedLength", rf_base}.def( + py::init(), py::arg("s") = index::pivoted_length::default_s); + + py::class_{m_idx, "OkapiBM25", rf_base}.def( + py::init(), + py::arg("k1") = index::okapi_bm25::default_k1, + py::arg("b") = index::okapi_bm25::default_b, + py::arg("k3") = index::okapi_bm25::default_k3); + + py::class_{m_idx, "KLDivergencePRF", rank_base} + .def(py::init>()) + .def("__init__", + [](index::kl_divergence_prf& kl_div, + std::shared_ptr fwd, + index::language_model_ranker& lm_ranker, float alpha, + float lambda, uint64_t k, uint64_t max_terms) { + // + // TODO: make this less of an absolute hack; will need API + // changes in MeTA + // + // Ideally make ranker subclass util::clonable + // + std::stringstream ss; + lm_ranker.save(ss); + auto lm_ranker_clone = index::load_lm_ranker(ss); + + new (&kl_div) + index::kl_divergence_prf(fwd, std::move(lm_ranker_clone), + alpha, lambda, k, max_terms); + }, + py::arg("fwd"), py::arg("lm_ranker"), + py::arg("alpha") = index::kl_divergence_prf::default_alpha, + py::arg("lambda") = index::kl_divergence_prf::default_lambda, + py::arg("k") = index::kl_divergence_prf::default_k, + py::arg("max_terms") + = index::kl_divergence_prf::default_max_terms); + + py::class_{m_idx, "Rocchio", rank_base} + .def(py::init>()) + .def("__init__", + [](index::rocchio& rocchio, + std::shared_ptr fwd, + index::ranker& initial_ranker, float alpha, float beta, + uint64_t k, uint64_t max_terms) { + // + // TODO: make this less of an absolute hack; will need API + // changes in MeTA + // + // Ideally make ranker subclass util::clonable + // + std::stringstream ss; + initial_ranker.save(ss); + auto ranker_clone = index::load_ranker(ss); + + new (&rocchio) index::rocchio(fwd, std::move(ranker_clone), + alpha, beta, k, max_terms); + }, + py::arg("fwd"), py::arg("initial_ranker"), + py::arg("alpha") = index::rocchio::default_alpha, + py::arg("beta") = index::rocchio::default_beta, + py::arg("k") = index::rocchio::default_k, + py::arg("max_terms") = index::rocchio::default_max_terms); + + py::class_{m_idx, "IREval"} + .def("__init__", + [](index::ir_eval& ev, const std::string& cfg_path) { + new (&ev) index::ir_eval(*cpptoml::parse_file(cfg_path)); + }) + .def("precision", + [](const index::ir_eval& ev, + const index::ir_eval::result_type& results, query_id q_id, + uint64_t num_docs) { + return ev.precision(results, q_id, num_docs); + }, + "Return precision = (#relevant_retrieved / #retrieved)", + py::arg("results"), py::arg("q_id"), + py::arg("num_docs") = std::numeric_limits::max()) + .def("recall", + [](const index::ir_eval& ev, + const index::ir_eval::result_type& results, query_id q_id, + uint64_t num_docs) { + return ev.recall(results, q_id, num_docs); + }, + "Return recall = (#relevant_retrieved / #relevant)", + py::arg("results"), py::arg("q_id"), + py::arg("num_docs") = std::numeric_limits::max()) + .def("f1", + [](const index::ir_eval& ev, + const index::ir_eval::result_type& results, query_id q_id, + uint64_t num_docs, + double beta) { return ev.f1(results, q_id, num_docs, beta); }, + "Return F1 score, a balance between precision and recall", + py::arg("results"), py::arg("q_id"), + py::arg("num_docs") = std::numeric_limits::max(), + py::arg("beta") = 1.0) + .def("ndcg", + [](const index::ir_eval& ev, + const index::ir_eval::result_type& results, query_id q_id, + uint64_t num_docs) { return ev.ndcg(results, q_id, num_docs); }, + "Return normalized discounted cumulative gain score", + py::arg("results"), py::arg("q_id"), + py::arg("num_docs") = std::numeric_limits::max()) + .def("avg_p", + [](index::ir_eval& ev, const index::ir_eval::result_type& results, + query_id q_id, uint64_t num_docs) { + return ev.avg_p(results, q_id, num_docs); + }, + "Return average precision", py::arg("results"), py::arg("q_id"), + py::arg("num_docs") = std::numeric_limits::max()) + .def("map", &index::ir_eval::map) + .def("gmap", &index::ir_eval::gmap) + .def("reset_stats", &index::ir_eval::reset_stats); +} diff --git a/metapy/src/metapy_learn.cpp b/metapy/src/metapy_learn.cpp new file mode 100644 index 0000000000..86f1e72386 --- /dev/null +++ b/metapy/src/metapy_learn.cpp @@ -0,0 +1,246 @@ +/** + * @file metapy_learn.cpp + * @author Chase Geigle + */ + +#include +#include +#include + +#include "cpptoml.h" +#include "meta/learn/dataset.h" +#include "meta/learn/dataset_view.h" +#include "meta/learn/loss/all.h" +#include "meta/learn/sgd.h" +#include "meta/learn/transform.h" +#include "meta/util/iterator.h" +#include "metapy_identifiers.h" +#include "metapy_learn.h" + +namespace py = pybind11; +using namespace meta; + +template +void bind_loss_function(py::module& m, const char* name, Base& base) +{ + py::class_{m, name, base} + .def(py::init<>()) + .def_property_readonly_static("id", [](py::object /* self */) { + return LossFunction::id.to_string(); + }); +} + +struct py_loss_function : public learn::loss::loss_function +{ + double loss(double prediction, double expected) const override + { + PYBIND11_OVERLOAD_PURE(double, learn::loss::loss_function, loss, + prediction, expected); + return 0; + } + + double derivative(double prediction, double expected) const override + { + PYBIND11_OVERLOAD_PURE(double, learn::loss::loss_function, derivative, + prediction, expected); + return 0; + } + + virtual void save(std::ostream& /* os */) const override + { + throw std::runtime_error{ + "cannot serialize python-defined loss functions"}; + } +}; + +void metapy_bind_learn(py::module& m) +{ + auto m_learn = m.def_submodule("learn"); + + py::class_{m_learn, "FeatureVector"} + .def(py::init<>()) + .def(py::init()) + .def(py::init()) + .def("__init__", + [](learn::feature_vector& fv, py::iterable& iter) { + using pair_type = learn::feature_vector::pair_type; + auto cast_fn + = [](py::handle h) { return h.cast(); }; + new (&fv) learn::feature_vector( + util::make_transform_iterator(iter.begin(), cast_fn), + util::make_transform_iterator(iter.end(), cast_fn)); + }) + .def("__len__", &learn::feature_vector::size) + .def("__iter__", + [](learn::feature_vector& fv) { + return py::make_iterator(fv.begin(), fv.end()); + }, + py::keep_alive<0, 1>()) + .def("__getitem__", [](const learn::feature_vector& fv, + learn::feature_id fid) { return fv.at(fid); }) + .def("__setitem__", [](learn::feature_vector& fv, learn::feature_id fid, + double val) { fv[fid] = val; }) + .def("clear", &learn::feature_vector::clear) + .def("shrink_to_fit", &learn::feature_vector::shrink_to_fit) + .def("condense", &learn::feature_vector::condense) + .def("dot", + [](const learn::feature_vector& self, + const learn::feature_vector& other) { + return util::dot_product(self, other); + }) + .def("cosine", + [](const learn::feature_vector& self, + const learn::feature_vector& other) { + return util::cosine_sim(self, other); + }) + .def("l2norm", + [](const learn::feature_vector& self) { + return util::l2norm(self); + }) + .def("__str__", [](const learn::feature_vector& fv) { + std::stringstream ss; + util::string_view padding = ""; + ss << '['; + for (const auto& pr : fv) + { + ss << padding << '(' << pr.first << ", " << pr.second << ')'; + padding = ", "; + } + ss << ']'; + return ss.str(); + }); + + m_learn.def("dot", &util::dot_product); + m_learn.def("cosine", &util::cosine_sim); + m_learn.def("l2norm", [](const learn::feature_vector& vec) { + return util::l2norm(vec); + }); + + py::class_{m_learn, "Instance"} + .def(py::init()) + .def(py::init()) + .def_readonly("id", &learn::instance::id) + .def_readwrite("weights", &learn::instance::weights); + + py::class_ pydset{m_learn, "Dataset"}; + pydset + .def("__init__", + [](learn::dataset& dset, + const std::shared_ptr& fidx) { + py::gil_scoped_release release; + new (&dset) learn::dataset(fidx); + }) + .def("__init__", + [](learn::dataset& dset, + const std::shared_ptr& fidx, + const std::vector& docs) { + py::gil_scoped_release release; + new (&dset) learn::dataset(fidx, docs); + }) + .def("__init__", + [](learn::dataset& dset, py::list& data, + std::size_t total_features, py::function& featurizer) { + new (&dset) + learn::dataset(data.begin(), data.end(), total_features, + [&](py::handle obj) { + return py::cast( + featurizer(obj)); + }); + }) + .def("__getitem__", + [](learn::dataset& dset, int64_t offset) -> learn::instance& { + std::size_t idx = offset >= 0 + ? static_cast(offset) + : dset.size() + offset; + if (idx >= dset.size()) + throw py::index_error(); + return *(dset.begin() + idx); + }, + py::return_value_policy::reference_internal) + .def("__getitem__", + [](learn::dataset& dset, py::slice slice) { + learn::dataset_view dv{dset}; + return make_sliced_dataset_view(dv, slice); + }, + py::keep_alive<0, 1>()) + .def("__len__", &learn::dataset::size) + .def("__iter__", + [](const learn::dataset& dset) { + return py::make_iterator(dset.begin(), dset.end()); + }, + py::keep_alive<0, 1>()) + .def("total_features", &learn::dataset::total_features); + + py::class_{m_learn, "DatasetView"} + .def(py::init(), py::keep_alive<0, 1>()) + .def("shuffle", &learn::dataset_view::shuffle) + .def("rotate", &learn::dataset_view::rotate) + .def("total_features", &learn::dataset_view::total_features) + .def("__getitem__", + [](const learn::dataset_view& dv, int64_t offset) { + std::size_t idx = offset >= 0 + ? static_cast(offset) + : dv.size() + offset; + if (idx >= dv.size()) + throw py::index_error(); + return *(dv.begin() + idx); + }) + .def("__getitem__", + [](const learn::dataset_view& dv, py::slice slice) { + return make_sliced_dataset_view(dv, slice); + }, + py::keep_alive<0, 1>()) + .def("__len__", &learn::dataset_view::size) + .def("__iter__", + [](const learn::dataset_view& dv) { + return py::make_iterator(dv.begin(), dv.end()); + }, + py::keep_alive<0, 1>()); + + py::implicitly_convertible(); + + m_learn.def("tfidf_transform", &learn::tfidf_transform); + m_learn.def("l2norm_transform", &learn::l2norm_transform); + + auto m_loss = m_learn.def_submodule("loss"); + + py::class_ pyloss{ + m_loss, "LossFunction"}; + pyloss.def("loss", &learn::loss::loss_function::loss) + .def("derivative", &learn::loss::loss_function::derivative); + + bind_loss_function(m_loss, "Hinge", pyloss); + bind_loss_function(m_loss, "Huber", pyloss); + bind_loss_function(m_loss, "LeastSquares", + pyloss); + bind_loss_function(m_loss, "Logistic", pyloss); + bind_loss_function(m_loss, "ModifiedHuber", + pyloss); + bind_loss_function(m_loss, "Perceptron", pyloss); + bind_loss_function(m_loss, "SmoothHinge", + pyloss); + bind_loss_function(m_loss, "SquaredHinge", + pyloss); + + py::class_ py_sgdmodel{m_learn, "SGDModel"}; + py::class_{py_sgdmodel, "Options"} + .def(py::init<>()) + .def_readwrite("learning_rate", + &learn::sgd_model::options_type::learning_rate) + .def_readwrite("l2_regularizer", + &learn::sgd_model::options_type::l2_regularizer) + .def_readwrite("l1_regularizer", + &learn::sgd_model::options_type::l1_regularizer); + py_sgdmodel + .def_readonly_static("default_learning_rate", + &learn::sgd_model::default_learning_rate) + .def_readonly_static("default_l2_regularizer", + &learn::sgd_model::default_l2_regularizer) + .def_readonly_static("default_l1_regularizer", + &learn::sgd_model::default_l1_regularizer) + .def(py::init()) + .def("predict", &learn::sgd_model::predict) + .def("train_one", &learn::sgd_model::train_one); +} diff --git a/metapy/src/metapy_parser.cpp b/metapy/src/metapy_parser.cpp new file mode 100644 index 0000000000..3dbdcea02c --- /dev/null +++ b/metapy/src/metapy_parser.cpp @@ -0,0 +1,330 @@ +/** + * @file metapy_parser.cpp + * @author Chase Geigle + * + * This file defines the metapy.parser submodule and creates bindings for + * that part of the MeTA API. + */ + +#include + +#include +#include +#include + +#include + +#include "meta/parser/trees/evalb.h" +#include "meta/parser/trees/internal_node.h" +#include "meta/parser/trees/leaf_node.h" +#include "meta/parser/trees/visitors/annotation_remover.h" +#include "meta/parser/trees/visitors/binarizer.h" +#include "meta/parser/trees/visitors/debinarizer.h" +#include "meta/parser/trees/visitors/empty_remover.h" +#include "meta/parser/trees/visitors/head_finder.h" +#include "meta/parser/trees/visitors/leaf_node_finder.h" +#include "meta/parser/trees/visitors/unary_chain_remover.h" + +#include "meta/parser/sequence_extractor.h" +#include "meta/parser/sr_parser.h" + +#include "meta/parser/io/ptb_reader.h" + +#include "metapy_identifiers.h" +#include "metapy_parser.h" + +namespace py = pybind11; +using namespace meta; + +template +class visitor_wrapper : public parser::visitor +{ + public: + virtual py::object operator()(parser::leaf_node& ln) override + { + return py::cast(vtor_(ln)); + } + + virtual py::object operator()(parser::internal_node& n) override + { + return py::cast(vtor_(n)); + } + + Visitor& visitor() + { + return vtor_; + } + + private: + Visitor vtor_; +}; + +template +class visitor_wrapper> + : public parser::visitor +{ + public: + virtual py::object operator()(parser::leaf_node& ln) override + { + return py::cast(vtor_(ln).release()); + } + + virtual py::object operator()(parser::internal_node& n) override + { + return py::cast(vtor_(n).release()); + } + + Visitor& visitor() + { + return vtor_; + } + + private: + Visitor vtor_; +}; + +template +class visitor_wrapper : public parser::visitor +{ + public: + virtual py::object operator()(parser::leaf_node& ln) override + { + vtor_(ln); + return py::cast(nullptr); + } + + virtual py::object operator()(parser::internal_node& n) override + { + vtor_(n); + return py::cast(nullptr); + } + + Visitor& visitor() + { + return vtor_; + } + + private: + Visitor vtor_; +}; + +class py_visitor : public parser::visitor +{ + public: + virtual py::object operator()(parser::leaf_node& ln) override + { + PYBIND11_OVERLOAD_PURE(py::object, parser::visitor, + visit_leaf, ln); + return py::cast(nullptr); + } + + virtual py::object operator()(parser::internal_node& n) override + { + + PYBIND11_OVERLOAD_PURE(py::object, parser::visitor, + visit_internal, n); + return py::cast(nullptr); + } +}; + +void metapy_bind_parser(py::module& m) +{ + using namespace parser; + + auto m_parse = m.def_submodule("parser"); + + py::class_{m_parse, "Node"} + .def("category", &node::category) + .def("is_leaf", &node::is_leaf) + .def("is_temporary", &node::is_temporary) + .def("equal", &node::equal) + .def("accept", [](node& n, parser::visitor& vtor) { + return n.accept(vtor); + }); + + py::class_{m_parse, "LeafNode"} + .def(py::init()) + .def(py::init()) + .def("word", [](const leaf_node& ln) { return *ln.word(); }); + + py::class_{m_parse, "InternalNode"} + .def("__init__", + [](internal_node& n, class_label cat, py::list pylist) { + std::vector> children(pylist.size()); + for (std::size_t i = 0; i < pylist.size(); ++i) + children[i] = pylist[i].cast().clone(); + + new (&n) internal_node(std::move(cat), std::move(children)); + }) + .def(py::init()) + .def("add_child", [](internal_node& n, + const node& child) { n.add_child(child.clone()); }) + .def("num_children", &internal_node::num_children) + .def("child", &internal_node::child, py::keep_alive<0, 1>()) + .def("head_lexicon", [](internal_node& n) { return n.head_lexicon(); }, + py::keep_alive<0, 1>()) + .def("head_lexicon", + [](internal_node& n, const leaf_node* descendent) { + n.head_lexicon(descendent); + }) + .def("head_constituent", + [](internal_node& n) { return n.head_constituent(); }, + py::keep_alive<0, 1>()) + .def("head_constituent", + [](internal_node& n, const node* descendent) { + n.head_constituent(descendent); + }) + // weirdness: need to ensure that the child nodes passed down to + // the python lambda preserve the lifetime of the current internal + // node in case they are stored internally + .def("each_child", + [](internal_node& n, py::function fn) { + n.each_child([&](node* child) { + auto handle = py::cast( + *child, py::return_value_policy::reference_internal, + py::cast(n)); + fn(handle); + }); + }) + .def("__getitem__", + [](internal_node& n, int64_t offset) { + uint64_t idx = offset >= 0 ? static_cast(offset) + : n.num_children() + offset; + if (idx >= n.num_children()) + throw py::index_error(); + return n.child(idx); + }, + py::keep_alive<0, 1>()) + .def("__len__", &internal_node::num_children); + + py::class_{m_parse, "ParseTree"} + .def("__init__", + [](parse_tree& tree, const node& n) { + new (&tree) parse_tree(n.clone()); + }) + .def(py::init()) + .def("__str__", + [](const parse_tree& tree) { + std::stringstream ss; + ss << tree; + return ss.str(); + }) + .def("pretty_str", + [](const parse_tree& tree) { + std::stringstream ss; + tree.pretty_print(ss); + return ss.str(); + }) + // keep_alive here is to ensure that the visitor keeps the tree + // alive as long as it is still referenced, since it might hold an + // internal pointer into the tree + .def("visit", + [](parse_tree& tree, parser::visitor& vtor) { + return tree.visit(vtor); + }, + py::keep_alive<2, 1>()); + + py::implicitly_convertible(); + + py::class_, py_visitor> vtorbase{m_parse, "Visitor"}; + vtorbase.def(py::init<>()) + .def("visit_leaf", + [](visitor& vtor, leaf_node& ln) { return vtor(ln); }) + .def("visit_internal", [](visitor& vtor, + internal_node& in) { return vtor(in); }); + + py::class_>{ + m_parse, "AnnotationRemover", vtorbase} + .def(py::init<>()); + py::class_>{m_parse, "Binarizer", vtorbase}.def( + py::init<>()); + py::class_>{m_parse, "Debinarizer", vtorbase} + .def(py::init<>()); + py::class_>{m_parse, "EmptyRemover", + vtorbase} + .def(py::init<>()); + py::class_>{ + m_parse, "UnaryChainRemover", vtorbase} + .def(py::init<>()); + + py::class_>{m_parse, "HeadFinder", vtorbase} + .def(py::init<>()); + py::class_>{m_parse, "LeafNodeFinder", + vtorbase} + .def(py::init<>()) + .def("leaves", [](visitor_wrapper& lnf) { + // need to manually create the py::list here since the + // pybind11 caster for vector operates on a const vector, + // not a mutable one + auto leaves = lnf.visitor().leaves(); + + py::list ret(leaves.size()); + for (std::size_t i = 0; i < leaves.size(); ++i) + { + ret[i] = py::reinterpret_steal( + py::detail::type_caster>::cast( + std::move(leaves[i]), + py::return_value_policy::automatic_reference, + py::handle())); + } + return ret; + }); + + py::class_>{ + m_parse, "SequenceExtractor", vtorbase} + .def(py::init<>()) + .def("sequence", [](visitor_wrapper& vtor) { + return vtor.visitor().sequence(); + }); + + py::class_{m_parse, "EvalB"} + .def(py::init<>()) + .def("matched", &evalb::matched) + .def("proposed_total", &evalb::proposed_total) + .def("gold_total", &evalb::gold_total) + .def("labeled_precision", &evalb::labeled_precision) + .def("labeled_recall", &evalb::labeled_recall) + .def("labeled_f1", &evalb::labeled_f1) + .def("perfect", &evalb::perfect) + .def("average_crossing", &evalb::average_crossing) + .def("zero_crossing", &evalb::zero_crossing) + .def("add_tree", &evalb::add_tree); + + m_parse.def("extract_trees_from_file", [](const std::string& filename) { + return parser::io::extract_trees(filename); + }); + + m_parse.def("extract_trees", [](const std::string& input) { + std::stringstream ss{input}; + return parser::io::extract_trees(ss); + }); + + m_parse.def("read_tree", [](const std::string& input) { + std::stringstream ss{input}; + return parser::io::extract_trees(ss).at(0); + }); + + py::class_ parser{m_parse, "Parser"}; + + py::enum_{parser, "TrainingAlgorithm"} + .value("EarlyTermination", + sr_parser::training_algorithm::EARLY_TERMINATION) + .value("BeamSearch", sr_parser::training_algorithm::BEAM_SEARCH); + + py::class_{parser, "TrainingOptions"} + .def(py::init<>()) + .def(py::init()) + .def_readwrite("batch_size", &sr_parser::training_options::batch_size) + .def_readwrite("beam_size", &sr_parser::training_options::beam_size) + .def_readwrite("max_iterations", + &sr_parser::training_options::max_iterations) + .def_readwrite("seed", &sr_parser::training_options::seed) + .def_readwrite("num_threads", &sr_parser::training_options::num_threads) + .def_readwrite("algorithm", &sr_parser::training_options::algorithm); + + parser.def(py::init<>()) + .def(py::init()) + .def("parse", &sr_parser::parse) + .def("train", &sr_parser::train) + .def("save", &sr_parser::save); +} diff --git a/metapy/src/metapy_sequence.cpp b/metapy/src/metapy_sequence.cpp new file mode 100644 index 0000000000..467c438ec7 --- /dev/null +++ b/metapy/src/metapy_sequence.cpp @@ -0,0 +1,134 @@ +/** + * @file metapy_sequence.cpp + * @author Chase Geigle + * + * This file defines the metapy.sequence submodule and creates bindings + * for that part of the MeTA API. + */ + +#include + +#include +#include + +#include "cpptoml.h" + +#include "meta/sequence/io/ptb_parser.h" +#include "meta/sequence/perceptron.h" +#include "meta/sequence/sequence.h" + +#include "metapy_identifiers.h" +#include "metapy_sequence.h" + +namespace py = pybind11; +using namespace meta; + +void metapy_bind_sequence(py::module& m) +{ + auto m_seq = m.def_submodule("sequence"); + + py::class_{m_seq, "Observation"} + .def(py::init()) + .def(py::init()) + .def_property( + "symbol", + [](const sequence::observation& obs) { return obs.symbol(); }, + [](sequence::observation& obs, sequence::symbol_t sym) { + obs.symbol(std::move(sym)); + }) + .def_property( + "tag", [](const sequence::observation& obs) { return obs.tag(); }, + [](sequence::observation& obs, sequence::tag_t tag) { + obs.tag(std::move(tag)); + }) + .def_property( + "label", + [](const sequence::observation& obs) { return obs.label(); }, + [](sequence::observation& obs, label_id lbl) { obs.label(lbl); }) + .def_property( + "features", + [](const sequence::observation& obs) { return obs.features(); }, + [](sequence::observation& obs, + sequence::observation::feature_vector feats) { + obs.features(std::move(feats)); + }) + .def("tagged", &sequence::observation::tagged); + + py::class_{m_seq, "Sequence"} + .def(py::init<>()) + .def("add_observation", &sequence::sequence::add_observation) + .def("add_symbol", &sequence::sequence::add_symbol) + .def("__getitem__", + [](sequence::sequence& seq, int64_t offset) { + std::size_t idx = offset >= 0 + ? static_cast(offset) + : seq.size() + offset; + if (idx >= seq.size()) + throw py::index_error(); + return seq[idx]; + }) + .def("__setitem__", + [](sequence::sequence& seq, int64_t offset, + sequence::observation obs) { + std::size_t idx = offset >= 0 + ? static_cast(offset) + : seq.size() + offset; + if (idx >= seq.size()) + throw py::index_error(); + seq[idx] = std::move(obs); + }) + .def("__len__", &sequence::sequence::size) + .def("__iter__", + [](const sequence::sequence& seq) { + return py::make_iterator(seq.begin(), seq.end()); + }, + py::keep_alive<0, 1>()) + .def("__str__", + [](const sequence::sequence& seq) { + std::string res; + for (auto it = seq.begin(); it != seq.end();) + { + res += "(" + static_cast(it->symbol()) + ", " + + (it->tagged() + ? static_cast(it->tag()) + : "???") + + ")"; + if (++it != seq.end()) + res += ", "; + } + return res; + }) + .def("tagged", [](const sequence::sequence& seq) { + std::vector> res(seq.size()); + std::transform(seq.begin(), seq.end(), res.begin(), + [](const sequence::observation& obs) { + return std::make_pair( + obs.symbol(), + obs.tagged() + ? static_cast(obs.tag()) + : "???"); + }); + return res; + }); + + m_seq.def("extract_sequences", &sequence::extract_sequences); + + using sequence::perceptron; + py::class_ perc_tagger{m_seq, "PerceptronTagger"}; + + py::class_{perc_tagger, "TrainingOptions"} + .def(py::init<>()) + .def_readwrite("max_iterations", + &perceptron::training_options::max_iterations) + .def_readwrite("seed", &perceptron::training_options::seed); + + perc_tagger.def(py::init<>()) + .def("__init__", + [](perceptron& model, const std::string& path) { + py::gil_scoped_release rel; + new (&model) perceptron(path); + }) + .def("tag", &perceptron::tag) + .def("train", &perceptron::train) + .def("save", &perceptron::save); +} diff --git a/metapy/src/metapy_stats.cpp b/metapy/src/metapy_stats.cpp new file mode 100644 index 0000000000..8a3cdea6ef --- /dev/null +++ b/metapy/src/metapy_stats.cpp @@ -0,0 +1,50 @@ +/** + * @file metapy_stats.cpp + * @author Chase Geigle + * + * This file defines the metapy.stats submodule and creates bindings + * for that part of the MeTA API. + */ + +#include + +#include +#include + +#include "meta/stats/multinomial.h" + +#include "metapy_identifiers.h" +#include "metapy_stats.h" + +namespace py = pybind11; +using namespace meta; + +void metapy_bind_stats(py::module& m) +{ + auto m_stats = m.def_submodule("stats"); + + py::class_{m_stats, "Multinomial"} + .def("increment", &py_multinomial::increment) + .def("decrement", &py_multinomial::decrement) + .def("counts", [](const py_multinomial& dist, + py::object obj) { return dist.counts(obj); }) + .def("counts", [](const py_multinomial& dist) { return dist.counts(); }) + .def("unique_events", &py_multinomial::unique_events) + .def("each_seen_event", &py_multinomial::each_seen_event) + .def("clear", &py_multinomial::clear) + .def("probability", &py_multinomial::probability) + .def("__repr__", [](const py_multinomial& mult) { + const auto size = mult.unique_events(); + uint64_t i = 0; + std::string result = "(); + result += ": "; + result += std::to_string(mult.probability(obj)); + if (++i != size) + result += ", "; + }); + result += "}>"; + return result; + }); +} diff --git a/metapy/src/metapy_topics.cpp b/metapy/src/metapy_topics.cpp new file mode 100644 index 0000000000..dd8a95ef76 --- /dev/null +++ b/metapy/src/metapy_topics.cpp @@ -0,0 +1,230 @@ +/** + * @file metapy_topics.cpp + * @author Sean Massung + */ + +#include +#include + +#include "cpptoml.h" +#include "meta/learn/dataset.h" +#include "meta/logging/logger.h" +#include "meta/topics/bl_term_scorer.h" +#include "meta/topics/inferencer.h" +#include "meta/topics/lda_cvb.h" +#include "meta/topics/lda_cvb_inferencer.h" +#include "meta/topics/lda_gibbs.h" +#include "meta/topics/lda_gibbs_inferencer.h" +#include "meta/topics/lda_scvb.h" +#include "meta/topics/parallel_lda_gibbs.h" +#include "meta/util/random.h" +#include "metapy_identifiers.h" +#include "metapy_stats.h" +#include "metapy_topics.h" + +namespace py = pybind11; +using namespace meta; + +void metapy_bind_topics(py::module& m) +{ + auto m_topics = m.def_submodule("topics"); + + py::class_{m_topics, "LDAModel"} + .def("run", + [](topics::lda_model& model, uint64_t num_iters, + double convergence) { + py::gil_scoped_release release; + model.run(num_iters, convergence); + }) + .def("save_doc_topic_distributions", + [](const topics::lda_model& model, const std::string& filename) { + std::ofstream output{filename, std::ios::binary}; + model.save_doc_topic_distributions(output); + }) + .def("save_topic_term_distributions", + [](const topics::lda_model& model, const std::string& filename) { + std::ofstream output{filename, std::ios::binary}; + model.save_topic_term_distributions(output); + }) + .def("save", &topics::lda_model::save) + .def("compute_term_topic_probability", + &topics::lda_model::compute_term_topic_probability) + .def("compute_doc_topic_probability", + &topics::lda_model::compute_doc_topic_probability) + .def("topic_distribution", + [](const topics::lda_model& model, doc_id doc) { + return py_multinomial{model.topic_distribution(doc)}; + }) + .def("term_distribution", + [](const topics::lda_model& model, topic_id k) { + return py_multinomial{model.term_distribution(k)}; + }) + .def("num_topics", &topics::lda_model::num_topics); + + py::class_{m_topics, "LDAInferencer"} + .def("term_distribution", + [](const topics::inferencer& inf, topic_id k) { + return py_multinomial{inf.term_distribution(k)}; + }, + py::arg("k")) + .def("num_topics", &topics::inferencer::num_topics); + + py::class_{m_topics, "LDACollapsedVB"} + .def(py::init(), + py::keep_alive<0, 1>(), py::arg("docs"), py::arg("num_topics"), + py::arg("alpha"), py::arg("beta")) + .def("run", + [](topics::lda_cvb& lda, uint64_t num_iters, double convergence) { + py::gil_scoped_release release; + lda.run(num_iters, convergence); + }, + py::arg("num_iters"), py::arg("convergence") = 1e-3); + + py::class_{m_topics, + "CVBInferencer"} + .def("__init__", + [](topics::inferencer& inf, const std::string& cfgfile) { + py::gil_scoped_release release; + auto config = cpptoml::parse_file(cfgfile); + new (&inf) topics::inferencer(*config); + }, + py::arg("cfg_file")) + .def("__init__", + [](topics::inferencer& inf, const std::string& topicsfile, + double alpha) { + py::gil_scoped_release release; + std::ifstream topics_stream{topicsfile, std::ios::binary}; + new (&inf) topics::inferencer(topics_stream, alpha); + }, + py::arg("topics_file"), py::arg("alpha")) + .def("infer", + [](const topics::lda_cvb::inferencer& inf, + const learn::feature_vector& doc, std::size_t max_iters, + double convergence) { + return py_multinomial{inf(doc, max_iters, convergence)}; + }, + py::arg("doc"), py::arg("max_iters"), py::arg("convergence")); + + py::class_{m_topics, "LDAGibbs"} + .def(py::init(), + py::keep_alive<0, 1>(), py::arg("docs"), py::arg("num_topics"), + py::arg("alpha"), py::arg("beta")) + .def( + "run", + [](topics::lda_gibbs& lda, uint64_t num_iters, double convergence) { + py::gil_scoped_release release; + lda.run(num_iters, convergence); + }, + py::arg("num_iters"), py::arg("convergence") = 1e-6); + + py::class_{ + m_topics, "GibbsInferencer"} + .def("__init__", + [](topics::inferencer& inf, const std::string& cfgfile) { + py::gil_scoped_release release; + auto config = cpptoml::parse_file(cfgfile); + new (&inf) topics::inferencer(*config); + }, + py::arg("cfg_file")) + .def("__init__", + [](topics::inferencer& inf, const std::string& topicsfile, + double alpha) { + py::gil_scoped_release release; + std::ifstream topics_stream{topicsfile, std::ios::binary}; + new (&inf) topics::inferencer(topics_stream, alpha); + }, + py::arg("topics_file"), py::arg("alpha")) + + .def("infer", + [](const topics::lda_gibbs::inferencer& inf, + const learn::feature_vector& doc, std::size_t num_iters, + std::size_t seed) { + random::xoroshiro128 rng{seed}; + return py_multinomial{inf(doc, num_iters, rng)}; + }, + py::arg("doc"), py::arg("max_iters"), py::arg("rng_seed")); + + py::class_{ + m_topics, "LDAParallelGibbs"} + .def(py::init(), + py::keep_alive<0, 1>(), py::arg("docs"), py::arg("num_topics"), + py::arg("alpha"), py::arg("beta")); + + py::class_{m_topics, + "LDAStochasticCVB"} + .def(py::init(), + py::keep_alive<0, 1>(), py::arg("docs"), py::arg("num_topics"), + py::arg("alpha"), py::arg("beta"), py::arg("minibatch_size") = 100) + .def("run", + [](topics::lda_scvb& lda, uint64_t num_iters, double convergence) { + py::gil_scoped_release release; + lda.run(num_iters, convergence); + }, + py::arg("num_iters"), py::arg("convergence") = 0); + + py::class_{m_topics, "TopicModel"} + .def("__init__", + [](topics::topic_model& model, const std::string& prefix) { + py::gil_scoped_release release; + + std::ifstream theta{prefix + ".theta.bin", std::ios::binary}; + + if (!theta) + { + throw topics::topic_model_exception{ + "missing document topic probabilities file: " + prefix + + ".theta.bin"}; + } + + std::ifstream phi{prefix + ".phi.bin", std::ios::binary}; + if (!phi) + { + throw topics::topic_model_exception{ + "missing topic term probabilities file: " + prefix + + ".phi.bin"}; + } + + new (&model) topics::topic_model(theta, phi); + }) + .def("top_k", + [](const topics::topic_model& model, topic_id tid, std::size_t k) { + return model.top_k(tid, k); + }, + py::arg("tid"), py::arg("k") = 10) + .def("top_k", + [](const topics::topic_model& model, topic_id tid, std::size_t k, + std::function scorer) { + return model.top_k(tid, k, scorer); + }, + py::arg("tid"), py::arg("k") = 10, py::arg("scorer")) + .def("top_k", + [](const topics::topic_model& model, topic_id tid, std::size_t k, + const topics::bl_term_scorer& scorer) { + return model.top_k(tid, k, scorer); + }, + py::arg("tid"), py::arg("k") = 10, py::arg("scorer")) + .def("topic_distribution", + [](const topics::topic_model& self, doc_id did) { + return py_multinomial{self.topic_distribution(did)}; + }) + .def("term_distribution", + [](const topics::topic_model& self, topic_id k) { + return py_multinomial{self.term_distribution(k)}; + }) + .def("term_probability", &topics::topic_model::term_probability) + .def("topic_probability", &topics::topic_model::topic_probability) + .def("num_topics", &topics::topic_model::num_topics) + .def("num_words", &topics::topic_model::num_words) + .def("num_docs", &topics::topic_model::num_docs); + + m_topics.def("load_topic_model", [](const std::string& config_path) { + py::gil_scoped_release release; + auto config = cpptoml::parse_file(config_path); + return topics::load_topic_model(*config); + }); + + py::class_{m_topics, "BLTermScorer"} + .def(py::init(), py::keep_alive<0, 1>()) + .def("__call__", &topics::bl_term_scorer::operator()); +} diff --git a/metapy/src/nltk_additions.py b/metapy/src/nltk_additions.py new file mode 100644 index 0000000000..73a1c8524d --- /dev/null +++ b/metapy/src/nltk_additions.py @@ -0,0 +1,246 @@ +import nltk +import math +import numpy + +nltk.download('punkt') +nltk.download('wordnet') +nltk.download('omw-1.4') +nltk.download('averaged_perceptron_tagger') +nltk.download('vader_lexicon') +nltk.download('stopwords') + + +# NLTK integrated Inl2 retrieval functionality (MP Integration Function #1) +def get_stopwords(lang='english'): + return set(nltk.corpus.stopwords.words(lang)) + + +def inl2_retrieval(documents, query): + # Tokenize documents and query + def tokenize(text): + return nltk.word_tokenize(text.lower()) + + t_doc = [tokenize(doc) for doc in documents] + t_query = tokenize(query) + + # Compute TF-IDF scores for each document + def score(query_terms, document_terms, corpus): + tf_scores = [document_terms.count(term) for term in query_terms] + idf_scores = [math.log(len(corpus) / (1 + corpus.count(term))) for term in query_terms] + tfidf_scores = [tf * idf for tf, idf in zip(tf_scores, idf_scores)] + return sum(tfidf_scores) + + corpus = [token for doc in t_doc for token in doc] + scores = [(doc, score(t_query, doc, corpus)) for doc in t_doc] + + # Sort documents by score (highest score first) + scores.sort(key=lambda x: x[1], reverse=True) + + return scores + + +# NLTK integrated Part of speech tagging functionality (MP Integration Function #2) +def pos_tagging(text): + # Tokenize the input text into words + words = nltk.word_tokenize(text) + + # Perform POS tagging + pos_tags = nltk.pos_tag(words) + + return pos_tags + + +# NDCG scoring functionality (MP Integration Function #3) +def ndcg(ranker, queries, relevant_docs, k=10): + ndcg_scores = [] + + def dcg(relevance_scores): + # Calculate the Discounted Cumulative Gain (DCG) + dcg_score = 0.0 + for i, rel in enumerate(relevance_scores): + dcg_score += (2**rel - 1) / math.log2(i + 2) + return dcg_score + + for query in queries: + # Use the ranker to rank documents for the current query + ranked_docs = ranker(query)[:k] # Consider only the top k documents + + # Calculate the relevance scores for the ranked documents + relevance_scores = [1 if doc in relevant_docs.get(query, []) else 0 for doc in ranked_docs] + + # Calculate DCG at k + dcg_at_k = dcg(relevance_scores) + + # Sort the relevance scores in descending order for ideal DCG calculation + ideal_relevance_scores = sorted(relevance_scores, reverse=True) + + # Calculate ideal DCG at k + ideal_dcg_at_k = dcg(ideal_relevance_scores) + + # Calculate NDCG at k + if ideal_dcg_at_k == 0: + ndcg_score = 0.0 + else: + ndcg_score = dcg_at_k / ideal_dcg_at_k + + ndcg_scores.append(ndcg_score) + + # Calculate the average NDCG over all queries + avg_ndcg = numpy.mean(ndcg_scores) + + return avg_ndcg + +# NLTK integrated Naive Bayes Classifier (MP Integration Function #4) +def naive_bayes_classifier(training_data, new_text): + # Define a feature extractor function (simple bag-of-words) + def extract_features(text): + words = set(text) + features = {} + for word in word_features: + features['contains({})'.format(word)] = (word in words) + return features + + # Get the most frequent words as features + all_words = nltk.FreqDist(w.lower() for w in nltk.word_tokenize(' '.join([review for review, _ in training_data]))) + word_features = list(all_words.keys())[:2000] # Use the top 2000 words as features + + # Extract features for each review + feature_sets = [(extract_features(review.split()), label) for (review, label) in training_data] + + # Train a Naive Bayes classifier + classifier = nltk.classify.NaiveBayesClassifier.train(feature_sets) + + # Classify the new text + new_features = extract_features(new_text.split()) + classification = classifier.classify(new_features) + + return classification + + +# NLTK integrated stemmer and lemmatizer (MP Integration Function #5) +def stem_lemmatize(text): + # Tokenize the text into words + words = nltk.word_tokenize(text) + + # Initialize the stemmer and lemmatizer + stemmer = nltk.stem.PorterStemmer() + lemmatizer = nltk.stem.WordNetLemmatizer() + + # Apply stemming and lemmatization to each word + stemmed_words = [stemmer.stem(word) for word in words] + lemmatized_words = [lemmatizer.lemmatize(word) for word in words] + + return stemmed_words, lemmatized_words + + +def get_text_sentiment(text, negative_thres=-0.05, positive_thres=0.05): + # Create an instance of SentimentIntensityAnalyzer + from nltk.sentiment import SentimentIntensityAnalyzer + sid = SentimentIntensityAnalyzer() + + # Get the sentiment scores + sentiment_score = sid.polarity_scores(text) + + # Determine sentiment based on the compound score + if sentiment_score['compound'] >= positive_thres: + sentiment = 'Positive' + elif sentiment_score['compound'] <= negative_thres: + sentiment = 'Negative' + else: + sentiment = 'Neutral' + + return sentiment, sentiment_score + + +def max_entropy(train_data, test_data, algorithm='GIS', trace=0, max_iter=1000): + # Feature extraction function + def document_features(document): + return {word: (word in document) for word in document_words} + + # Get all unique words in the dataset + document_words = set(word.lower() for doc, _ in train_data for word in doc) + + # Train the MaxEnt classifier + classifier = nltk.classify.MaxentClassifier.train(train_data, algorithm=algorithm, trace=trace, max_iter=max_iter) + + # Evaluate the classifier + probs = [] + for featureset in test_data: + pdist = classifier.prob_classify(featureset) + prob = {} + for word in ['x', 'y']: + prob[word] = round(pdist.prob(word), 2) + probs.append(prob) + + # Get prediction for test data + many = classifier.classify_many(test_data) + + return classifier, probs, many + + +def analyze_collocation(text, gram): + # Tools to utilize depending on the gram number + finders = { + 2: nltk.collocations.BigramCollocationFinder, + 3: nltk.collocations.TrigramCollocationFinder, + 4: nltk.collocations.QuadgramCollocationFinder + } + measures = { + 2: nltk.collocations.BigramAssocMeasures, + 3: nltk.collocations.TrigramAssocMeasures, + 4: nltk.collocations.QuadgramAssocMeasures + } + + # Tokenize the text + words = nltk.wordpunct_tokenize(text) + + # Create a gramCollocationFinder + gram_finder = finders[gram].from_words(words) + + # Filter out collocations based on frequency and other measures + gram_measures = measures[gram]() + + return {'gram_finder': gram_finder, 'gram_measures': gram_measures} + + +def get_collocation_ngram_score(text, gram=2, n=2, method='raw_freq'): + analysis = analyze_collocation(text, gram) + return analysis['gram_finder'].score_ngrams(getattr(analysis['gram_measures'], method)) + + +def get_collocation_n_best(text, gram=2, n=2, method='raw_freq'): + analysis = analyze_collocation(text, gram) + return analysis['gram_finder'].nbest(getattr(analysis['gram_measures'], method), n) + + +def analyze_corpus(corpus): + # Tokenize and remove stopwords + tokenized_corpus = [nltk.word_tokenize(doc.lower()) for doc in corpus] + stop_words = get_stopwords() + filtered_corpus = [[word.lower() for word in doc if word.isalnum() and word not in stop_words] for doc in tokenized_corpus] + + # Perform part-of-speech tagging + pos_tagged_corpus = [nltk.pos_tag(doc) for doc in filtered_corpus] + + return pos_tagged_corpus + + +def generate_tree(text, grammar, text_is_formatted=False): + def build_trees_from_text(): + # Tokenize the input string + words = nltk.word_tokenize(text) + + # Perform syntactic parsing + parser = nltk.ChartParser(grammar) + return list(parser.parse(words)) + + if text_is_formatted: + trees = list(nltk.tree.Tree.fromstring(text)) + else: + trees = build_trees_from_text() + + for tree in trees: + # Visualize the tree + tree.pretty_print() + + return trees diff --git a/metapy/src/nltk_test.py b/metapy/src/nltk_test.py new file mode 100644 index 0000000000..9fbfdb7e6b --- /dev/null +++ b/metapy/src/nltk_test.py @@ -0,0 +1,301 @@ +import unittest +import nltk +import math +import numpy + +nltk.download('punkt') +nltk.download('wordnet') +nltk.download('omw-1.4') +nltk.download('averaged_perceptron_tagger') + +# Import the functions to be tested +from nltk_additions import * + + +class TestYourFunctions(unittest.TestCase): + + # Test NLTK integrated inl2 retrieval function + def test_inl2_retrieval(self): + documents = [ + "This is the first document.", + "This document is the second document.", + "And this is the third one." + ] + query = "first document" + result = inl2_retrieval(documents, query) + + eq = [(['this', 'is', 'the', 'first', 'document', '.'], 3.9120230054281464), + (['this', 'document', 'is', 'the', 'second', 'document', '.'], 3.2188758248682006), + (['and', 'this', 'is', 'the', 'third', 'one', '.'], 0.0)] + self.assertEqual(result, eq) + + documents = [ + "This is the second test document.", + "Could this be another sample document?", + "Let's run some more tests on this document?" + ] + query = "a second document that will be sampled for tests" + result = inl2_retrieval(documents, query) + + eq = [(['this', 'is', 'the', 'second', 'test', 'document', '.'], 4.276666119016055), + (['could', 'this', 'be', 'another', 'sample', 'document', '?'], 4.276666119016055), + (['let', "'s", 'run', 'some', 'more', 'tests', 'on', 'this', 'document', '?'], 4.276666119016055)] + self.assertEqual(result, eq) + + documents = [ + "This is the third test we will perform.", + "I wonder what range of values we will get.", + "Let's throw in our names: [Nikil, David]." + ] + query = "a third document that Nikil uses as a range of values" + result = inl2_retrieval(documents, query) + + eq = [(['i', 'wonder', 'what', 'range', 'of', 'values', 'we', 'will', 'get', '.'], 8.317766166719343), + (['this', 'is', 'the', 'third', 'test', 'we', 'will', 'perform', '.'], 2.772588722239781), ( + ['let', "'s", 'throw', 'in', 'our', 'names', ':', '[', 'nikil', ',', 'david', ']', '.'], + 2.772588722239781)] + self.assertEqual(result, eq) + + # Test NLTK integrated part of speech tagging function + def test_pos_tagging(self): + text = "NLTK is a powerful library for natural language processing." + tags = pos_tagging(text) + + eq = [('NLTK', 'NNP'), ('is', 'VBZ'), ('a', 'DT'), ('powerful', 'JJ'), ('library', 'NN'), ('for', 'IN'), + ('natural', 'JJ'), ('language', 'NN'), ('processing', 'NN'), ('.', '.')] + self.assertEqual(tags, eq) + + text = "Another test to ensure this function works." + tags = pos_tagging(text) + + eq = [('Another', 'DT'), ('test', 'NN'), ('to', 'TO'), ('ensure', 'VB'), ('this', 'DT'), ('function', 'NN'), + ('works', 'VBZ'), ('.', '.')] + self.assertEqual(tags, eq) + + text = "A final test to verify correctness." + tags = pos_tagging(text) + + eq = [('A', 'DT'), ('final', 'JJ'), ('test', 'NN'), ('to', 'TO'), ('verify', 'VB'), ('correctness', 'NN'), + ('.', '.')] + self.assertEqual(tags, eq) + + # Test with a perfect ranking where all relevant documents are at the top + def test_ndcg_perfect_ranking(self): + ranker = lambda query: ["doc1", "doc2", "doc3", "doc4"] + queries = ["query1"] + relevant_docs = { + "query1": ["doc1", "doc2", "doc3"] + } + k = 3 + result = ndcg(ranker, queries, relevant_docs, k) + self.assertAlmostEqual(result, 1.0, places=2, msg="Perfect ranking should result in NDCG=1.0") + + # Test with a partial ranking where only some relevant documents are at the top + def test_ndcg_partial_ranking(self): + ranker = lambda query: ["doc1", "doc4", "doc2", "doc3"] + queries = ["query1"] + relevant_docs = { + "query1": ["doc1", "doc2", "doc3"] + } + k = 3 + result = ndcg(ranker, queries, relevant_docs, k) + self.assertAlmostEqual(result, 0.919, places=2, msg="Partial ranking should result in NDCG ~0.794") + + # Test with no relevant documents in the ranking + def test_ndcg_no_relevant_docs(self): + ranker = lambda query: ["doc4", "doc5", "doc6"] + queries = ["query1"] + relevant_docs = { + "query1": ["doc1", "doc2", "doc3"] + } + k = 3 + result = ndcg(ranker, queries, relevant_docs, k) + self.assertAlmostEqual(result, 0.0, places=2, msg="No relevant docs in ranking should result in NDCG=0.0") + + # Test the classifier with positive training data + def test_nbc_positive(self): + training_data = [ + ("This is a positive review", "positive"), + ("Great product, highly recommended", "positive"), + ("I love this!", "positive") + ] + new_text = "This product is amazing" + result = naive_bayes_classifier(training_data, new_text) + self.assertEqual(result, "positive", "Classification should be positive") + + # Test the classifier with negative training data + def test_nbc_negative(self): + training_data = [ + ("Terrible experience, do not buy", "negative"), + ("Waste of money", "negative"), + ("I regret buying this", "negative") + ] + new_text = "I'm so disappointed with this product" + result = naive_bayes_classifier(training_data, new_text) + self.assertEqual(result, "negative", "Classification should be negative") + + # Test the classifier with neutral training data + def test_nbc_neutral(self): + training_data = [ + ("It's okay, not great but not terrible", "neutral"), + ("Average product, nothing special", "neutral"), + ("I have mixed feelings about this", "neutral") + ] + new_text = "It's neither good nor bad" + result = naive_bayes_classifier(training_data, new_text) + self.assertEqual(result, "neutral", "Classification should be neutral") + + # Test the function's stemming capability + def test_stemming(self): + text = "running jumps" + stemmed_words, _ = stem_lemmatize(text) + self.assertEqual(stemmed_words, ["run", "jump"], "Stemming should produce ['run', 'jump']") + + # Test the function's lemmatization capability + def test_lemmatization(self): + text = "better best" + _, lemmatized_words = stem_lemmatize(text) + self.assertEqual(lemmatized_words, ["better", "best"], "Lemmatization should produce ['better', 'best']") + + # Test both stemming and lemmatization together + def test_stem_lemmatize_combined(self): + text = "running better" + stemmed_words, lemmatized_words = stem_lemmatize(text) + self.assertEqual(stemmed_words, ["run", "better"], "Stemming should produce ['run', 'better']") + self.assertEqual(lemmatized_words, ["running", "better"], "Lemmatization should produce ['running', 'better']") + + # Test a declarative statement for neutral sentimentality + def test_neutral_sentiment(self, negative_thres=-0.05, positive_thres=0.05): + text = 'This is a test.' + sentiment, score = get_text_sentiment(text, negative_thres, positive_thres) + self.assertGreaterEqual(score['compound'], negative_thres) + self.assertLessEqual(score['compound'], positive_thres) + + # Test a negative statement for negative sentimentality + def test_negative_sentiment(self, negative_thres=-0.05, positive_thres=0.05): + text = 'This failing test will fail.' + sentiment, score = get_text_sentiment(text, negative_thres, positive_thres) + self.assertLessEqual(score['compound'], negative_thres) + + # Test a positive statement for positive sentimentality + def test_positive_sentiment(self, negative_thres=-0.05, positive_thres=0.05): + text = 'This successful test will pass.' + sentiment, score = get_text_sentiment(text, negative_thres, positive_thres) + self.assertGreaterEqual(score['compound'], positive_thres) + + def test_max_entropy(self): + train = [ + (dict(a=1, b=1, c=1), 'y'), + (dict(a=1, b=1, c=1), 'x'), + (dict(a=1, b=1, c=0), 'y'), + (dict(a=0, b=1, c=1), 'x'), + (dict(a=0, b=1, c=1), 'y'), + (dict(a=0, b=0, c=1), 'y'), + (dict(a=0, b=1, c=0), 'x'), + (dict(a=0, b=0, c=0), 'x'), + (dict(a=0, b=1, c=1), 'y'), + (dict(a=None, b=1, c=0), 'x'), + ] + test = [ + (dict(a=1, b=0, c=1)), # unseen + (dict(a=1, b=0, c=0)), # unseen + (dict(a=0, b=1, c=1)), # seen 3 times, labels=y,y,x + (dict(a=0, b=1, c=0)), # seen 1 time, label=x + ] + + gis = max_entropy(train_data=train, test_data=test, algorithm='GIS') + self.assertEqual([ + {'x': 0.16, "y": 0.84}, + {'x': 0.46, "y": 0.54}, + {'x': 0.41, "y": 0.59}, + {'x': 0.76, "y": 0.24} + ], gis[1]) + self.assertEqual(['y', 'y', 'y', 'x'], gis[2]) + + iis = max_entropy(train_data=train, test_data=test, algorithm='IIS') + self.assertEqual([ + {'x': 0.16, "y": 0.84}, + {'x': 0.46, "y": 0.54}, + {'x': 0.41, "y": 0.59}, + {'x': 0.76, "y": 0.24} + ], iis[1]) + self.assertEqual(['y', 'y', 'y', 'x'], gis[2]) + + def test_analyze_collocation_bigram(self): + # Input text for testing + input_text = "I do not like green eggs and ham, I do not like them Sam I am!" + + # Expected collocations based on the input text + expected_collocations = [(',', 'I'), ('I', 'am'), ('I', 'do'), ('Sam', 'I'), ('am', '!'), + ('and', 'ham'), ('do', 'not'), ('eggs', 'and'), ('green', 'eggs'), + ('ham', ','), ('like', 'green'), ('like', 'them'), ('not', 'like'), + ('them', 'Sam')] + + # Perform collocation analysis + result_collocations = get_collocation_ngram_score(input_text, gram=2) + + # Assert that the result matches the expected collocations + score_ngrams = sorted(gram for gram, score in result_collocations) + self.assertEqual(score_ngrams, expected_collocations) + + def test_analyze_collocation_trigram(self): + # Input text for testing + input_text = "I do not like green eggs and ham, I do not like them Sam I am!" + + # Expected collocations based on the input text + expected_collocations = [('I', 'do', 'not'), ('do', 'not', 'like')] + + # Perform collocation analysis + result_collocations = get_collocation_n_best(input_text, gram=3, n=2) + + # Assert that the result matches the expected collocations + n_best = sorted(result_collocations) + self.assertEqual(n_best, expected_collocations) + + def test_analyze_corpus(self): + # Input corpus for testing + corpus = [ + "This is a sample document. It contains various words.", + "Another document with different words and punctuation!" + ] + + # Expected result (dummy result for demonstration purposes) + expected_result = [ + [('sample', 'JJ'), ('document', 'NN'), ('contains', 'VBZ'), ('various', 'JJ'), + ('words', 'NNS')], + [('another', 'DT'), ('document', 'NN'), ('different', 'JJ'), ('words', 'NNS'), ('punctuation', 'NN')] + ] + + # Perform the analysis + result = analyze_corpus(corpus) + + # Assert that the result matches the expected result + self.assertEqual(result, expected_result) + + def test_generate_tree(self): + # Input and (expected) output + text = 'I rode an elephant in my pajamas' + output = ['''(S (NP I) (VP (VP (V rode) (NP (Det an) (N elephant))) (PP (P in) (NP (Det my) (N pajamas)))))''', + '''(S (NP I) (VP (V rode) (NP (Det an) (N elephant) (PP (P in) (NP (Det my) (N pajamas))))))'''] + + # Perform syntactic parsing + grammar = nltk.CFG.fromstring(""" + S -> NP VP + PP -> P NP + NP -> Det N | Det N PP | 'I' + VP -> V NP | VP PP + Det -> 'an' | 'my' + N -> 'elephant' | 'pajamas' + V -> 'rode' + P -> 'in' + """) + + # For each tree generated due to differentiating sentence structure, confirm it is in the output above + trees = generate_tree(text, grammar) + for tree in trees: + tree = ' '.join(str(tree).split()) + self.assertTrue(tree in output) + + +if __name__ == '__main__': + unittest.main() diff --git a/metapy/travis/build_linux.sh b/metapy/travis/build_linux.sh new file mode 100755 index 0000000000..6bee45165c --- /dev/null +++ b/metapy/travis/build_linux.sh @@ -0,0 +1,6 @@ +#!/bin/bash +sudo docker run --rm \ + -e PYTHON_VERSION=$VERSION \ + -e UNICODE_WIDTH=$UNICODE_WIDTH \ + -v `pwd`:/metapy \ + quay.io/pypa/manylinux1_x86_64 /metapy/travis/build_linux_wheel.sh diff --git a/metapy/travis/build_linux_wheel.sh b/metapy/travis/build_linux_wheel.sh new file mode 100755 index 0000000000..0c87b96a13 --- /dev/null +++ b/metapy/travis/build_linux_wheel.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# based heavily on https://github.com/matthew-brett/manylinux-builds +set -eo pipefail + +# UNICODE_WIDTH selects "32"=wide (UCS4) or "16"=narrow (UTF-16) builds +UNICODE_WIDTH="${UNICODE_WIDTH:-32}" + +# Install cmake +wget --no-check-certificate http://www.cmake.org/files/v3.2/cmake-3.2.0-Linux-x86_64.sh +sh cmake-3.2.0-Linux-x86_64.sh --prefix=/usr/local --exclude-subdir + +# Install zlib +yum install -y zlib-devel + +# taken from https://github.com/matthew-brett/manylinux-builds/blob/master/common_vars.sh +function lex_ver { + # Echoes dot-separated version string padded with zeros + # Thus: + # 3.2.1 -> 003002001 + # 3 -> 003000000 + echo $1 | awk -F "." '{printf "%03d%03d%03d", $1, $2, $3}' +} + +# taken from https://github.com/matthew-brett/manylinux-builds/blob/master/common_vars.sh +function strip_dots { + # Strip "." characters from string + echo $1 | sed "s/\.//g" +} + +# taken from https://github.com/matthew-brett/manylinux-builds/blob/master/common_vars.sh +function cpython_path { + # Return path to cpython given + # * version (of form "2.7") + # * u_width ("16" or "32" default "32") + # + # For back-compatibility "u" as u_width also means "32" + local py_ver="${1:-2.7}" + local u_width="${2:-${UNICODE_WIDTH}}" + local u_suff=u + # Back-compatibility + if [ "$u_width" == "u" ]; then u_width=32; fi + # For Python >= 3.3, "u" suffix not meaningful + if [ $(lex_ver $py_ver) -ge $(lex_ver 3.3) ] || + [ "$u_width" == "16" ]; then + u_suff="" + elif [ "$u_width" != "32" ]; then + echo "Incorrect u_width value $u_width" + # exit 1 + fi + local no_dots=$(strip_dots $py_ver) + echo "/opt/python/cp${no_dots}-cp${no_dots}m${u_suff}" +} + +# taken from https://github.com/matthew-brett/manylinux-builds/blob/master/common_vars.sh +function repair_wheelhouse { + local in_dir=$1 + local out_dir=$2 + for whl in $in_dir/*.whl; do + if [[ $whl == *none-any.whl ]]; then + cp $whl $out_dir + else + auditwheel repair $whl -w $out_dir/ + fi + done + chmod -R a+rwX $out_dir +} + +# adapted from https://github.com/matthew-brett/manylinux-builds/blob/master/build_sklearns.sh +PIP="$(cpython_path $PYTHON_VERSION)/bin/pip" +pushd /metapy +$PIP wheel -w unfixed_wheels --verbose ./ +ls unfixed_wheels/*.whl +repair_wheelhouse unfixed_wheels dist +ls dist/*.whl +$PIP install dist/*.whl +popd diff --git a/metapy/travis/build_osx.sh b/metapy/travis/build_osx.sh new file mode 100755 index 0000000000..407428180f --- /dev/null +++ b/metapy/travis/build_osx.sh @@ -0,0 +1,4 @@ +#!/bin/bash +pip wheel -w dist --verbose ./ +ls dist/*.whl +pip install dist/*.whl diff --git a/metapy/travis/install_linux.sh b/metapy/travis/install_linux.sh new file mode 100755 index 0000000000..03ef4607a3 --- /dev/null +++ b/metapy/travis/install_linux.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sudo docker pull quay.io/pypa/manylinux1_x86_64 diff --git a/metapy/travis/install_osx.sh b/metapy/travis/install_osx.sh new file mode 100755 index 0000000000..c32d55a675 --- /dev/null +++ b/metapy/travis/install_osx.sh @@ -0,0 +1,8 @@ +#!/bin/bash +brew update +brew outdated cmake || brew upgrade cmake +git clone --recursive https://github.com/MacPython/terryfy +git clone https://github.com/matthew-brett/multibuild +source multibuild/osx_utils.sh +get_macpython_environment $VERSION venv +pip install wheel diff --git a/metapy/tutorials/1-analyzers-tokenizers-filters.ipynb b/metapy/tutorials/1-analyzers-tokenizers-filters.ipynb new file mode 100644 index 0000000000..c19d461ec3 --- /dev/null +++ b/metapy/tutorials/1-analyzers-tokenizers-filters.ipynb @@ -0,0 +1,311 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "This is the Analyzers, Tokenizers, and Filters metapy tutorial. First, you should read the following two MeTA tutorials:\n", + "- [MeTA System Overview](https://meta-toolkit.org/overview-tutorial.html). Everything on this page is relevant to metapy except for the *Unit tests* section (you can't run them in Python).\n", + "- [Analyzers, Tokenizers, and Filters](https://meta-toolkit.org/analyzers-filters-tutorial.html). Everything on this page is relevant except for the *Extending MeTA With Your Own Filters* section.\n", + "\n", + "Let's get started!\n", + "\n", + "First, let's create a document to play with." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "import metapy\n", + "doc = metapy.index.Document()\n", + "doc.content(\"I said that I can't believe that it only costs $19.95!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can make our own filter chain and run it on the document's content. Let's start with a simple example of only using `ICUTokenizer`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['',\n", + " 'I',\n", + " 'said',\n", + " 'that',\n", + " 'I',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " '']" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.ICUTokenizer()\n", + "tok.set_content(doc.content())\n", + "[t for t in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "See how the begin and end sentence markers (`` and ``) are inserted at the beginning and end of each sentence. We get an ordered list from using a tokenizer or filter.\n", + "\n", + "Next, use `LowercaseFilter` to convert each token to lowercase. We use the previous `tok` (which is an `ICUTokenizer`) in the constructor to `LowercaseFilter`. This lets us connect an arbitrary amount of filters together with a tokenizer at the start." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['',\n", + " 'i',\n", + " 'said',\n", + " 'that',\n", + " 'i',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " '']" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.ICUTokenizer()\n", + "tok = metapy.analyzers.LowercaseFilter(tok)\n", + "tok.set_content(doc.content())\n", + "[t for t in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Just like in MeTA, metapy's filter chain can be created from a config file. Create the following file called `config.toml`. It will perform the same tokenization and filtering as above (`ICUTokenizer -> LowercaseFilter`). Then, it will aggregate token counts together using an *n*-gram words analyzer.\n", + "\n", + "```toml\n", + "[[analyzers]]\n", + "method = \"ngram-word\"\n", + "ngram = 1\n", + "filter = [{type = \"icu-tokenizer\"}, {type = \"lowercase\"}]\n", + "```\n", + "\n", + "Now, you can load this config file to create a unigram words analyzer. This uses the specified tokenizer/filter chain and analyzer type to convert a document into a dictionary of features and their counts." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'!': 1,\n", + " '$': 1,\n", + " '19.95': 1,\n", + " '': 1,\n", + " '': 1,\n", + " 'believe': 1,\n", + " \"can't\": 1,\n", + " 'costs': 1,\n", + " 'i': 2,\n", + " 'it': 1,\n", + " 'only': 1,\n", + " 'said': 1,\n", + " 'that': 2}" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana = metapy.analyzers.load('config.toml')\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The tokens *i* and *that* are shown with two counts, while all the other tokens have 1 count. These features can then be passed to other parts of metapy, such as ranking functions or indexers.\n", + "\n", + "We can also manually specify the analyzer instead of loading it from the config file:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'!': 1,\n", + " '$': 1,\n", + " '19.95': 1,\n", + " '': 1,\n", + " '': 1,\n", + " 'believe': 1,\n", + " \"can't\": 1,\n", + " 'costs': 1,\n", + " 'i': 2,\n", + " 'it': 1,\n", + " 'only': 1,\n", + " 'said': 1,\n", + " 'that': 2}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana = metapy.analyzers.NGramWordAnalyzer(1, tok)\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{('$', '19.95', '!'): 1,\n", + " ('19.95', '!', ''): 1,\n", + " ('', 'i', 'said'): 1,\n", + " ('believe', 'that', 'it'): 1,\n", + " (\"can't\", 'believe', 'that'): 1,\n", + " ('costs', '$', '19.95'): 1,\n", + " ('i', \"can't\", 'believe'): 1,\n", + " ('i', 'said', 'that'): 1,\n", + " ('it', 'only', 'costs'): 1,\n", + " ('only', 'costs', '$'): 1,\n", + " ('said', 'that', 'i'): 1,\n", + " ('that', 'i', \"can't\"): 1,\n", + " ('that', 'it', 'only'): 1}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana = metapy.analyzers.NGramWordAnalyzer(3, tok)\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Usually, metapy applications will create and call analyzers based on a config file, so you won't have to create your own manually. However, it may still be useful if you are performing your own analysis that is not part of MeTA." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/metapy/tutorials/2-search-and-ir-eval.ipynb b/metapy/tutorials/2-search-and-ir-eval.ipynb new file mode 100644 index 0000000000..bc7f4a57f0 --- /dev/null +++ b/metapy/tutorials/2-search-and-ir-eval.ipynb @@ -0,0 +1,538 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "This is the Indexing and Search metapy tutorial. First, you should read the following tutorial:\n", + "- [Search Tutorial](https://meta-toolkit.org/search-tutorial.html). Read *Initially setting up the config file* and *Relevance judgements*.\n", + "\n", + "First, let's create an index. We will use the AP News dataset. Your current directory should look like this:\n", + "- `apnews`: AP News 88 dataset in MeTA format.\n", + "- `queries.txt`: 100 queries, one per line.\n", + "- `qrels.txt`: Over 10,000 relevance judgements for the queries.\n", + "- `stopwords.txt`: A file containing stopwords that will not be indexed.\n", + "- `apnews-config.toml`: A config file with paths set to all the above files, including index and ranker settings.\n", + "\n", + "Here's how we can use metapy to create the index." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "import metapy\n", + "idx = metapy.index.make_inverted_index('apnews-config.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "This may take a minute at first, since the index needs to be built. Subsequent calls to `make_inverted_index` with this config file will simply load the index, which will not take any time.\n", + "\n", + "Here's how we can interact with the index object:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "164465" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "idx.num_docs()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "299769" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "idx.unique_terms()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "526.3216552734375" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "idx.avg_doc_length()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "86561496" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "idx.total_corpus_terms()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "All the disk index and inverted index functions from MeTA are implemented in metapy.\n", + "\n", + "Let's create a `Ranker` object so we can search the index;" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "ranker = metapy.index.OkapiBM25()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, we need a query. Create a `Document` and set its content to our query:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "query = metapy.index.Document()\n", + "query.content('Airbus Subsidies') # query from AP news" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Search our index using our ranker and query:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(49687, 20.686737060546875),\n", + " (8005, 20.367332458496094),\n", + " (8645, 20.20011329650879),\n", + " (13158, 20.071775436401367),\n", + " (10212, 19.91327667236328)]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "top_docs = ranker.score(idx, query, num_results=5)\n", + "top_docs" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We are returned a ranked list of *(doc_id, score)* pairs. The scores are from the ranker, which in this case was Okapi BM25. Since our `line.toml` file in the AP News dataset has `store-full-text = true`, we can verify the content of our top documents by inspecting the document metadata field \"content\"." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1. A top West German economic official said Sunday that reduction of government subsidies for Airbus Industrie will be a main topic at a planned September meeting ofthe consortium's member nations in Britain . Erich Riedl , parlimentary state secretary ...\n", + "\n", + "2. The United States , angry over European subsidies for the Airbus aircraft - manufacturing consortium , is increasing pressure on Airbus nations to abolish or at least reduce the payments , say diplomatic sources . ` ` The Americans at a minimum want ...\n", + "\n", + "3. U.S . and European trade official sare holding a new round of talks in the lengthy dispute over government subsidies to the Airbus aircraft manufacturing consortium . But both sides remain far apart on the long - simmering issue of subsidies to Airbu...\n", + "\n", + "4. U.S . Trade Representative Clayton Yeutter tol dthe governments of Britain , France , West Germany and Spain onWednesday they are risking a trade war by their ` ` enormous subsidies ' ' to Airbus passenger planes . The major trade bill now before Con...\n", + "\n", + "5. The omnibus trade bill pending in Congres swill include a provision allowing the United States to ` ` get tough ' ' with a European airplane manufacturer which domestic aerospace companies claim receives subsidies and engages in unfair trading practi...\n", + "\n" + ] + } + ], + "source": [ + "for num, (d_id, _) in enumerate(top_docs):\n", + " content = idx.metadata(d_id).get('content')\n", + " print(\"{}. {}...\\n\".format(num + 1, content[0:250]))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Since we have the queries file and relevance judgements, we can do an IR evaluation." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "ev = metapy.index.IREval('apnews-config.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We will loop over the queries file and add each result to the `IREval` object `ev`." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Query 1 average precision: 1.0\n", + "Query 2 average precision: 1.0\n", + "Query 3 average precision: 0.14694444444444443\n", + "Query 4 average precision: 0.5308730158730158\n", + "Query 5 average precision: 0.08833333333333333\n", + "Query 6 average precision: 0.8154365079365078\n", + "Query 7 average precision: 0.4084126984126984\n", + "Query 8 average precision: 1.0\n", + "Query 9 average precision: 0.042222222222222223\n", + "Query 10 average precision: 0.0\n", + "Query 11 average precision: 0.9\n", + "Query 12 average precision: 0.05\n", + "Query 13 average precision: 0.3\n", + "Query 14 average precision: 0.0\n", + "Query 15 average precision: 0.0\n", + "Query 16 average precision: 0.0\n", + "Query 17 average precision: 0.0\n", + "Query 18 average precision: 0.26666666666666666\n", + "Query 19 average precision: 0.016666666666666666\n", + "Query 20 average precision: 0.671111111111111\n", + "Query 21 average precision: 0.5508730158730158\n", + "Query 22 average precision: 0.0\n", + "Query 23 average precision: 0.0\n", + "Query 24 average precision: 0.0\n", + "Query 25 average precision: 0.0325\n", + "Query 26 average precision: 0.2\n", + "Query 27 average precision: 0.4163095238095238\n", + "Query 28 average precision: 1.0\n", + "Query 29 average precision: 0.0\n", + "Query 30 average precision: 0.0\n", + "Query 31 average precision: 0.24166666666666664\n", + "Query 32 average precision: 0.8154365079365078\n", + "Query 33 average precision: 0.12333333333333334\n", + "Query 34 average precision: 0.05\n", + "Query 35 average precision: 0.6708730158730158\n", + "Query 36 average precision: 0.32666666666666666\n", + "Query 37 average precision: 0.0\n", + "Query 38 average precision: 0.0125\n", + "Query 39 average precision: 0.014285714285714285\n", + "Query 40 average precision: 0.3796428571428571\n", + "Query 41 average precision: 0.0\n", + "Query 42 average precision: 0.0\n", + "Query 43 average precision: 0.4747619047619048\n", + "Query 44 average precision: 0.0\n", + "Query 45 average precision: 0.0\n", + "Query 46 average precision: 0.0125\n", + "Query 47 average precision: 0.16333333333333333\n", + "Query 48 average precision: 0.3083333333333333\n", + "Query 49 average precision: 0.03888888888888888\n", + "Query 50 average precision: 0.38936507936507936\n", + "Query 51 average precision: 0.24285714285714288\n", + "Query 52 average precision: 0.20714285714285713\n", + "Query 53 average precision: 0.21341269841269842\n", + "Query 54 average precision: 0.15833333333333333\n", + "Query 55 average precision: 0.0\n", + "Query 56 average precision: 0.2596428571428572\n", + "Query 57 average precision: 0.78\n", + "Query 58 average precision: 0.03666666666666667\n", + "Query 59 average precision: 0.0\n", + "Query 60 average precision: 0.075\n", + "Query 61 average precision: 1.0\n", + "Query 62 average precision: 0.2816666666666666\n", + "Query 63 average precision: 0.0\n", + "Query 64 average precision: 0.0\n", + "Query 65 average precision: 0.05\n", + "Query 66 average precision: 0.0325\n", + "Query 67 average precision: 0.22063492063492066\n", + "Query 68 average precision: 0.43555555555555553\n", + "Query 69 average precision: 0.4397619047619047\n", + "Query 70 average precision: 0.06666666666666667\n", + "Query 71 average precision: 0.0\n", + "Query 72 average precision: 0.09\n", + "Query 73 average precision: 0.36944444444444446\n", + "Query 74 average precision: 0.34444444444444444\n", + "Query 75 average precision: 0.8521031746031745\n", + "Query 76 average precision: 0.4514285714285714\n", + "Query 77 average precision: 0.03333333333333333\n", + "Query 78 average precision: 0.569047619047619\n", + "Query 79 average precision: 0.34444444444444444\n", + "Query 80 average precision: 0.639047619047619\n", + "Query 81 average precision: 0.0\n", + "Query 82 average precision: 0.18051587301587302\n", + "Query 83 average precision: 0.5380952380952382\n", + "Query 84 average precision: 0.6863095238095237\n", + "Query 85 average precision: 0.3155555555555556\n", + "Query 86 average precision: 0.16190476190476188\n", + "Query 87 average precision: 0.7042063492063492\n", + "Query 88 average precision: 0.0\n", + "Query 89 average precision: 0.07222222222222222\n", + "Query 90 average precision: 0.02\n", + "Query 91 average precision: 0.13333333333333333\n", + "Query 92 average precision: 0.25\n", + "Query 93 average precision: 0.03333333333333333\n", + "Query 94 average precision: 0.21000000000000002\n", + "Query 95 average precision: 0.13583333333333333\n", + "Query 96 average precision: 0.44642857142857145\n", + "Query 97 average precision: 0.15\n", + "Query 98 average precision: 0.315\n", + "Query 99 average precision: 0.27166666666666667\n", + "Query 100 average precision: 0.5258333333333334\n" + ] + } + ], + "source": [ + "num_results = 10\n", + "with open('queries.txt') as query_file:\n", + " for query_num, line in enumerate(query_file):\n", + " query.content(line.strip())\n", + " results = ranker.score(idx, query, num_results) \n", + " avg_p = ev.avg_p(results, query_num, num_results)\n", + " print(\"Query {} average precision: {}\".format(query_num + 1, avg_p))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Afterwards, we can get the mean average precision of all the queries." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0.26801309523809536" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ev.map()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Try experimenting with different rankers, ranker parameters, tokenization, and filters. What combination give you the best MAP?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Lastly, it's possible to define your own ranking function in Python." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "class SimpleRanker(metapy.index.RankingFunction): \n", + " \"\"\" \n", + " Create a new ranking function in Python that can be used in MeTA. \n", + " \"\"\" \n", + " def __init__(self, some_param=1.0): \n", + " self.param = some_param\n", + " # You *must* call the base class constructor here!\n", + " super(SimpleRanker, self).__init__() \n", + " \n", + " def score_one(self, sd):\n", + " \"\"\"\n", + " You need to override this function to return a score for a single term.\n", + " For fields available in the score_data sd object,\n", + " @see https://meta-toolkit.org/doxygen/structmeta_1_1index_1_1score__data.html\n", + " \"\"\"\n", + " return (self.param + sd.doc_term_count) / (self.param * sd.doc_unique_terms + sd.doc_size)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/metapy/tutorials/3-deeper-text-analysis.ipynb b/metapy/tutorials/3-deeper-text-analysis.ipynb new file mode 100644 index 0000000000..5244136e66 --- /dev/null +++ b/metapy/tutorials/3-deeper-text-analysis.ipynb @@ -0,0 +1,3571 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "First, we'll import the `metapy` python bindings." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "import metapy" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's create a document with some content." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "doc = metapy.index.Document()\n", + "doc.content(\"I said that I can't believe that it only costs $19.95!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "MeTA provides a stream-based interface for performing document tokenization. Each stream starts off with a Tokenizer object, and in most cases you should use the [Unicode standard aware](http://site.icu-project.org) `ICUTokenizer`." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "tok = metapy.analyzers.ICUTokenizer()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Tokenizers operate on raw text and provide an Iterable that spits out the individual text tokens. Let's try running just the `ICUTokenizer` to see what it does." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['',\n", + " 'I',\n", + " 'said',\n", + " 'that',\n", + " 'I',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " '']" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok.set_content(doc.content()) # this could be any string\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "One thing that you likely immediately notice is the insertion of these pseudo-XML looking `` and `` tags. These are called \"sentence boundary tags\". As a side-effect, a default-construted `ICUTokenizer` discovers the sentences in a document by delimiting them with the sentence boundary tags. Let's try tokenizing a multi-sentence document to see what that looks like." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['',\n", + " 'I',\n", + " 'said',\n", + " 'that',\n", + " 'I',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " '',\n", + " '',\n", + " 'I',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '$',\n", + " '30',\n", + " 'before',\n", + " '.',\n", + " '']" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "doc.content(\"I said that I can't believe that it only costs $19.95! I could only find it for more than $30 before.\")\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Most of the information retrieval techniques you have likely been learning about in this class don't need to concern themselves with finding the boundaries between separate sentences in a document, but later today we'll explore a scenario where this might matter more.\n", + "\n", + "Let's pass a flag to the `ICUTokenizer` constructor to disable sentence boundary tags for now." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['I',\n", + " 'said',\n", + " 'that',\n", + " 'I',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " 'I',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '$',\n", + " '30',\n", + " 'before',\n", + " '.']" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.ICUTokenizer(suppress_tags=True)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "I mentioned earlier that MeTA treats tokenization as a *streaming* process, and that it *starts* with a tokenizer. As you've learned, for optimal search performance it's often beneficial to modify the raw underlying tokens of a document, and thus change its representation, before adding it to an inverted index structure for searching.\n", + "\n", + "The \"intermediate\" steps in the tokenization stream are represented with objects called Filters. Each filter consumes the content of a previous filter (or a tokenizer) and modifies the tokens coming out of the stream in some way.\n", + "\n", + "Let's start by using a simple filter that can help eliminate a lot of noise that we might encounter when tokenizing web documents: a `LengthFilter`." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['said',\n", + " 'that',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '19.95',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '30',\n", + " 'before']" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.LengthFilter(tok, min=2, max=30)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Here, we can see that the `LengthFilter` is consuming our original `ICUTokenizer`. It modifies the token stream by only emitting tokens that are of a minimum length of 2 and a maximum length of 30. This can get rid of a lot of punctuation tokens, but also excessively long tokens such as URLs." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Another common trick is to remove stopwords. (Can anyone tell me what a stopword is?) In MeTA, this is done using a `ListFilter`." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2017-03-28 12:52:33-- https://raw.githubusercontent.com/meta-toolkit/meta/master/data/lemur-stopwords.txt\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving raw.githubusercontent.com... 151.101.44.133\n", + "Connecting to raw.githubusercontent.com|151.101.44.133|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 2747 (2.7K) [text/plain]\n", + "Saving to: ‘lemur-stopwords.txt’\n", + "\n", + "lemur-stopwords.txt 100%[===================>] 2.68K --.-KB/s in 0s \n", + "\n", + "2017-03-28 12:52:33 (22.6 MB/s) - ‘lemur-stopwords.txt’ saved [2747/2747]\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "[\"can't\", 'believe', 'costs', '19.95', 'find', '30']" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "!wget -nc https://raw.githubusercontent.com/meta-toolkit/meta/master/data/lemur-stopwords.txt\n", + "\n", + "tok = metapy.analyzers.ListFilter(tok, \"lemur-stopwords.txt\", metapy.analyzers.ListFilter.Type.Reject)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Here we've downloaded a common list of stopwords obtained from the [Lemur project](http://lemurproject.org) and created a `ListFilter` to reject any tokens that occur in that list of words.\n", + "\n", + "You can see how much of a difference removing stopwords can make on the size of a document's token stream! This translates to a lot of space savings in the inverted index as well." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Another common filter that people use is called a stemmer, or lemmatizer. This kind of filter tries to modify individual tokens in such a way that different inflected forms of a word all reduce to the same representation. This lets you, for example, find documents about a \"run\" when you search \"running\" or \"runs\". A common stemmer is the [Porter2 Stemmer](http://snowball.tartarus.org/algorithms/english/stemmer.html), which MeTA has an implementation of. Let's try it!" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[\"can't\", 'believ', 'cost', '19.95', 'find', '30']" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.Porter2Filter(tok)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Notice how \"believe\" becomes \"believ\" and \"costs\" becomes \"cost\". Stemming can help search by allowing queries to return more matched documents by relaxing what it means for a document to match a query term. Note that it's important to ensure that queries are tokenized in the *exact same way* as your documents were before indexing them. If you ignore this, your query is unlikely to contain the raw token \"believ\" and you'll miss a lot of results." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Finally, after you've got the token stream configured the way you'd like, it's time to analyze the document by consuming each token from its token stream and performing some actions based on these tokens. In the simplest case, which often is enough for \"good enough\" search results, our action can simply be counting how many times these tokens occur.\n", + "\n", + "For clarity, let's switch back to a simpler token stream first. Write me a token stream that tokenizes using the Unicode standard, and then lowercases each token. (Hint: `help(metapy.analyzers)`.)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on module metapy.metapy.analyzers in metapy.metapy:\n", + "\n", + "NAME\n", + " metapy.metapy.analyzers\n", + "\n", + "CLASSES\n", + " pybind11_builtins.pybind11_object_48(builtins.object)\n", + " Analyzer\n", + " MultiAnalyzer\n", + " NGramWordAnalyzer\n", + " TokenStream\n", + " AlphaFilter\n", + " CharacterTokenizer\n", + " EmptySentenceFilter\n", + " EnglishNormalizer\n", + " ICUFilter\n", + " ICUTokenizer\n", + " LengthFilter\n", + " ListFilter\n", + " LowercaseFilter\n", + " PennTreebankNormalizer\n", + " Porter2Filter\n", + " SentenceBoundaryAdder\n", + " \n", + " class AlphaFilter(TokenStream)\n", + " | Method resolution order:\n", + " | AlphaFilter\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.AlphaFilter, arg0: metapy.metapy.analyzers.TokenStream) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class Analyzer(pybind11_builtins.pybind11_object_48)\n", + " | Method resolution order:\n", + " | Analyzer\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.Analyzer) -> None\n", + " | \n", + " | analyze(...) from builtins.PyCapsule\n", + " | analyze(self: metapy.metapy.analyzers.Analyzer, arg0: metapy.metapy.index.Document) -> dict\n", + " | \n", + " | featurize(...) from builtins.PyCapsule\n", + " | featurize(self: metapy.metapy.analyzers.Analyzer, arg0: metapy.metapy.index.Document) -> dict\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class CharacterTokenizer(TokenStream)\n", + " | Method resolution order:\n", + " | CharacterTokenizer\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.CharacterTokenizer) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class EmptySentenceFilter(TokenStream)\n", + " | Method resolution order:\n", + " | EmptySentenceFilter\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.EmptySentenceFilter, arg0: metapy.metapy.analyzers.TokenStream) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class EnglishNormalizer(TokenStream)\n", + " | Method resolution order:\n", + " | EnglishNormalizer\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.EnglishNormalizer, arg0: metapy.metapy.analyzers.TokenStream) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class ICUFilter(TokenStream)\n", + " | Method resolution order:\n", + " | ICUFilter\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.ICUFilter, arg0: metapy.metapy.analyzers.TokenStream, arg1: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class ICUTokenizer(TokenStream)\n", + " | Method resolution order:\n", + " | ICUTokenizer\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.ICUTokenizer, suppress_tags: bool=False) -> None\n", + " | \n", + " | Creates a tokenizer using the UTF text segmentation standard\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class LengthFilter(TokenStream)\n", + " | Method resolution order:\n", + " | LengthFilter\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.LengthFilter, source: metapy.metapy.analyzers.TokenStream, min: int, max: int) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class ListFilter(TokenStream)\n", + " | Method resolution order:\n", + " | ListFilter\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.ListFilter, arg0: metapy.metapy.analyzers.TokenStream, arg1: str, arg2: metapy.metapy.analyzers.Type) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes defined here:\n", + " | \n", + " | Type = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class LowercaseFilter(TokenStream)\n", + " | Method resolution order:\n", + " | LowercaseFilter\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.LowercaseFilter, arg0: metapy.metapy.analyzers.TokenStream) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class MultiAnalyzer(Analyzer)\n", + " | Method resolution order:\n", + " | MultiAnalyzer\n", + " | Analyzer\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(self, /, *args, **kwargs)\n", + " | Initialize self. See help(type(self)) for accurate signature.\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from Analyzer:\n", + " | \n", + " | analyze(...) from builtins.PyCapsule\n", + " | analyze(self: metapy.metapy.analyzers.Analyzer, arg0: metapy.metapy.index.Document) -> dict\n", + " | \n", + " | featurize(...) from builtins.PyCapsule\n", + " | featurize(self: metapy.metapy.analyzers.Analyzer, arg0: metapy.metapy.index.Document) -> dict\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class NGramWordAnalyzer(Analyzer)\n", + " | Method resolution order:\n", + " | NGramWordAnalyzer\n", + " | Analyzer\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.NGramWordAnalyzer, arg0: int, arg1: metapy.metapy.analyzers.TokenStream) -> None\n", + " | \n", + " | analyze(...) from builtins.PyCapsule\n", + " | analyze(self: metapy.metapy.analyzers.NGramWordAnalyzer, arg0: metapy.metapy.index.Document) -> object\n", + " | \n", + " | featurize(...) from builtins.PyCapsule\n", + " | featurize(self: metapy.metapy.analyzers.NGramWordAnalyzer, arg0: metapy.metapy.index.Document) -> object\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class PennTreebankNormalizer(TokenStream)\n", + " | Method resolution order:\n", + " | PennTreebankNormalizer\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.PennTreebankNormalizer, arg0: metapy.metapy.analyzers.TokenStream) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class Porter2Filter(TokenStream)\n", + " | Method resolution order:\n", + " | Porter2Filter\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.Porter2Filter, arg0: metapy.metapy.analyzers.TokenStream) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class SentenceBoundaryAdder(TokenStream)\n", + " | Method resolution order:\n", + " | SentenceBoundaryAdder\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.SentenceBoundaryAdder, arg0: metapy.metapy.analyzers.TokenStream) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from TokenStream:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes inherited from TokenStream:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " \n", + " class TokenStream(pybind11_builtins.pybind11_object_48)\n", + " | Method resolution order:\n", + " | TokenStream\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __bool__(...) from builtins.PyCapsule\n", + " | __bool__(self: metapy.metapy.analyzers.TokenStream) -> bool\n", + " | \n", + " | __deepcopy__(...) from builtins.PyCapsule\n", + " | __deepcopy__(self: metapy.metapy.analyzers.TokenStream, arg0: dict) -> metapy.metapy.analyzers.TokenStream\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.analyzers.TokenStream) -> None\n", + " | \n", + " | __iter__(...) from builtins.PyCapsule\n", + " | __iter__(self: object) -> py_token_stream_iterator\n", + " | \n", + " | next(...) from builtins.PyCapsule\n", + " | next(self: metapy.metapy.analyzers.TokenStream) -> str\n", + " | \n", + " | set_content(...) from builtins.PyCapsule\n", + " | set_content(self: metapy.metapy.analyzers.TokenStream, arg0: str) -> None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes defined here:\n", + " | \n", + " | Iterator = \n", + " | \n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + "\n", + "FUNCTIONS\n", + " load(...) method of builtins.PyCapsule instance\n", + " load(arg0: str) -> metapy.metapy.analyzers.Analyzer\n", + " \n", + " register_filter(...) method of builtins.PyCapsule instance\n", + " register_filter(arg0: object) -> None\n", + "\n", + "FILE\n", + " (built-in)\n", + "\n", + "\n" + ] + } + ], + "source": [ + "help(metapy.analyzers)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['i',\n", + " 'said',\n", + " 'that',\n", + " 'i',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " 'i',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '$',\n", + " '30',\n", + " 'before',\n", + " '.']" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.ICUTokenizer(suppress_tags=True)\n", + "tok = metapy.analyzers.LowercaseFilter(tok)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's count how often each individual token appears in the stream. You might have called this representation the \"bag of words\" representation, but it is also often called \"unigram word counts\". In MeTA, classes that consume a token stream and emit a document representation are called Analyzers." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I said that I can't believe that it only costs $19.95! I could only find it for more than $30 before.\n" + ] + }, + { + "data": { + "text/plain": [ + "{'!': 1,\n", + " '$': 2,\n", + " '.': 1,\n", + " '19.95': 1,\n", + " '30': 1,\n", + " 'before': 1,\n", + " 'believe': 1,\n", + " \"can't\": 1,\n", + " 'costs': 1,\n", + " 'could': 1,\n", + " 'find': 1,\n", + " 'for': 1,\n", + " 'i': 3,\n", + " 'it': 2,\n", + " 'more': 1,\n", + " 'only': 2,\n", + " 'said': 1,\n", + " 'than': 1,\n", + " 'that': 2}" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana = metapy.analyzers.NGramWordAnalyzer(1, tok)\n", + "print(doc.content())\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "If you noticed the name of the analyzer, you might have realized that you can count not just individual tokens, but groups of them. \"Unigram\" means \"1-gram\", and we count individual tokens. \"Bigram\" means \"2-gram\", and we count adjacent tokens together as a group. Let's try that now." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{('!', 'i'): 1,\n", + " ('$', '19.95'): 1,\n", + " ('$', '30'): 1,\n", + " ('19.95', '!'): 1,\n", + " ('30', 'before'): 1,\n", + " ('before', '.'): 1,\n", + " ('believe', 'that'): 1,\n", + " (\"can't\", 'believe'): 1,\n", + " ('costs', '$'): 1,\n", + " ('could', 'only'): 1,\n", + " ('find', 'it'): 1,\n", + " ('for', 'more'): 1,\n", + " ('i', \"can't\"): 1,\n", + " ('i', 'could'): 1,\n", + " ('i', 'said'): 1,\n", + " ('it', 'for'): 1,\n", + " ('it', 'only'): 1,\n", + " ('more', 'than'): 1,\n", + " ('only', 'costs'): 1,\n", + " ('only', 'find'): 1,\n", + " ('said', 'that'): 1,\n", + " ('than', '$'): 1,\n", + " ('that', 'i'): 1,\n", + " ('that', 'it'): 1}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana = metapy.analyzers.NGramWordAnalyzer(2, tok)\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now the individual \"tokens\" we're counting are pairs of tokens. You can analyze any n-gram of tokens you would like to in this way (and this is a simple way to attempt to support phrase search). Note, however, that as you increase the size of the n-grams you are counting, you are also increasing (exponentially!) the number of possible n-grams you could observe, so there's no free lunch here.\n", + "\n", + "This analysis pipeline feeds both the creation of the `InvertedIndex`, which is used for search applications, and the `ForwardIndex`, which is used for topic modeling and classification applications. For classification, sometimes looking at n-grams of characters is useful." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{(' ', '$', '1', '9'): 1,\n", + " (' ', '$', '3', '0'): 1,\n", + " (' ', 'I', ' ', 'c'): 2,\n", + " (' ', 'b', 'e', 'f'): 1,\n", + " (' ', 'b', 'e', 'l'): 1,\n", + " (' ', 'c', 'a', 'n'): 1,\n", + " (' ', 'c', 'o', 's'): 1,\n", + " (' ', 'c', 'o', 'u'): 1,\n", + " (' ', 'f', 'i', 'n'): 1,\n", + " (' ', 'f', 'o', 'r'): 1,\n", + " (' ', 'i', 't', ' '): 2,\n", + " (' ', 'm', 'o', 'r'): 1,\n", + " (' ', 'o', 'n', 'l'): 2,\n", + " (' ', 's', 'a', 'i'): 1,\n", + " (' ', 't', 'h', 'a'): 3,\n", + " ('!', ' ', 'I', ' '): 1,\n", + " ('$', '1', '9', '.'): 1,\n", + " ('$', '3', '0', ' '): 1,\n", + " (\"'\", 't', ' ', 'b'): 1,\n", + " ('.', '9', '5', '!'): 1,\n", + " ('0', ' ', 'b', 'e'): 1,\n", + " ('1', '9', '.', '9'): 1,\n", + " ('3', '0', ' ', 'b'): 1,\n", + " ('5', '!', ' ', 'I'): 1,\n", + " ('9', '.', '9', '5'): 1,\n", + " ('9', '5', '!', ' '): 1,\n", + " ('I', ' ', 'c', 'a'): 1,\n", + " ('I', ' ', 'c', 'o'): 1,\n", + " ('I', ' ', 's', 'a'): 1,\n", + " ('a', 'i', 'd', ' '): 1,\n", + " ('a', 'n', ' ', '$'): 1,\n", + " ('a', 'n', \"'\", 't'): 1,\n", + " ('a', 't', ' ', 'I'): 1,\n", + " ('a', 't', ' ', 'i'): 1,\n", + " ('b', 'e', 'f', 'o'): 1,\n", + " ('b', 'e', 'l', 'i'): 1,\n", + " ('c', 'a', 'n', \"'\"): 1,\n", + " ('c', 'o', 's', 't'): 1,\n", + " ('c', 'o', 'u', 'l'): 1,\n", + " ('d', ' ', 'i', 't'): 1,\n", + " ('d', ' ', 'o', 'n'): 1,\n", + " ('d', ' ', 't', 'h'): 1,\n", + " ('e', ' ', 't', 'h'): 2,\n", + " ('e', 'f', 'o', 'r'): 1,\n", + " ('e', 'l', 'i', 'e'): 1,\n", + " ('e', 'v', 'e', ' '): 1,\n", + " ('f', 'i', 'n', 'd'): 1,\n", + " ('f', 'o', 'r', ' '): 1,\n", + " ('f', 'o', 'r', 'e'): 1,\n", + " ('h', 'a', 'n', ' '): 1,\n", + " ('h', 'a', 't', ' '): 2,\n", + " ('i', 'd', ' ', 't'): 1,\n", + " ('i', 'e', 'v', 'e'): 1,\n", + " ('i', 'n', 'd', ' '): 1,\n", + " ('i', 't', ' ', 'f'): 1,\n", + " ('i', 't', ' ', 'o'): 1,\n", + " ('l', 'd', ' ', 'o'): 1,\n", + " ('l', 'i', 'e', 'v'): 1,\n", + " ('l', 'y', ' ', 'c'): 1,\n", + " ('l', 'y', ' ', 'f'): 1,\n", + " ('m', 'o', 'r', 'e'): 1,\n", + " ('n', ' ', '$', '3'): 1,\n", + " ('n', \"'\", 't', ' '): 1,\n", + " ('n', 'd', ' ', 'i'): 1,\n", + " ('n', 'l', 'y', ' '): 2,\n", + " ('o', 'n', 'l', 'y'): 2,\n", + " ('o', 'r', ' ', 'm'): 1,\n", + " ('o', 'r', 'e', ' '): 1,\n", + " ('o', 'r', 'e', '.'): 1,\n", + " ('o', 's', 't', 's'): 1,\n", + " ('o', 'u', 'l', 'd'): 1,\n", + " ('r', ' ', 'm', 'o'): 1,\n", + " ('r', 'e', ' ', 't'): 1,\n", + " ('s', ' ', '$', '1'): 1,\n", + " ('s', 'a', 'i', 'd'): 1,\n", + " ('s', 't', 's', ' '): 1,\n", + " ('t', ' ', 'I', ' '): 1,\n", + " ('t', ' ', 'b', 'e'): 1,\n", + " ('t', ' ', 'f', 'o'): 1,\n", + " ('t', ' ', 'i', 't'): 1,\n", + " ('t', ' ', 'o', 'n'): 1,\n", + " ('t', 'h', 'a', 'n'): 1,\n", + " ('t', 'h', 'a', 't'): 2,\n", + " ('t', 's', ' ', '$'): 1,\n", + " ('u', 'l', 'd', ' '): 1,\n", + " ('v', 'e', ' ', 't'): 1,\n", + " ('y', ' ', 'c', 'o'): 1,\n", + " ('y', ' ', 'f', 'i'): 1}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.CharacterTokenizer()\n", + "ana = metapy.analyzers.NGramWordAnalyzer(4, tok)\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Different analyzers can be combined together to create document representations that have many unique perspectives. Once things start to get more complicated, we recommend using a configuration file to specify each of the analyzers you wish to combine for your document representation." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's explore something a little bit different. MeTA also has a natural language processing (NLP) component, which currently supports two major NLP tasks: part-of-speech tagging and syntactic parsing.\n", + "\n", + "(Does anyone know what part-of-speech tagging is?) POS tagging is a task in NLP that involves identifying a type for each word in a sentence. For example, POS tagging can be used to identify all of the nouns in a sentence, or all of the verbs, or adjectives, or... This is useful as first step towards developing an understanding of the meaning of a particular sentence." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "MeTA places its POS tagging component in its \"sequences\" library. Let's play with some sequences first to get an idea of how they work. We'll start of by creating a sequence." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "seq = metapy.sequence.Sequence()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, we can add individual words to this sequence. Sequences consist of a list of `Observation`s, which are essentially (word, tag) pairs. If we don't yet know the tags for a `Sequence`, we can just add individual words and leave the tags unset. Words are called \"symbols\" in the library terminology." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(The, ???), (dog, ???), (ran, ???), (across, ???), (the, ???), (park, ???), (., ???)\n" + ] + } + ], + "source": [ + "for word in [\"The\", \"dog\", \"ran\", \"across\", \"the\", \"park\", \".\"]:\n", + " seq.add_symbol(word)\n", + "print(seq)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The printed form of the sequence shows that we do not yet know the tags for each word. Let's fill them in by using a pre-trained POS-tagger model that's distributed with MeTA." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2017-03-28 12:52:33-- https://github.com/meta-toolkit/meta/releases/download/v3.0.1/greedy-perceptron-tagger.tar.gz\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving github.com... 192.30.253.113, 192.30.253.112\n", + "Connecting to github.com|192.30.253.113|:443... connected.\n", + "HTTP request sent, awaiting response... 302 Found\n", + "Location: https://github-cloud.s3.amazonaws.com/releases/16466317/5becfb4a-07f9-11e7-9984-0b59d0729937.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAISTNZFOVBIJMK3TQ%2F20170328%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20170328T175233Z&X-Amz-Expires=300&X-Amz-Signature=9ff6c60870700e0c06de2dfd82410a889aeee8a791c98830969c9d27c913149e&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dgreedy-perceptron-tagger.tar.gz&response-content-type=application%2Foctet-stream [following]\n", + "--2017-03-28 12:52:33-- https://github-cloud.s3.amazonaws.com/releases/16466317/5becfb4a-07f9-11e7-9984-0b59d0729937.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAISTNZFOVBIJMK3TQ%2F20170328%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20170328T175233Z&X-Amz-Expires=300&X-Amz-Signature=9ff6c60870700e0c06de2dfd82410a889aeee8a791c98830969c9d27c913149e&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dgreedy-perceptron-tagger.tar.gz&response-content-type=application%2Foctet-stream\n", + "Resolving github-cloud.s3.amazonaws.com... 54.231.121.43\n", + "Connecting to github-cloud.s3.amazonaws.com|54.231.121.43|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 6622528 (6.3M) [application/octet-stream]\n", + "Saving to: ‘greedy-perceptron-tagger.tar.gz’\n", + "\n", + "greedy-perceptron-t 100%[===================>] 6.32M 5.59MB/s in 1.1s \n", + "\n", + "2017-03-28 12:52:35 (5.59 MB/s) - ‘greedy-perceptron-tagger.tar.gz’ saved [6622528/6622528]\n", + "\n", + "perceptron-tagger/\n", + "perceptron-tagger/feature.mapping.gz\n", + "perceptron-tagger/label.mapping\n", + "perceptron-tagger/tagger.model.gz\n" + ] + } + ], + "source": [ + "!wget -nc https://github.com/meta-toolkit/meta/releases/download/v3.0.1/greedy-perceptron-tagger.tar.gz\n", + "!tar xvf greedy-perceptron-tagger.tar.gz" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "tagger = metapy.sequence.PerceptronTagger(\"perceptron-tagger/\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now let's fill in the missing tags in our sentence based on the best guess this model has." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(The, DT), (dog, NN), (ran, VBD), (across, IN), (the, DT), (park, NN), (., .)\n" + ] + } + ], + "source": [ + "tagger.tag(seq)\n", + "print(seq)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Each tag indicates the type of a word, and this particular tagger was trained to output the tags present in the [Penn Treebank tagset](https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html).\n", + "\n", + "But what if we want to POS-tag a document?" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I said that I can't believe that it only costs $19.95! I could only find it for more than $30 before.\n" + ] + } + ], + "source": [ + "print(doc.content())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We need a way of going from a document to a list of `Sequence`s, each representing an individual sentence. I'll get you started." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['',\n", + " 'I',\n", + " 'said',\n", + " 'that',\n", + " 'I',\n", + " 'ca',\n", + " \"n't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " '',\n", + " '',\n", + " 'I',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '$',\n", + " '30',\n", + " 'before',\n", + " '.',\n", + " '']" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.ICUTokenizer() # keep sentence boundaries!\n", + "tok = metapy.analyzers.PennTreebankNormalizer(tok)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "(Notice that the `PennTreebankNormalizer` modifies some tokens to better match the conventions of the Penn Treebank training data. This should help improve performance a little.)\n", + "\n", + "Now, write me a function that can take a token stream that contains sentence boundary tags and returns a list of `Sequence` objects. Don't include the sentence boundary tags in the actual `Sequence` objects." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "def extract_sequences(tok):\n", + " sequences = []\n", + " for token in tok:\n", + " if token == '':\n", + " sequences.append(metapy.sequence.Sequence())\n", + " elif token != '':\n", + " sequences[-1].add_symbol(token) \n", + " return sequences" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(I, PRP), (said, VBD), (that, IN), (I, PRP), (ca, MD), (n't, RB), (believe, VB), (that, IN), (it, PRP), (only, RB), (costs, VBZ), ($, $), (19.95, CD), (!, .)\n", + "(I, PRP), (could, MD), (only, RB), (find, VB), (it, PRP), (for, IN), (more, JJR), (than, IN), ($, $), (30, CD), (before, IN), (., .)\n" + ] + } + ], + "source": [ + "tok.set_content(doc.content())\n", + "for seq in extract_sequences(tok):\n", + " tagger.tag(seq)\n", + " print(seq)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "This is still a rather shallow understanding of these sentences. The next major leap is to parse these sequences of POS-tagged words to obtain a tree for each sentence. These trees, in our case, will represent the hierarchical phrase structure of a single sentence by grouping together tokens that belong to one phrase together, and showing how small phrases combine into larger phrases, and eventually a sentence.\n", + "\n", + "Let's try parsing the sentences in our document using a pre-tranned constituency parser that's distributed with MeTA." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2017-03-28 12:52:36-- https://github.com/meta-toolkit/meta/releases/download/v3.0.1/greedy-constituency-parser.tar.gz\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving github.com... 192.30.253.113, 192.30.253.112\n", + "Connecting to github.com|192.30.253.113|:443... connected.\n", + "HTTP request sent, awaiting response... 302 Found\n", + "Location: https://github-cloud.s3.amazonaws.com/releases/16466317/5bec2648-07f9-11e7-9d02-cb0d49fd3f76.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAISTNZFOVBIJMK3TQ%2F20170328%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20170328T175236Z&X-Amz-Expires=300&X-Amz-Signature=5ea88ec218ec18f32366d6d448437787721e819451b371250e390c89cec4ca9c&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dgreedy-constituency-parser.tar.gz&response-content-type=application%2Foctet-stream [following]\n", + "--2017-03-28 12:52:36-- https://github-cloud.s3.amazonaws.com/releases/16466317/5bec2648-07f9-11e7-9d02-cb0d49fd3f76.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAISTNZFOVBIJMK3TQ%2F20170328%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20170328T175236Z&X-Amz-Expires=300&X-Amz-Signature=5ea88ec218ec18f32366d6d448437787721e819451b371250e390c89cec4ca9c&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dgreedy-constituency-parser.tar.gz&response-content-type=application%2Foctet-stream\n", + "Resolving github-cloud.s3.amazonaws.com... 54.231.97.200\n", + "Connecting to github-cloud.s3.amazonaws.com|54.231.97.200|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 55347000 (53M) [application/octet-stream]\n", + "Saving to: ‘greedy-constituency-parser.tar.gz’\n", + "\n", + "greedy-constituency 100%[===================>] 52.78M 8.66MB/s in 6.4s \n", + "\n", + "2017-03-28 12:52:43 (8.19 MB/s) - ‘greedy-constituency-parser.tar.gz’ saved [55347000/55347000]\n", + "\n", + "parser/\n", + "parser/parser.trans.gz\n", + "parser/parser.model.gz\n" + ] + } + ], + "source": [ + "!wget -nc https://github.com/meta-toolkit/meta/releases/download/v3.0.1/greedy-constituency-parser.tar.gz\n", + "!tar xvf greedy-constituency-parser.tar.gz" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "parser = metapy.parser.Parser(\"parser/\")" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I could only find it for more than $ 30 before .\n", + "(I, PRP), (could, MD), (only, RB), (find, VB), (it, PRP), (for, IN), (more, JJR), (than, IN), ($, $), (30, CD), (before, IN), (., .)\n", + "(ROOT\n", + " (S\n", + " (NP (PRP I))\n", + " (VP\n", + " (MD could)\n", + " (ADVP (RB only))\n", + " (VP\n", + " (VB find)\n", + " (NP (PRP it))\n", + " (PP\n", + " (IN for)\n", + " (NP\n", + " (QP\n", + " (JJR more)\n", + " (IN than)\n", + " ($ $)\n", + " (CD 30))))\n", + " (ADVP (IN before))))\n", + " (. .)))\n", + "\n" + ] + } + ], + "source": [ + "print(' '.join([obs.symbol for obs in seq]))\n", + "print(seq)\n", + "tree = parser.parse(seq)\n", + "print(tree.pretty_str())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "(You can also play with this with a [prettier online demo](https://meta-toolkit.org/nlp-demo.html).)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can now parse all of the sentences in our document." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(ROOT\n", + " (S\n", + " (NP (PRP I))\n", + " (VP\n", + " (VBD said)\n", + " (SBAR\n", + " (IN that)\n", + " (S\n", + " (NP (PRP I))\n", + " (VP\n", + " (MD ca)\n", + " (RB n't)\n", + " (VP\n", + " (VB believe)\n", + " (SBAR\n", + " (IN that)\n", + " (S\n", + " (NP (PRP it))\n", + " (ADVP (RB only))\n", + " (VP\n", + " (VBZ costs)\n", + " (NP\n", + " ($ $)\n", + " (CD 19.95))))))))))\n", + " (. !)))\n", + "\n", + "(ROOT\n", + " (S\n", + " (NP (PRP I))\n", + " (VP\n", + " (MD could)\n", + " (ADVP (RB only))\n", + " (VP\n", + " (VB find)\n", + " (NP (PRP it))\n", + " (PP\n", + " (IN for)\n", + " (NP\n", + " (QP\n", + " (JJR more)\n", + " (IN than)\n", + " ($ $)\n", + " (CD 30))))\n", + " (ADVP (IN before))))\n", + " (. .)))\n", + "\n" + ] + } + ], + "source": [ + "tok.set_content(doc.content())\n", + "for seq in extract_sequences(tok):\n", + " tagger.tag(seq)\n", + " print(parser.parse(seq).pretty_str())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now that we know how to build these phrase structure trees from POS-tagged sentences extracted from raw text, let's explore a simple way we might be able to exploit this knowledge to help a downstream task.\n", + "\n", + "Our goal is going to be to extract the Subject-Verb-Object triples from some simple sentences. This will allow us to understand who is doing what to whom, which is knowledge that might be useful for lots of downstream tasks as diverse as question answering to stock market prediction. We should be able to extract these from our constituency parses. (This, of course, isn't the only way, and this method is quite naive. However, the implementation is simple enough that I think you should be able to grasp it in a single lecture.)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "First, let's grab our sample data. This is a collection of BBC news headlines that will serve as our \"simple\" sentences." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2017-03-28 12:52:48-- https://meta-toolkit.org/data/2017-03-27/headlines.tar.gz\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving meta-toolkit.org... 50.116.41.177, 2600:3c02::f03c:91ff:feae:b777\n", + "Connecting to meta-toolkit.org|50.116.41.177|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 31358 (31K) [application/octet-stream]\n", + "Saving to: ‘headlines.tar.gz’\n", + "\n", + "headlines.tar.gz 100%[===================>] 30.62K --.-KB/s in 0.002s \n", + "\n", + "2017-03-28 12:52:48 (15.1 MB/s) - ‘headlines.tar.gz’ saved [31358/31358]\n", + "\n", + "headlines/\n", + "headlines/tech.txt\n", + "headlines/entertainment.txt\n", + "headlines/politics.txt\n", + "headlines/README.md\n", + "headlines/sport.txt\n", + "headlines/business.txt\n", + "\n", + "README:\n", + "http://mlg.ucd.ie/datasets/bbc.html\n", + "\n", + "Exactracted first sentence of each doc from this dataset.\n" + ] + } + ], + "source": [ + "!wget -nc https://meta-toolkit.org/data/2017-03-27/headlines.tar.gz # please be nice!\n", + "!tar xvf headlines.tar.gz\n", + "!echo \"\" && echo \"README:\"\n", + "!cat headlines/README.md" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Let's look at the first headline of the business category." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Brazil approves bankruptcy reform'" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "with open(\"headlines/business.txt\") as f:\n", + " business = f.readlines()\n", + "business[0].strip()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "This looks simple enough. Let's see how it gets tagged." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(Brazil, NNP), (approves, VBZ), (bankruptcy, NN), (reform, NN)\n" + ] + } + ], + "source": [ + "tok.set_content(business[0].strip())\n", + "sequence = extract_sequences(tok)[0]\n", + "tagger.tag(sequence)\n", + "print(sequence)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Let's also parse it." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(ROOT\n", + " (S\n", + " (NP (NNP Brazil))\n", + " (VP\n", + " (VBZ approves)\n", + " (NP\n", + " (NN bankruptcy)\n", + " (NN reform)))))\n", + "\n" + ] + } + ], + "source": [ + "tree = parser.parse(sequence)\n", + "print(tree.pretty_str())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Great. We can now start to develop our technique. We can see that the subject here is the first noun phrase (NP), the verb is the first verb-like token in the VP, and the object is the NP within that VP.\n", + "\n", + "We're going to need to traverse this tree to extract what we want. MeTA supports this by exploiting the [Visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern), so the easiest way for us to get at what we're looking for is to write some classes that encapsulate the traversal we want to perform and keep track of things within this tree that we are interested in.\n", + "\n", + "Let's write our first simple visitor that traverses the tree to find the first NP node, at which point it will stop and store the root of that subtree." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on class Visitor in module metapy.metapy.parser:\n", + "\n", + "class Visitor(pybind11_builtins.pybind11_object_48)\n", + " | Method resolution order:\n", + " | Visitor\n", + " | pybind11_builtins.pybind11_object_48\n", + " | builtins.object\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(...) from builtins.PyCapsule\n", + " | __init__(self: metapy.metapy.parser.Visitor) -> None\n", + " | \n", + " | visit_internal(...) from builtins.PyCapsule\n", + " | visit_internal(self: metapy.metapy.parser.Visitor, arg0: metapy.metapy.parser.InternalNode) -> object\n", + " | \n", + " | visit_leaf(...) from builtins.PyCapsule\n", + " | visit_leaf(self: metapy.metapy.parser.Visitor, arg0: metapy.metapy.parser.LeafNode) -> object\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Methods inherited from pybind11_builtins.pybind11_object_48:\n", + " | \n", + " | __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + "\n" + ] + } + ], + "source": [ + "help(metapy.parser.Visitor)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "class NounPhraseFinder(metapy.parser.Visitor):\n", + " def __init__(self):\n", + " self.node = None\n", + " super(NounPhraseFinder, self).__init__() # required; invoke base class __init__\n", + " \n", + " def visit_leaf(self, node):\n", + " pass # we don't care about leaf nodes\n", + " \n", + " def visit_internal(self, node):\n", + " if self.node:\n", + " return\n", + "\n", + " # we do care about internal nodes; check if it is an NP\n", + " if node.category() == 'NP':\n", + " # store this node and stop the traversal\n", + " self.node = node\n", + " else:\n", + " # continue traversing by visiting all of the child nodes\n", + " node.each_child(lambda child: child.accept(self))" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NP with 1 child(ren)\n" + ] + } + ], + "source": [ + "npf = NounPhraseFinder()\n", + "tree.visit(npf)\n", + "print(\"{} with {} child(ren)\".format(npf.node.category(), npf.node.num_children()))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now that we have that working, we should be able to make a more generic PhraseFinder that finds the first internal node that matches a specific node category. We'll need one for finding the first NP and one for finding the first VP anyway, so this will be helpful." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "class PhraseFinder(metapy.parser.Visitor):\n", + " def __init__(self, category):\n", + " super(PhraseFinder, self).__init__()\n", + " self.node = None\n", + " self.category = category\n", + " \n", + " def visit_leaf(self, node):\n", + " pass # we don't care about leaf nodes\n", + " \n", + " def visit_internal(self, node):\n", + " if self.node:\n", + " return\n", + " \n", + " if node.category() == self.category:\n", + " self.node = node\n", + " else:\n", + " node.each_child(lambda child: child.accept(self))" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NP with 1 child(ren)\n", + "VP with 2 child(ren)\n" + ] + } + ], + "source": [ + "npf = PhraseFinder('NP')\n", + "vpf = PhraseFinder('VP')\n", + "tree.visit(npf)\n", + "tree.visit(vpf)\n", + "for node in [npf.node, vpf.node]:\n", + " print(\"{} with {} child(ren)\".format(node.category(), node.num_children()))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now that we can find the first internal node matching a category label, we need to set about extracting the actual leaf nodes we care about. Fortunately there is already a visitor that can extract all leaf nodes from a subtree, so we can use that to get started.\n", + "\n", + "From the first noun phrase, we want to extract all leaf nodes that are noun-like tags and join them together to make up our subject." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Brazil\n" + ] + } + ], + "source": [ + "noun_tags = set(['NN', 'NNS', 'NNP', 'NNPS'])\n", + "lnf = metapy.parser.LeafNodeFinder()\n", + "npf.node.accept(lnf)\n", + "subject = ' '.join([leaf.word() for leaf in lnf.leaves() if leaf.category() in noun_tags])\n", + "print(subject)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "And from the first verb phrase, we want to extract (1) the first verb-like leaf node to be the verb and (2) the noun-like tags in the first NP that occurs within that VP. We should be able to re-use some existing code we've already written." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "approves\n" + ] + } + ], + "source": [ + "verb_tags = set(['VB', 'VBD', 'VBG', 'VBN', 'VBP', 'VBZ'])\n", + "lnf = metapy.parser.LeafNodeFinder()\n", + "vpf.node.accept(lnf)\n", + "verb = next(leaf.word() for leaf in lnf.leaves() if leaf.category() in verb_tags)\n", + "print(verb)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bankruptcy reform\n" + ] + } + ], + "source": [ + "np_finder = PhraseFinder('NP')\n", + "vpf.node.accept(np_finder)\n", + "lnf = metapy.parser.LeafNodeFinder()\n", + "np_finder.node.accept(lnf)\n", + "obj = ' '.join([leaf.word() for leaf in lnf.leaves() if leaf.category() in noun_tags])\n", + "print(obj)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SUBJ: Brazil VERB: approves OBJ: bankruptcy reform\n" + ] + } + ], + "source": [ + "print(\"SUBJ: {} VERB: {} OBJ: {}\".format(subject, verb, obj))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Putting this all together, we can write a visitor to extract (SUBJ, VERB, OBJ) triples." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "class SVOExtractor(metapy.parser.Visitor):\n", + " noun_tags = set(['NN', 'NNS', 'NNP', 'NNPS'])\n", + " verb_tags = set(['VB', 'VBD', 'VBG', 'VBN', 'VBP', 'VBZ']) \n", + " \n", + " def __init__(self):\n", + " super(SVOExtractor, self).__init__()\n", + " self.subject = self.verb = self.object = None\n", + " \n", + " def extract_noun_tagged_words(self, node):\n", + " lnf = metapy.parser.LeafNodeFinder()\n", + " node.accept(lnf)\n", + " return ' '.join([leaf.word() for leaf in lnf.leaves() if leaf.category() in noun_tags])\n", + " \n", + " def visit_leaf(self, node):\n", + " pass # don't care about leaf nodes\n", + " \n", + " def visit_internal(self, node):\n", + " # find and handle the first NP\n", + " first_np = PhraseFinder('NP') \n", + " node.accept(first_np)\n", + " if first_np.node:\n", + " self.subject = self.extract_noun_tagged_words(first_np.node)\n", + " \n", + " # find and handle the first VP\n", + " first_vp = PhraseFinder('VP')\n", + " node.accept(first_vp)\n", + " \n", + " if first_vp.node:\n", + " # find the first NP within the first VP\n", + " vp_first_np = PhraseFinder('NP')\n", + " first_vp.node.accept(vp_first_np)\n", + " \n", + " if vp_first_np.node:\n", + " self.object = self.extract_noun_tagged_words(vp_first_np.node)\n", + " \n", + " lnf = metapy.parser.LeafNodeFinder()\n", + " first_vp.node.accept(lnf)\n", + " for leaf in lnf.leaves():\n", + " if leaf.category() in verb_tags:\n", + " self.verb = leaf.word()\n", + " break\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Brazil approves bankruptcy reform\n", + "SUBJ: Brazil VERB: approves OBJ: bankruptcy reform\n", + "German business confidence slides\n", + "SUBJ: business confidence slides VERB: None OBJ: None\n", + "Dollar slides ahead of New Year\n", + "SUBJ: Dollar slides New Year VERB: None OBJ: None\n", + "Aviation firms eye booming India\n", + "SUBJ: Aviation firms VERB: eye OBJ: India\n", + "Metlife buys up Citigroup insurer\n", + "SUBJ: Metlife VERB: buys OBJ: Citigroup insurer\n", + "US economy still growing says Fed\n", + "SUBJ: VERB: says OBJ: None\n", + "Russia WTO talks 'make progress'\n", + "SUBJ: Russia WTO talks make progress VERB: None OBJ: None\n", + "Deadline nears for Fiat-GM deal\n", + "SUBJ: Deadline VERB: nears OBJ: Fiat GM deal\n", + "Five million Germans out of work\n", + "SUBJ: Germans work VERB: None OBJ: None\n", + "Jobs go at Oracle after takeover\n", + "SUBJ: Jobs VERB: go OBJ: Oracle\n", + "Asian banks halt dollar's slide\n", + "SUBJ: banks VERB: halt OBJ: dollar slide\n", + "Markets signal Brazilian recovery\n", + "SUBJ: Markets VERB: signal OBJ: recovery\n", + "GE sees 'excellent' world economy\n", + "SUBJ: GE VERB: sees OBJ: world economy\n", + "Q&A: Malcolm Glazer and Man Utd\n", + "SUBJ: Q A Malcolm Glazer Man Utd VERB: None OBJ: None\n", + "China continues rapid growth\n", + "SUBJ: China VERB: continues OBJ: growth\n", + "M&S cuts prices by average of 24%\n", + "SUBJ: M S cuts prices average % VERB: None OBJ: None\n", + "Trial begins of Spain's top banker\n", + "SUBJ: Trial VERB: begins OBJ: Spain banker\n", + "Malaysia lifts Islamic bank limit\n", + "SUBJ: Malaysia VERB: lifts OBJ: Islamic bank limit\n", + "Giant waves damage S Asia economy\n", + "SUBJ: Giant VERB: waves OBJ: damage S Asia economy\n", + "Europe asks Asia for euro help\n", + "SUBJ: Europe VERB: asks OBJ: Asia\n", + "Troubled Marsh under SEC scrutiny\n", + "SUBJ: Marsh SEC scrutiny VERB: None OBJ: None\n", + "US to probe airline travel chaos\n", + "SUBJ: airline travel chaos VERB: probe OBJ: airline travel chaos\n", + "China's Shanda buys stake in Sina\n", + "SUBJ: China Shanda VERB: buys OBJ: stake Sina\n", + "Strong demand triggers oil rally\n", + "SUBJ: demand VERB: triggers OBJ: oil rally\n", + "Karachi stocks hit historic high\n", + "SUBJ: Karachi stocks VERB: hit OBJ: None\n", + "Senior Fannie Mae bosses resign\n", + "SUBJ: Fannie Mae bosses VERB: resign OBJ: None\n", + "Bank opts to leave rates on hold\n", + "SUBJ: Bank VERB: opts OBJ: rates\n", + "Standard Life cuts policy bonuses\n", + "SUBJ: Life cuts policy bonuses VERB: None OBJ: None\n", + "Ukraine revisits state sell-offs\n", + "SUBJ: Ukraine VERB: revisits OBJ: state\n", + "Venezuela reviews foreign deals\n", + "SUBJ: Venezuela VERB: reviews OBJ: deals\n", + "Fed chief warning on US deficit\n", + "SUBJ: Fed chief VERB: deficit OBJ: None\n", + "US industrial output growth eases\n", + "SUBJ: output growth eases VERB: None OBJ: None\n", + "IMF 'cuts' German growth estimate\n", + "SUBJ: IMF cuts growth estimate VERB: None OBJ: None\n", + "Electronics firms eye plasma deal\n", + "SUBJ: Electronics firms VERB: eye OBJ: plasma deal\n", + "Ethiopia's crop production up 24%\n", + "SUBJ: Ethiopia crop production % VERB: None OBJ: None\n", + "India widens access to telecoms\n", + "SUBJ: India VERB: widens OBJ: access telecoms\n", + "'Standoff' on Deutsche's LSE bid\n", + "SUBJ: Standoff Deutsche LSE bid VERB: None OBJ: None\n", + "JP Morgan admits US slavery links\n", + "SUBJ: JP Morgan VERB: admits OBJ: slavery links\n", + "Home loan approvals rising again\n", + "SUBJ: Home loan approvals VERB: rising OBJ: None\n", + "Bank payout to Pinochet victims\n", + "SUBJ: Bank payout Pinochet victims VERB: None OBJ: None\n", + "India's Reliance family feud heats up\n", + "SUBJ: India Reliance family feud VERB: heats OBJ: None\n", + "Tsunami cost hits Jakarta shares\n", + "SUBJ: Tsunami cost VERB: hits OBJ: Jakarta shares\n", + "ECB holds rates amid growth fears\n", + "SUBJ: ECB VERB: holds OBJ: rates\n", + "Ad sales boost Time Warner profit\n", + "SUBJ: Ad sales boost Time Warner profit VERB: None OBJ: None\n", + "Deutsche attacks Yukos case\n", + "SUBJ: Deutsche attacks Yukos case VERB: None OBJ: None\n", + "Latin America sees strong growth\n", + "SUBJ: Latin America VERB: sees OBJ: growth\n", + "Chinese exports rise 25% in 2004\n", + "SUBJ: exports VERB: rise OBJ: %\n", + "Mixed signals from French economy\n", + "SUBJ: signals economy VERB: None OBJ: None\n", + "Parmalat to return to stockmarket\n", + "SUBJ: Parmalat VERB: return OBJ: None\n", + "Krispy Kreme shares hit\n", + "SUBJ: Krispy Kreme shares VERB: hit OBJ: None\n", + "Watchdog probes Vivendi bond sale\n", + "SUBJ: Watchdog VERB: probes OBJ: Vivendi bond sale\n", + "Khodorkovsky ally denies charges\n", + "SUBJ: Khodorkovsky VERB: denies OBJ: charges\n", + "Profits jump at China's top bank\n", + "SUBJ: Profits VERB: jump OBJ: China bank\n", + "Parmalat bank barred from suing\n", + "SUBJ: Parmalat bank VERB: barred OBJ: \n", + "Germany nears 1990 jobless level\n", + "SUBJ: Germany VERB: nears OBJ: level\n", + "Peugeot deal boosts Mitsubishi\n", + "SUBJ: Peugeot deal boosts Mitsubishi VERB: None OBJ: None\n", + "WorldCom director admits lying\n", + "SUBJ: WorldCom director VERB: admits OBJ: None\n", + "Ask Jeeves tips online ad revival\n", + "SUBJ: Jeeves tips VERB: Ask OBJ: Jeeves tips\n", + "Euro firms miss out on optimism\n", + "SUBJ: Euro firms VERB: miss OBJ: optimism\n", + "Business fears over sluggish EU economy\n", + "SUBJ: Business fears EU economy VERB: None OBJ: None\n", + "Bush to get 'tough' on deficit\n", + "SUBJ: Bush VERB: get OBJ: deficit\n", + "SEC to rethink post-Enron rules\n", + "SUBJ: SEC VERB: rethink OBJ: post\n", + "EU 'too slow' on economic reforms\n", + "SUBJ: EU reforms VERB: None OBJ: None\n", + "Amex shares up on spin-off news\n", + "SUBJ: Amex shares spin news VERB: None OBJ: None\n", + "US bank boss hails 'genius' Smith\n", + "SUBJ: bank boss genius Smith VERB: hails OBJ: genius Smith\n", + "Mystery surrounds new Yukos owner\n", + "SUBJ: Mystery VERB: surrounds OBJ: Yukos owner\n", + "Mexican in US send $16bn home\n", + "SUBJ: VERB: send OBJ: home\n", + "Euronext 'poised to make LSE bid'\n", + "SUBJ: LSE bid VERB: None OBJ: None\n", + "Parmalat founder offers apology\n", + "SUBJ: Parmalat founder VERB: offers OBJ: apology\n", + "Turkey-Iran mobile deal 'at risk'\n", + "SUBJ: Turkey Iran deal risk VERB: None OBJ: None\n", + "Brazil plays down Varig rescue\n", + "SUBJ: Brazil VERB: plays OBJ: Varig rescue\n", + "High fuel prices hit BA's profits\n", + "SUBJ: fuel prices VERB: hit OBJ: BA profits\n", + "Bombardier chief to leave company\n", + "SUBJ: Bombardier chief company VERB: leave OBJ: company\n", + "Christmas shoppers flock to tills\n", + "SUBJ: Christmas shoppers VERB: flock OBJ: tills\n", + "Jobs growth still slow in the US\n", + "SUBJ: Jobs growth VERB: None OBJ: \n", + "Winter freeze keeps oil above $50\n", + "SUBJ: Winter freeze VERB: keeps OBJ: oil\n", + "US prepares for hybrid onslaught\n", + "SUBJ: VERB: prepares OBJ: hybrid onslaught\n", + "Indonesians face fuel price rise\n", + "SUBJ: Indonesians VERB: face OBJ: fuel price rise\n", + "Car giant hit by Mercedes slump\n", + "SUBJ: Car giant Mercedes slump VERB: hit OBJ: Mercedes slump\n", + "Bank voted 8-1 for no rate change\n", + "SUBJ: Bank VERB: voted OBJ: rate change\n", + "Brazil buy boosts Belgium's Inbev\n", + "SUBJ: Brazil VERB: buy OBJ: boosts Belgium Inbev\n", + "Tsunami slows Sri Lanka's growth\n", + "SUBJ: Tsunami VERB: slows OBJ: Sri Lanka growth\n", + "Japanese growth grinds to a halt\n", + "SUBJ: growth VERB: grinds OBJ: halt\n", + "Shares rise on new Man Utd offer\n", + "SUBJ: Shares VERB: rise OBJ: Man Utd offer\n", + "Takeover rumour lifts Exel shares\n", + "SUBJ: Takeover rumour VERB: lifts OBJ: Exel shares\n", + "Executive trio leave Aer Lingus\n", + "SUBJ: Executive trio VERB: leave OBJ: Aer Lingus\n", + "Businesses fail to plan for HIV\n", + "SUBJ: Businesses VERB: fail OBJ: HIV\n", + "Iranian MPs threaten mobile deal\n", + "SUBJ: MPs VERB: threaten OBJ: deal\n", + "Air passengers win new EU rights\n", + "SUBJ: Air passengers VERB: win OBJ: EU rights\n", + "Yukos drops banks from court bid\n", + "SUBJ: Yukos drops banks court bid VERB: None OBJ: None\n", + "Yukos seeks court action on sale\n", + "SUBJ: Yukos VERB: seeks OBJ: court action sale\n", + "Lesotho textile workers lose jobs\n", + "SUBJ: Lesotho textile workers VERB: lose OBJ: jobs\n", + "Oil rebounds from weather effect\n", + "SUBJ: Oil rebounds weather effect VERB: None OBJ: None\n", + "Cairn shares up on new oil find\n", + "SUBJ: Cairn shares oil find VERB: None OBJ: None\n", + "Huge rush for Jet Airways shares\n", + "SUBJ: rush Jet Airways shares VERB: None OBJ: None\n", + "Brewers' profits lose their fizz\n", + "SUBJ: Brewers profits VERB: lose OBJ: fizz\n", + "Winemaker rejects Foster's offer\n", + "SUBJ: Winemaker VERB: rejects OBJ: Foster offer\n", + "No seasonal lift for house market\n", + "SUBJ: lift house market VERB: None OBJ: None\n", + "Unilever shake up as profit slips\n", + "SUBJ: Unilever VERB: shake OBJ: profit slips\n", + "Japan's ageing workforce: built to last\n", + "SUBJ: Japan workforce VERB: built OBJ: None\n", + "US interest rates increased to 2%\n", + "SUBJ: interest rates % VERB: increased OBJ: %\n", + "Train strike grips Buenos Aires\n", + "SUBJ: Train strike grips Buenos Aires VERB: None OBJ: None\n", + "Axa Sun Life cuts bonus payments\n", + "SUBJ: Axa Sun Life cuts bonus payments VERB: None OBJ: None\n", + "Russian oil merger excludes Yukos\n", + "SUBJ: oil merger VERB: excludes OBJ: Yukos\n", + "Wembley firm won't make a profit\n", + "SUBJ: Wembley firm VERB: make OBJ: profit\n", + "Millions 'to lose textile jobs'\n", + "SUBJ: Millions textile jobs VERB: lose OBJ: textile jobs\n", + "BMW reveals new models pipeline\n", + "SUBJ: BMW VERB: reveals OBJ: models pipeline\n", + "French boss to leave EADS\n", + "SUBJ: boss EADS VERB: leave OBJ: EADS\n", + "Irish markets reach all-time high\n", + "SUBJ: markets VERB: reach OBJ: time\n", + "Argentina, Venezuela in oil deal\n", + "SUBJ: Argentina Venezuela oil deal VERB: None OBJ: None\n", + "Japan economy slides to recession\n", + "SUBJ: Japan economy VERB: slides OBJ: recession\n", + "Green reports shun supply chain\n", + "SUBJ: reports VERB: shun OBJ: supply chain\n", + "Georgia plans hidden asset pardon\n", + "SUBJ: Georgia VERB: plans OBJ: asset pardon\n", + "India's Deccan gets more planes\n", + "SUBJ: India Deccan VERB: gets OBJ: planes\n", + "Yukos unit fetches $9bn at auction\n", + "SUBJ: Yukos unit VERB: fetches OBJ: \n", + "Bargain calls widen Softbank loss\n", + "SUBJ: Bargain VERB: calls OBJ: Softbank loss\n", + "Lufthansa may sue over Bush visit\n", + "SUBJ: Lufthansa VERB: sue OBJ: Bush visit\n", + "Stormy year for property insurers\n", + "SUBJ: Stormy year property insurers VERB: None OBJ: None\n", + "G7 backs Africa debt relief plan\n", + "SUBJ: G7 VERB: backs OBJ: Africa debt relief plan\n", + "Boeing unveils new 777 aircraft\n", + "SUBJ: Boeing VERB: unveils OBJ: aircraft\n", + "Steady job growth continues in US\n", + "SUBJ: job growth VERB: continues OBJ: \n", + "China suspends 26 power projects\n", + "SUBJ: China VERB: suspends OBJ: power projects\n", + "UK firm faces Venezuelan land row\n", + "SUBJ: UK firm VERB: faces OBJ: land row\n", + "J&J agrees $25bn Guidant deal\n", + "SUBJ: J J VERB: agrees OBJ: Guidant deal\n", + "S Korean consumers spending again\n", + "SUBJ: VERB: None OBJ: None\n", + "Industrial revival hope for Japan\n", + "SUBJ: revival hope Japan VERB: None OBJ: None\n", + "UK young top Euro earnings league\n", + "SUBJ: UK top Euro earnings league VERB: None OBJ: None\n", + "Dollar hits new low versus euro\n", + "SUBJ: Dollar VERB: hits OBJ: versus euro\n", + "Turkey knocks six zeros off lira\n", + "SUBJ: Turkey VERB: knocks OBJ: zeros lira\n", + "House prices drop as sales slow\n", + "SUBJ: House prices VERB: drop OBJ: sales\n", + "Pension hitch for long-living men\n", + "SUBJ: Pension hitch living men VERB: None OBJ: None\n", + "Ban on forced retirement under 65\n", + "SUBJ: Ban retirement VERB: None OBJ: None\n", + "UK Coal plunges into deeper loss\n", + "SUBJ: UK Coal VERB: plunges OBJ: loss\n", + "US Airways staff agree to pay cut\n", + "SUBJ: Airways staff cut VERB: agree OBJ: cut\n", + "US firm pulls out of Iraq\n", + "SUBJ: VERB: firm OBJ: Iraq\n", + "Card fraudsters 'targeting web'\n", + "SUBJ: Card fraudsters targeting web VERB: None OBJ: None\n", + "Putin backs state grab for Yukos\n", + "SUBJ: Putin VERB: backs OBJ: state grab Yukos\n", + "Iraq to invite phone licence bids\n", + "SUBJ: Iraq phone licence bids VERB: invite OBJ: phone licence bids\n", + "Go-ahead for Balkan oil pipeline\n", + "SUBJ: oil pipeline VERB: Go OBJ: oil pipeline\n", + "Mixed Christmas for US retailers\n", + "SUBJ: Christmas US retailers VERB: None OBJ: None\n", + "Irish duo could block Man Utd bid\n", + "SUBJ: duo VERB: block OBJ: Man Utd bid\n", + "Nortel in $300m profit revision\n", + "SUBJ: Nortel profit revision VERB: None OBJ: None\n", + "China now top trader with Japan\n", + "SUBJ: China trader Japan VERB: None OBJ: None\n", + "Hyundai to build new India plant\n", + "SUBJ: Hyundai India plant VERB: build OBJ: India plant\n", + "House prices suffer festive fall\n", + "SUBJ: House prices VERB: suffer OBJ: fall\n", + "Yukos bankruptcy 'not US matter'\n", + "SUBJ: Yukos bankruptcy VERB: None OBJ: None\n", + "Millions go missing at China bank\n", + "SUBJ: Millions VERB: go OBJ: China bank\n", + "Markets fall on weak dollar fears\n", + "SUBJ: Markets VERB: fall OBJ: dollar fears\n", + "German bidder in talks with LSE\n", + "SUBJ: bidder talks LSE VERB: None OBJ: None\n", + "Khodorkovsky quits Yukos shares\n", + "SUBJ: Khodorkovsky VERB: quits OBJ: Yukos shares\n", + "AstraZeneca hit by drug failure\n", + "SUBJ: AstraZeneca drug failure VERB: hit OBJ: drug failure\n", + "BT offers equal access to rivals\n", + "SUBJ: BT VERB: offers OBJ: access rivals\n", + "US consumer confidence up\n", + "SUBJ: VERB: consumer OBJ: confidence\n", + "BA to suspend two Saudi services\n", + "SUBJ: BA Saudi services VERB: suspend OBJ: Saudi services\n", + "Honda wins China copyright ruling\n", + "SUBJ: Honda VERB: wins OBJ: China copyright ruling\n", + "Ebbers denies WorldCom fraud\n", + "SUBJ: Ebbers VERB: denies OBJ: WorldCom fraud\n", + "Parmalat sues 45 banks over crash\n", + "SUBJ: Parmalat VERB: sues OBJ: banks\n", + "Yukos accused of lying to court\n", + "SUBJ: Yukos VERB: accused OBJ: court\n", + "Making your office work for you\n", + "SUBJ: office work VERB: Making OBJ: office work\n", + "Economy 'strong' in election year\n", + "SUBJ: Economy election year VERB: None OBJ: None\n", + "Survey confirms property slowdown\n", + "SUBJ: Survey VERB: confirms OBJ: property slowdown\n", + "The 'ticking budget' facing the US\n", + "SUBJ: ticking budget VERB: facing OBJ: \n", + "Ukraine strikes Turkmen gas deal\n", + "SUBJ: Ukraine VERB: strikes OBJ: Turkmen gas deal\n", + "Mitsubishi in Peugeot link talks\n", + "SUBJ: Mitsubishi Peugeot link talks VERB: None OBJ: None\n", + "Golden rule 'intact' says ex-aide\n", + "SUBJ: Golden rule aide VERB: says OBJ: aide\n", + "Irish company hit by Iraqi report\n", + "SUBJ: company Iraqi report VERB: hit OBJ: Iraqi report\n", + "Fiat chief takes steering wheel\n", + "SUBJ: Fiat chief VERB: takes OBJ: steering wheel\n", + "Bat spit drug firm goes to market\n", + "SUBJ: Bat spit drug firm VERB: goes OBJ: market\n", + "Sales 'fail to boost High Street'\n", + "SUBJ: Sales fail High Street VERB: boost OBJ: High Street\n", + "Indy buys into India paper\n", + "SUBJ: buys India paper VERB: None OBJ: None\n", + "Industrial output falls in Japan\n", + "SUBJ: output VERB: falls OBJ: Japan\n", + "VW considers opening Indian plant\n", + "SUBJ: VW VERB: considers OBJ: plant\n", + "US retail sales surge in December\n", + "SUBJ: sales surge December VERB: None OBJ: None\n", + "LSE 'sets date for takeover deal'\n", + "SUBJ: LSE sets date takeover deal VERB: None OBJ: None\n", + "Glazer makes new Man Utd approach\n", + "SUBJ: Glazer VERB: makes OBJ: Man Utd approach\n", + "French suitor holds LSE meeting\n", + "SUBJ: suitor VERB: holds OBJ: LSE meeting\n", + "Booming markets shed few tears\n", + "SUBJ: markets tears VERB: Booming OBJ: markets tears\n", + "McDonald's boss Bell dies aged 44\n", + "SUBJ: McDonald boss Bell VERB: dies OBJ: \n", + "Wall Street cheers Bush victory\n", + "SUBJ: Wall Street cheers Bush victory VERB: None OBJ: None\n", + "US Ahold suppliers face charges\n", + "SUBJ: Ahold suppliers charges VERB: face OBJ: charges\n", + "Italy to get economic action plan\n", + "SUBJ: Italy VERB: get OBJ: action plan\n", + "India calls for fair trade rules\n", + "SUBJ: India VERB: calls OBJ: trade rules\n", + "US trade gap hits record in 2004\n", + "SUBJ: VERB: trade OBJ: gap hits record\n", + "Britannia members' £42m windfall\n", + "SUBJ: Britannia members £ windfall VERB: None OBJ: None\n", + "Manufacturing recovery 'slowing'\n", + "SUBJ: recovery VERB: Manufacturing OBJ: recovery\n", + "Asia shares defy post-quake gloom\n", + "SUBJ: Asia shares VERB: defy OBJ: quake gloom\n", + "Weak dollar hits Reuters\n", + "SUBJ: dollar hits Reuters VERB: None OBJ: None\n", + "Cannabis hopes for drug firm\n", + "SUBJ: Cannabis VERB: hopes OBJ: drug firm\n", + "India's rupee hits five-year high\n", + "SUBJ: India rupee VERB: hits OBJ: year\n", + "Yangtze Electric's profits double\n", + "SUBJ: Yangtze Electric profits VERB: None OBJ: None\n", + "Dollar drops on reserves concerns\n", + "SUBJ: Dollar drops reserves concerns VERB: None OBJ: None\n", + "Worldcom ex-boss launches defence\n", + "SUBJ: Worldcom boss launches defence VERB: None OBJ: None\n", + "Google shares fall as staff sell\n", + "SUBJ: Google shares VERB: fall OBJ: staff sell\n", + "Absa and Barclays talks continue\n", + "SUBJ: Absa Barclays talks VERB: continue OBJ: None\n", + "US regulator to rule on pain drug\n", + "SUBJ: VERB: regulator OBJ: pain drug\n", + "Hariri killing hits Beirut shares\n", + "SUBJ: Hariri hits Beirut shares VERB: killing OBJ: hits Beirut shares\n", + "Jobs growth still slow in the US\n", + "SUBJ: Jobs growth VERB: None OBJ: \n", + "S Korea spending boost to economy\n", + "SUBJ: S Korea spending boost economy VERB: None OBJ: None\n", + "Marsh executive in guilty plea\n", + "SUBJ: Marsh executive plea VERB: None OBJ: None\n", + "India seeks to boost construction\n", + "SUBJ: India VERB: seeks OBJ: construction\n", + "Tokyo says deflation 'controlled'\n", + "SUBJ: Tokyo VERB: says OBJ: deflation\n", + "Stock market eyes Japan recovery\n", + "SUBJ: Stock market eyes Japan recovery VERB: None OBJ: None\n", + "MCI shares climb on takeover bid\n", + "SUBJ: MCI shares VERB: climb OBJ: takeover bid\n", + "UK homes hit £3.3 trillion total\n", + "SUBJ: UK homes VERB: hit OBJ: £\n", + "US adds more jobs than expected\n", + "SUBJ: VERB: adds OBJ: jobs\n", + "Buyers snap up Jet Airways' shares\n", + "SUBJ: Buyers VERB: snap OBJ: Jet Airways shares\n", + "Electrolux to export Europe jobs\n", + "SUBJ: Electrolux Europe jobs VERB: export OBJ: Europe jobs\n", + "Crude oil prices back above $50\n", + "SUBJ: oil prices VERB: None OBJ: None\n", + "Madagascar completes currency switch\n", + "SUBJ: Madagascar VERB: completes OBJ: currency switch\n", + "Tsunami 'to hit Sri Lanka banks'\n", + "SUBJ: Tsunami Sri Lanka banks VERB: hit OBJ: Sri Lanka banks\n", + "India and Iran in gas export deal\n", + "SUBJ: India Iran gas export deal VERB: None OBJ: None\n", + "Rank 'set to sell off film unit'\n", + "SUBJ: Rank set film unit VERB: sell OBJ: film unit\n", + "Iraqi voters turn to economic issues\n", + "SUBJ: voters VERB: turn OBJ: issues\n", + "Fed warns of more US rate rises\n", + "SUBJ: Fed VERB: warns OBJ: rate rises\n", + "Standard Life concern at LSE bid\n", + "SUBJ: Standard Life concern LSE bid VERB: None OBJ: None\n", + "Ukraine trims privatisation check\n", + "SUBJ: Ukraine VERB: trims OBJ: privatisation check\n", + "US data sparks inflation worries\n", + "SUBJ: VERB: sparks OBJ: inflation worries\n", + "Optimism remains over UK housing\n", + "SUBJ: Optimism VERB: remains OBJ: UK housing\n", + "UK 'risks breaking golden rule'\n", + "SUBJ: UK risks rule VERB: breaking OBJ: rule\n", + "Call centre users 'lose patience'\n", + "SUBJ: Call centre users lose patience VERB: None OBJ: None\n", + "'Strong dollar' call halts slide\n", + "SUBJ: dollar call halts VERB: slide OBJ: None\n", + "Criminal probe on Citigroup deals\n", + "SUBJ: probe Citigroup deals VERB: None OBJ: None\n", + "EU aiming to fuel development aid\n", + "SUBJ: EU VERB: aiming OBJ: development aid\n", + "Why few targets are better than many\n", + "SUBJ: targets VERB: are OBJ: \n", + "Chinese dam firm 'defies Beijing'\n", + "SUBJ: dam firm defies Beijing VERB: None OBJ: None\n", + "Beijingers fume over parking fees\n", + "SUBJ: Beijingers VERB: fume OBJ: parking fees\n", + "EU-US seeking deal on air dispute\n", + "SUBJ: EU VERB: seeking OBJ: deal air dispute\n", + "WMC profits up amid bid criticism\n", + "SUBJ: WMC VERB: profits OBJ: bid criticism\n", + "DaimlerChrysler's 2004 sales rise\n", + "SUBJ: DaimlerChrysler sales rise VERB: None OBJ: None\n", + "Weak data buffets French economy\n", + "SUBJ: Weak data buffets economy VERB: None OBJ: None\n", + "Rover deal 'may cost 2,000 jobs'\n", + "SUBJ: Rover deal jobs VERB: cost OBJ: jobs\n", + "Split-caps pay £194m compensation\n", + "SUBJ: Split caps compensation VERB: pay OBJ: compensation\n", + "Cairn Energy in Indian gas find\n", + "SUBJ: Cairn Energy Indian gas find VERB: None OBJ: None\n", + "Kraft cuts snack ads for children\n", + "SUBJ: Kraft VERB: cuts OBJ: snack ads\n", + "EU to probe Alitalia 'state aid'\n", + "SUBJ: EU Alitalia state aid VERB: probe OBJ: Alitalia state aid\n", + "Oil prices reach three-month low\n", + "SUBJ: Oil prices VERB: reach OBJ: month\n", + "Minister hits out at Yukos sale\n", + "SUBJ: Minister VERB: hits OBJ: Yukos sale\n", + "Continental 'may run out of cash'\n", + "SUBJ: Continental VERB: run OBJ: cash\n", + "BMW drives record sales in Asia\n", + "SUBJ: BMW VERB: drives OBJ: record sales Asia\n", + "ID theft surge hits US consumers\n", + "SUBJ: theft surge VERB: hits OBJ: consumers\n", + "Pernod takeover talk lifts Domecq\n", + "SUBJ: Pernod takeover talk VERB: lifts OBJ: Domecq\n", + "Wal-Mart fights back at accusers\n", + "SUBJ: Wal Mart accusers VERB: fights OBJ: accusers\n", + "Saab to build Cadillacs in Sweden\n", + "SUBJ: Saab VERB: build OBJ: Cadillacs\n", + "Police detain Chinese milk bosses\n", + "SUBJ: Police detain milk bosses VERB: None OBJ: None\n", + "Libya takes $1bn in unfrozen funds\n", + "SUBJ: Libya VERB: takes OBJ: \n", + "Singapore growth at 8.1% in 2004\n", + "SUBJ: Singapore growth % VERB: None OBJ: None\n", + "Yukos unit buyer faces loan claim\n", + "SUBJ: Yukos unit buyer VERB: faces OBJ: loan claim\n", + "India opens skies to competition\n", + "SUBJ: India VERB: opens OBJ: skies competition\n", + "LSE doubts boost bidders' shares\n", + "SUBJ: LSE doubts VERB: boost OBJ: bidders shares\n", + "Profits stall at China's Lenovo\n", + "SUBJ: Profits VERB: stall OBJ: China Lenovo\n", + "Profits slide at India's Dr Reddy\n", + "SUBJ: Profits VERB: slide OBJ: India Dr Reddy\n", + "Newest EU members underpin growth\n", + "SUBJ: Newest EU members VERB: underpin OBJ: growth\n", + "S Korean lender faces liquidation\n", + "SUBJ: lender liquidation VERB: faces OBJ: liquidation\n", + "GM, Ford cut output as sales fall\n", + "SUBJ: GM Ford VERB: cut OBJ: output\n", + "Giving financial gifts to children\n", + "SUBJ: gifts VERB: Giving OBJ: gifts\n", + "US bank 'loses' customer details\n", + "SUBJ: bank customer details VERB: None OBJ: None\n", + "Fiat mulls Ferrari market listing\n", + "SUBJ: Fiat VERB: mulls OBJ: Ferrari market\n", + "Lloyd's of London head chides FSA\n", + "SUBJ: Lloyd London head chides FSA VERB: None OBJ: None\n", + "Qwest may spark MCI bidding war\n", + "SUBJ: Qwest VERB: spark OBJ: MCI bidding war\n", + "EC calls truce in deficit battle\n", + "SUBJ: EC VERB: calls OBJ: truce deficit battle\n", + "Umbro profits lifted by Euro 2004\n", + "SUBJ: Umbro profits Euro VERB: lifted OBJ: Euro\n", + "US crude prices surge above $53\n", + "SUBJ: VERB: crude OBJ: prices\n", + "China keeps tight rein on credit\n", + "SUBJ: China VERB: keeps OBJ: rein\n", + "Mixed reaction to Man Utd offer\n", + "SUBJ: reaction Man Utd offer VERB: None OBJ: None\n", + "Soaring oil 'hits world economy'\n", + "SUBJ: oil VERB: Soaring OBJ: oil\n", + "India's Deccan seals $1.8bn deal\n", + "SUBJ: India Deccan VERB: seals OBJ: deal\n", + "Japan bank shares up on link talk\n", + "SUBJ: Japan bank shares link talk VERB: None OBJ: None\n", + "Laura Ashley chief stepping down\n", + "SUBJ: Laura Ashley chief VERB: stepping OBJ: None\n", + "Chinese wine tempts Italy's Illva\n", + "SUBJ: wine VERB: tempts OBJ: Italy Illva\n", + "Macy's owner buys rival for $11bn\n", + "SUBJ: Macy owner VERB: buys OBJ: \n", + "Japanese banking battle at an end\n", + "SUBJ: banking battle end VERB: None OBJ: None\n", + "GM issues 2005 profits warning\n", + "SUBJ: GM issues profits VERB: None OBJ: None\n", + "Warning over US pensions deficit\n", + "SUBJ: pensions VERB: Warning OBJ: pensions\n", + "Russia gets investment blessing\n", + "SUBJ: Russia VERB: gets OBJ: investment blessing\n", + "Brazil jobless rate hits new low\n", + "SUBJ: Brazil rate VERB: hits OBJ: None\n", + "Small firms 'hit by rising costs'\n", + "SUBJ: firms costs VERB: hit OBJ: costs\n", + "Alfa Romeos 'to get GM engines'\n", + "SUBJ: Alfa Romeos GM engines VERB: get OBJ: GM engines\n", + "BP surges ahead on high oil price\n", + "SUBJ: BP VERB: surges OBJ: oil price\n", + "McDonald's to sponsor MTV show\n", + "SUBJ: McDonald MTV VERB: sponsor OBJ: MTV\n", + "Worldcom boss 'left books alone'\n", + "SUBJ: Worldcom boss VERB: left OBJ: books\n", + "Egypt to sell off state-owned bank\n", + "SUBJ: Egypt state bank VERB: sell OBJ: state\n", + "Insurance bosses plead guilty\n", + "SUBJ: Insurance bosses VERB: plead OBJ: None\n", + "Cactus diet deal for Phytopharm\n", + "SUBJ: Cactus diet deal Phytopharm VERB: None OBJ: None\n", + "Strong quarterly growth for Nike\n", + "SUBJ: growth Nike VERB: None OBJ: None\n", + "Euronext joins bid battle for LSE\n", + "SUBJ: joins VERB: bid OBJ: battle LSE\n", + "US to rule on Yukos refuge call\n", + "SUBJ: VERB: rule OBJ: Yukos refuge call\n", + "Yukos loses US bankruptcy battle\n", + "SUBJ: Yukos VERB: loses OBJ: bankruptcy battle\n", + "Battered dollar hits another low\n", + "SUBJ: dollar VERB: hits OBJ: \n", + "Yukos sues four firms for $20bn\n", + "SUBJ: Yukos VERB: sues OBJ: firms\n", + "Delta cuts fares in survival plan\n", + "SUBJ: Delta cuts fares survival plan VERB: None OBJ: None\n", + "Salary scandal in Cameroon\n", + "SUBJ: Salary scandal Cameroon VERB: None OBJ: None\n", + "Bank set to leave rates on hold\n", + "SUBJ: Bank VERB: set OBJ: rates\n", + "Sluggish economy hits German jobs\n", + "SUBJ: economy VERB: hits OBJ: jobs\n", + "Wipro beats forecasts once again\n", + "SUBJ: Wipro VERB: beats OBJ: forecasts\n", + "SA unveils 'more for all' budget\n", + "SUBJ: SA unveils VERB: None OBJ: None\n", + "Renault boss hails 'great year'\n", + "SUBJ: Renault boss year VERB: None OBJ: None\n", + "Mild winter drives US oil down 6%\n", + "SUBJ: Mild winter drives % VERB: oil OBJ: %\n", + "Egypt and Israel seal trade deal\n", + "SUBJ: Egypt Israel seal trade deal VERB: None OBJ: None\n", + "Iraq and Afghanistan in WTO talks\n", + "SUBJ: Iraq Afghanistan WTO talks VERB: None OBJ: None\n", + "China had role in Yukos split-up\n", + "SUBJ: China VERB: had OBJ: role Yukos split\n", + "Venezuela identifies 'idle' farms\n", + "SUBJ: Venezuela farms VERB: None OBJ: None\n", + "Bush budget seeks deep cutbacks\n", + "SUBJ: Bush budget VERB: seeks OBJ: cutbacks\n", + "French wine gets 70m euro top-up\n", + "SUBJ: wine VERB: gets OBJ: euro top\n", + "Ryanair in $4bn Boeing plane deal\n", + "SUBJ: Ryanair Boeing plane deal VERB: None OBJ: None\n", + "Japan turns to beer alternatives\n", + "SUBJ: Japan VERB: turns OBJ: beer alternatives\n", + "MCI shareholder sues to stop bid\n", + "SUBJ: MCI shareholder VERB: sues OBJ: bid\n", + "Novartis hits acquisition trail\n", + "SUBJ: Novartis VERB: hits OBJ: acquisition trail\n", + "SEC to rethink post-Enron rules\n", + "SUBJ: SEC VERB: rethink OBJ: post\n", + "BBC poll indicates economic gloom\n", + "SUBJ: BBC poll VERB: indicates OBJ: gloom\n", + "WMC says Xstrata bid is too low\n", + "SUBJ: WMC VERB: says OBJ: Xstrata bid\n", + "Japanese mogul arrested for fraud\n", + "SUBJ: mogul VERB: arrested OBJ: fraud\n", + "Fannie Mae 'should restate books'\n", + "SUBJ: Fannie Mae VERB: restate OBJ: books\n", + "US trade gap ballooned in October\n", + "SUBJ: VERB: trade OBJ: gap October\n", + "Nasdaq planning $100m-share sale\n", + "SUBJ: Nasdaq share sale VERB: planning OBJ: \n", + "Oil prices fall back from highs\n", + "SUBJ: Oil prices VERB: fall OBJ: highs\n", + "French consumer spending rising\n", + "SUBJ: consumer spending VERB: rising OBJ: None\n", + "Saudi ministry to employ women\n", + "SUBJ: Saudi ministry women VERB: employ OBJ: women\n", + "Telegraph newspapers axe 90 jobs\n", + "SUBJ: Telegraph newspapers VERB: axe OBJ: jobs\n", + "UK interest rates held at 4.75%\n", + "SUBJ: interest rates VERB: held OBJ: %\n", + "US budget deficit to reach $368bn\n", + "SUBJ: VERB: budget OBJ: deficit\n", + "UK house prices dip in November\n", + "SUBJ: UK house prices VERB: dip OBJ: November\n", + "Verizon 'seals takeover of MCI'\n", + "SUBJ: Verizon seals takeover MCI VERB: None OBJ: None\n", + "Cars pull down US retail figures\n", + "SUBJ: Cars VERB: pull OBJ: figures\n", + "Christmas sales worst since 1981\n", + "SUBJ: Christmas sales VERB: None OBJ: None\n", + "Orange colour clash set for court\n", + "SUBJ: Orange colour clash court VERB: set OBJ: court\n", + "Steady job growth continues in US\n", + "SUBJ: job growth VERB: continues OBJ: \n", + "Fresh hope after Argentine crisis\n", + "SUBJ: hope crisis VERB: None OBJ: None\n", + "France Telecom gets Orange boost\n", + "SUBJ: France Telecom VERB: gets OBJ: Orange boost\n", + "Tate & Lyle boss bags top award\n", + "SUBJ: Tate Lyle boss bags award VERB: None OBJ: None\n", + "GSK aims to stop Aids profiteers\n", + "SUBJ: GSK VERB: aims OBJ: Aids profiteers\n", + "GM in crunch talks on Fiat future\n", + "SUBJ: GM crunch talks Fiat future VERB: None OBJ: None\n", + "News Corp eyes video games market\n", + "SUBJ: News Corp eyes VERB: video OBJ: games market\n", + "Market unfazed by Aurora setback\n", + "SUBJ: Market Aurora setback VERB: None OBJ: None\n", + "US gives foreign firms extra time\n", + "SUBJ: VERB: gives OBJ: firms\n", + "US economy shows solid GDP growth\n", + "SUBJ: economy GDP growth VERB: shows OBJ: GDP growth\n", + "India power shares jump on debut\n", + "SUBJ: India power shares VERB: jump OBJ: debut\n", + "Liberian economy starts to grow\n", + "SUBJ: economy VERB: starts OBJ: None\n", + "Tobacco giants hail court ruling\n", + "SUBJ: Tobacco giants VERB: hail OBJ: court ruling\n", + "Bad weather hits Nestle sales\n", + "SUBJ: weather VERB: hits OBJ: Nestle sales\n", + "EU ministers to mull jet fuel tax\n", + "SUBJ: EU ministers jet fuel tax VERB: mull OBJ: jet fuel tax\n", + "Indian oil firm eyes Yukos assets\n", + "SUBJ: oil firm VERB: eyes OBJ: Yukos assets\n", + "Consumers drive French economy\n", + "SUBJ: Consumers VERB: drive OBJ: economy\n", + "Troubled Marsh under SEC scrutiny\n", + "SUBJ: Marsh SEC scrutiny VERB: None OBJ: None\n", + "Bank holds interest rate at 4.75%\n", + "SUBJ: Bank VERB: holds OBJ: interest rate\n", + "Qantas considers offshore option\n", + "SUBJ: Qantas VERB: considers OBJ: offshore option\n", + "Steel firm 'to cut' 45,000 jobs\n", + "SUBJ: Steel firm jobs VERB: None OBJ: None\n", + "Borussia Dortmund near bust\n", + "SUBJ: Borussia Dortmund bust VERB: None OBJ: None\n", + "Economy 'strong' in election year\n", + "SUBJ: Economy election year VERB: None OBJ: None\n", + "China bans new tobacco factories\n", + "SUBJ: China VERB: bans OBJ: tobacco factories\n", + "India and Russia in energy talks\n", + "SUBJ: India Russia energy talks VERB: None OBJ: None\n", + "Arsenal 'may seek full share listing'\n", + "SUBJ: Arsenal VERB: seek OBJ: share listing\n", + "German jobless rate at new record\n", + "SUBJ: rate record VERB: None OBJ: None\n", + "US company admits Benin bribery\n", + "SUBJ: company Benin bribery VERB: admits OBJ: Benin bribery\n", + "Ailing EuroDisney vows turnaround\n", + "SUBJ: EuroDisney vows turnaround VERB: Ailing OBJ: EuroDisney vows turnaround\n", + "Record year for Chilean copper\n", + "SUBJ: Record year Chilean copper VERB: None OBJ: None\n", + "UK economy ends year with spurt\n", + "SUBJ: UK economy VERB: ends OBJ: year spurt\n", + "India-Pakistan peace boosts trade\n", + "SUBJ: India Pakistan peace boosts VERB: None OBJ: None\n", + "High fuel costs hit US airlines\n", + "SUBJ: fuel costs VERB: hit OBJ: \n", + "$1m payoff for former Shell boss\n", + "SUBJ: payoff Shell boss VERB: None OBJ: None\n", + "Palestinian economy in decline\n", + "SUBJ: economy decline VERB: None OBJ: None\n", + "Air China in $1bn London listing\n", + "SUBJ: Air China London listing VERB: None OBJ: None\n", + "Air Jamaica back in state control\n", + "SUBJ: Air Jamaica state control VERB: None OBJ: None\n", + "German growth goes into reverse\n", + "SUBJ: growth VERB: goes OBJ: reverse\n", + "Yukos owner sues Russia for $28bn\n", + "SUBJ: Yukos VERB: owner OBJ: sues Russia\n", + "Weak dollar trims Cadbury profits\n", + "SUBJ: dollar trims Cadbury profits VERB: None OBJ: None\n", + "'Post-Christmas lull' in lending\n", + "SUBJ: Post Christmas lull lending VERB: None OBJ: Post Christmas lull lending\n", + "Barclays shares up on merger talk\n", + "SUBJ: Barclays shares merger talk VERB: None OBJ: None\n", + "Soros group warns of Kazakh close\n", + "SUBJ: Soros group VERB: warns OBJ: Kazakh\n", + "Dollar hovers around record lows\n", + "SUBJ: Dollar hovers record lows VERB: None OBJ: None\n", + "WorldCom trial starts in New York\n", + "SUBJ: WorldCom trial VERB: starts OBJ: New York\n", + "Singapore growth at 8.1% in 2004\n", + "SUBJ: Singapore growth % VERB: None OBJ: None\n", + "US interest rate rise expected\n", + "SUBJ: VERB: rise OBJ: None\n", + "Ex-Boeing director gets jail term\n", + "SUBJ: Ex Boeing director jail term VERB: gets OBJ: jail term\n", + "Glaxo aims high after profit fall\n", + "SUBJ: Glaxo VERB: aims OBJ: profit fall\n", + "Vodafone appoints new Japan boss\n", + "SUBJ: Vodafone VERB: appoints OBJ: Japan boss\n", + "WorldCom bosses' $54m payout\n", + "SUBJ: WorldCom VERB: None OBJ: None\n", + "Ebbers 'aware' of WorldCom fraud\n", + "SUBJ: Ebbers WorldCom fraud VERB: None OBJ: None\n", + "Wall Street cool to eBay's profit\n", + "SUBJ: Wall Street VERB: cool OBJ: eBay profit\n", + "Could Yukos be a blessing in disguise?\n", + "SUBJ: Yukos VERB: be OBJ: blessing disguise\n", + "Budget Aston takes on Porsche\n", + "SUBJ: Budget Aston VERB: takes OBJ: Porsche\n", + "Cash gives way to flexible friend\n", + "SUBJ: Cash VERB: gives OBJ: way\n", + "Asia quake increases poverty risk\n", + "SUBJ: Asia quake increases poverty risk VERB: None OBJ: None\n", + "Parmalat boasts doubled profits\n", + "SUBJ: Parmalat VERB: boasts OBJ: profits\n", + "Burren awarded Egyptian contracts\n", + "SUBJ: Burren VERB: awarded OBJ: contracts\n", + "Germany calls for EU reform\n", + "SUBJ: Germany VERB: calls OBJ: EU reform\n", + "Asia shares defy post-quake gloom\n", + "SUBJ: Asia shares VERB: defy OBJ: quake gloom\n", + "EMI shares hit by profit warning\n", + "SUBJ: EMI shares profit warning VERB: hit OBJ: profit warning\n", + "Takeover offer for Sunderland FC\n", + "SUBJ: Takeover offer Sunderland FC VERB: None OBJ: None\n", + "Banker loses sexism claim\n", + "SUBJ: Banker VERB: loses OBJ: sexism claim\n", + "News Corp makes $5.4bn Fox offer\n", + "SUBJ: News Corp VERB: makes OBJ: Fox offer\n", + "India's Maruti sees profits jump\n", + "SUBJ: India Maruti VERB: sees OBJ: profits\n", + "Fosters buys stake in winemaker\n", + "SUBJ: Fosters VERB: buys OBJ: stake winemaker\n", + "Nasdaq planning $100m share sale\n", + "SUBJ: Nasdaq share sale VERB: planning OBJ: share sale\n", + "World leaders gather to face uncertainty\n", + "SUBJ: World leaders VERB: gather OBJ: uncertainty\n", + "Ore costs hit global steel firms\n", + "SUBJ: Ore VERB: costs OBJ: steel firms\n", + "Golden rule boost for Chancellor\n", + "SUBJ: Golden rule boost Chancellor VERB: None OBJ: None\n", + "Swiss cement firm in buying spree\n", + "SUBJ: cement firm spree VERB: buying OBJ: spree\n", + "Qantas sees profits fly to record\n", + "SUBJ: Qantas VERB: sees OBJ: profits\n", + "House prices rebound says Halifax\n", + "SUBJ: House prices VERB: rebound OBJ: Halifax\n", + "Circuit City gets takeover offer\n", + "SUBJ: Circuit City VERB: gets OBJ: takeover offer\n", + "Trade gap narrows as exports rise\n", + "SUBJ: Trade gap VERB: narrows OBJ: exports\n", + "Turkey turns on the economic charm\n", + "SUBJ: Turkey VERB: turns OBJ: charm\n", + "Qatar and Shell in $6bn gas deal\n", + "SUBJ: Qatar Shell gas deal VERB: None OBJ: None\n", + "Worldcom director ends evidence\n", + "SUBJ: Worldcom director VERB: ends OBJ: evidence\n", + "Disney settles disclosure charges\n", + "SUBJ: Disney VERB: settles OBJ: disclosure charges\n", + "S Korean credit card firm rescued\n", + "SUBJ: credit card firm VERB: rescued OBJ: None\n", + "Consumer spending lifts US growth\n", + "SUBJ: Consumer spending VERB: lifts OBJ: \n", + "Argentina closes $102.6bn debt swap\n", + "SUBJ: Argentina VERB: closes OBJ: debt swap\n", + "Building giant in asbestos payout\n", + "SUBJ: giant VERB: Building OBJ: giant\n", + "US seeks new $280bn smoker ruling\n", + "SUBJ: VERB: seeks OBJ: smoker ruling\n", + "Gaming firm to sell UK dog tracks\n", + "SUBJ: firm UK dog tracks VERB: Gaming OBJ: firm UK dog tracks\n", + "FAO warns on impact of subsidies\n", + "SUBJ: FAO VERB: warns OBJ: impact subsidies\n", + "Beer giant swallows Russian firm\n", + "SUBJ: Beer giant VERB: swallows OBJ: firm\n", + "Further rise in UK jobless total\n", + "SUBJ: rise UK total VERB: None OBJ: None\n", + "Japan narrowly escapes recession\n", + "SUBJ: Japan VERB: escapes OBJ: recession\n", + "Low-cost airlines hit Eurotunnel\n", + "SUBJ: cost airlines VERB: hit OBJ: Eurotunnel\n", + "UK economy facing 'major risks'\n", + "SUBJ: UK economy risks VERB: None OBJ: None\n", + "Barclays profits hit record level\n", + "SUBJ: Barclays profits VERB: hit OBJ: record level\n", + "MG Rover China tie-up 'delayed'\n", + "SUBJ: MG Rover China tie VERB: None OBJ: None\n", + "Asian quake hits European shares\n", + "SUBJ: quake VERB: hits OBJ: shares\n", + "SBC plans post-takeover job cuts\n", + "SUBJ: SBC VERB: plans OBJ: post takeover job cuts\n", + "Safety alert as GM recalls cars\n", + "SUBJ: Safety GM cars VERB: recalls OBJ: cars\n", + "Two Nigerian banks set to merge\n", + "SUBJ: banks VERB: set OBJ: None\n", + "India unveils anti-poverty budget\n", + "SUBJ: India VERB: unveils OBJ: poverty budget\n", + "Jarvis sells Tube stake to Spain\n", + "SUBJ: Jarvis VERB: sells OBJ: Tube stake\n", + "UK bank seals South Korean deal\n", + "SUBJ: UK bank seals deal VERB: None OBJ: None\n", + "US bank in $515m SEC settlement\n", + "SUBJ: VERB: None OBJ: \n", + "Boeing secures giant Japan order\n", + "SUBJ: Boeing secures Japan order VERB: None OBJ: None\n", + "US trade deficit widens sharply\n", + "SUBJ: VERB: trade OBJ: deficit\n", + "Lufthansa flies back to profit\n", + "SUBJ: Lufthansa VERB: flies OBJ: profit\n", + "HealthSouth ex-boss goes on trial\n", + "SUBJ: HealthSouth VERB: goes OBJ: boss trial\n", + "South African car demand surges\n", + "SUBJ: car demand VERB: surges OBJ: None\n", + "Share boost for feud-hit Reliance\n", + "SUBJ: Share boost feud hit Reliance VERB: None OBJ: None\n", + "GM pays $2bn to evade Fiat buyout\n", + "SUBJ: GM VERB: pays OBJ: \n", + "Nissan names successor to Ghosn\n", + "SUBJ: Nissan names successor Ghosn VERB: None OBJ: None\n", + "S&N extends Indian beer venture\n", + "SUBJ: S N VERB: extends OBJ: beer venture\n", + "Israeli economy picking up pace\n", + "SUBJ: economy VERB: picking OBJ: pace\n", + "Ukraine steel sell-off 'illegal'\n", + "SUBJ: Ukraine steel VERB: sell OBJ: \n", + "Dutch bank to lay off 2,850 staff\n", + "SUBJ: bank staff VERB: lay OBJ: staff\n", + "Ad firm WPP's profits surge 15%\n", + "SUBJ: Ad firm WPP profits VERB: surge OBJ: %\n", + "Algeria hit by further gas riots\n", + "SUBJ: Algeria gas riots VERB: hit OBJ: gas riots\n", + "US in EU tariff chaos trade row\n", + "SUBJ: EU tariff chaos trade row VERB: None OBJ: None\n", + "Crossrail link 'to get go-ahead'\n", + "SUBJ: Crossrail link VERB: get OBJ: None\n", + "Israel looks to US for bank chief\n", + "SUBJ: Israel VERB: looks OBJ: bank chief\n", + "Rescue hope for Borussia Dortmund\n", + "SUBJ: Rescue hope Borussia Dortmund VERB: None OBJ: None\n", + "Shares hit by MS drug suspension\n", + "SUBJ: Shares MS drug suspension VERB: hit OBJ: MS drug suspension\n", + "S Korea spending boost to economy\n", + "SUBJ: S Korea spending boost economy VERB: None OBJ: None\n", + "Australia rates at four year high\n", + "SUBJ: Australia VERB: rates OBJ: year\n", + "China continues breakneck growth\n", + "SUBJ: China VERB: continues OBJ: breakneck growth\n", + "Iran budget seeks state sell-offs\n", + "SUBJ: Iran budget VERB: seeks OBJ: offs\n", + "Deutsche Boerse boosts dividend\n", + "SUBJ: Deutsche Boerse VERB: boosts OBJ: dividend\n", + "IMF agrees fresh Turkey funding\n", + "SUBJ: IMF VERB: agrees OBJ: Turkey funding\n", + "Rich grab half Colombia poor fund\n", + "SUBJ: grab half Colombia fund VERB: None OBJ: None\n", + "Tsunami to cost Sri Lanka $1.3bn\n", + "SUBJ: Tsunami VERB: cost OBJ: Sri Lanka\n", + "Diageo to buy US wine firm\n", + "SUBJ: Diageo wine firm VERB: buy OBJ: wine firm\n", + "European losses hit GM's profits\n", + "SUBJ: losses VERB: hit OBJ: GM profits\n", + "Water firm Suez in Argentina row\n", + "SUBJ: Water firm Suez Argentina row VERB: None OBJ: None\n", + "Gold falls on IMF sale concerns\n", + "SUBJ: Gold VERB: falls OBJ: IMF sale concerns\n", + "Venezuela and China sign oil deal\n", + "SUBJ: Venezuela China sign oil deal VERB: None OBJ: None\n", + "Dollar gains on Greenspan speech\n", + "SUBJ: Dollar gains Greenspan speech VERB: None OBJ: None\n", + "Lacroix label bought by US firm\n", + "SUBJ: Lacroix label firm VERB: bought OBJ: firm\n", + "Reliance unit loses Anil Ambani\n", + "SUBJ: Reliance unit VERB: loses OBJ: Anil Ambani\n", + "Durex maker SSL awaits firm bid\n", + "SUBJ: Durex maker SSL VERB: awaits OBJ: firm bid\n", + "Call to save manufacturing jobs\n", + "SUBJ: manufacturing jobs VERB: Call OBJ: manufacturing jobs\n", + "German economy rebounds\n", + "SUBJ: economy VERB: rebounds OBJ: None\n", + "Saudi investor picks up the Savoy\n", + "SUBJ: investor VERB: picks OBJ: Savoy\n", + "Nigeria to boost cocoa production\n", + "SUBJ: Nigeria cocoa production VERB: boost OBJ: cocoa production\n", + "Cairn shares slump on oil setback\n", + "SUBJ: Cairn shares VERB: slump OBJ: oil setback\n", + "Wal-Mart to pay $14m in gun suit\n", + "SUBJ: Wal Mart gun suit VERB: pay OBJ: gun suit\n", + "Deutsche Telekom sees mobile gain\n", + "SUBJ: Deutsche Telekom VERB: sees OBJ: gain\n", + "Gazprom 'in $36m back-tax claim'\n", + "SUBJ: Gazprom VERB: None OBJ: None\n", + "Brussels raps mobile call charges\n", + "SUBJ: Brussels VERB: raps OBJ: call charges\n", + "Man Utd to open books to Glazer\n", + "SUBJ: Man Utd books Glazer VERB: open OBJ: books\n", + "Retail sales show festive fervour\n", + "SUBJ: sales VERB: show OBJ: fervour\n", + "BMW cash to fuel Mini production\n", + "SUBJ: BMW cash Mini production VERB: fuel OBJ: Mini production\n", + "US insurer Marsh cuts 2,500 jobs\n", + "SUBJ: VERB: insurer OBJ: Marsh cuts jobs\n", + "Ford gains from finance not cars\n", + "SUBJ: Ford VERB: gains OBJ: finance\n", + "Feta cheese battle reaches court\n", + "SUBJ: Feta cheese battle VERB: reaches OBJ: court\n", + "Monsanto fined $1.5m for bribery\n", + "SUBJ: Monsanto VERB: fined OBJ: \n", + "China Aviation seeks rescue deal\n", + "SUBJ: China Aviation VERB: seeks OBJ: rescue deal\n", + "Quake's economic costs emerging\n", + "SUBJ: Quake costs VERB: emerging OBJ: None\n", + "Saudi NCCI's shares soar\n", + "SUBJ: Saudi NCCI shares VERB: soar OBJ: None\n", + "Yukos heading back to US courts\n", + "SUBJ: Yukos courts VERB: heading OBJ: courts\n", + "News Corp eyes video games market\n", + "SUBJ: News Corp eyes VERB: video OBJ: games market\n", + "Firms pump billions into pensions\n", + "SUBJ: Firms VERB: pump OBJ: billions\n", + "US firm 'bids for Lacroix label'\n", + "SUBJ: VERB: None OBJ: None\n", + "US manufacturing expands\n", + "SUBJ: VERB: manufacturing OBJ: expands\n", + "Weak end-of-year sales hit Next\n", + "SUBJ: end year sales VERB: hit OBJ: None\n", + "Business confidence dips in Japan\n", + "SUBJ: Business confidence dips Japan VERB: None OBJ: None\n", + "BMW to recall faulty diesel cars\n", + "SUBJ: BMW diesel cars VERB: recall OBJ: diesel cars\n", + "Quiksilver moves for Rossignol\n", + "SUBJ: Quiksilver VERB: moves OBJ: Rossignol\n", + "House prices show slight increase\n", + "SUBJ: House prices VERB: show OBJ: increase\n", + "Winn-Dixie files for bankruptcy\n", + "SUBJ: Winn Dixie files bankruptcy VERB: None OBJ: None\n", + "Deutsche Boerse set to 'woo' LSE\n", + "SUBJ: Deutsche Boerse VERB: set OBJ: woo LSE\n", + "Ericsson sees earnings improve\n", + "SUBJ: Ericsson VERB: sees OBJ: earnings\n", + "Aids and climate top Davos agenda\n", + "SUBJ: Aids climate Davos agenda VERB: None OBJ: None\n", + "Indonesia 'declines debt freeze'\n", + "SUBJ: Indonesia declines debt freeze VERB: None OBJ: None\n", + "Oil companies get Russian setback\n", + "SUBJ: Oil companies VERB: get OBJ: setback\n", + "Economy 'stronger than forecast'\n", + "SUBJ: Economy forecast VERB: None OBJ: None\n", + "Bush to outline 'toughest' budget\n", + "SUBJ: Bush VERB: outline OBJ: budget\n", + "Disaster claims 'less than $10bn'\n", + "SUBJ: Disaster claims VERB: None OBJ: None\n", + "Virgin Blue shares plummet 20%\n", + "SUBJ: Virgin Blue shares VERB: plummet OBJ: %\n", + "Cuba winds back economic clock\n", + "SUBJ: Cuba VERB: winds OBJ: clock\n", + "FBI agent colludes with analyst\n", + "SUBJ: FBI agent VERB: colludes OBJ: analyst\n", + "Court rejects $280bn tobacco case\n", + "SUBJ: Court VERB: rejects OBJ: tobacco case\n", + "Enron bosses in $168m payout\n", + "SUBJ: Enron VERB: bosses OBJ: \n", + "'Golden economic period' to end\n", + "SUBJ: period VERB: end OBJ: period\n", + "Call to overhaul UK state pension\n", + "SUBJ: UK state pension VERB: Call OBJ: UK state pension\n", + "Slowdown hits US factory growth\n", + "SUBJ: Slowdown VERB: hits OBJ: factory growth\n", + "Europe blames US over weak dollar\n", + "SUBJ: Europe VERB: blames OBJ: \n" + ] + } + ], + "source": [ + "for line in business:\n", + " tok.set_content(line.strip())\n", + " seq = extract_sequences(tok)[0]\n", + " \n", + " tagger.tag(seq)\n", + " tree = parser.parse(seq)\n", + " \n", + " extractor = SVOExtractor()\n", + " tree.visit(extractor)\n", + " print(line.strip())\n", + " print(\"SUBJ: {} VERB: {} OBJ: {}\".format(extractor.subject, extractor.verb, extractor.object))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/metapy/tutorials/4-classification.ipynb b/metapy/tutorials/4-classification.ipynb new file mode 100644 index 0000000000..2885ce1447 --- /dev/null +++ b/metapy/tutorials/4-classification.ipynb @@ -0,0 +1,1603 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, let's import the Python bindings, as usual." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import metapy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's download a list of stopwords and a small dataset to begin playing around with classifiers in MeTA." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2017-04-18 15:20:46-- https://raw.githubusercontent.com/meta-toolkit/meta/master/data/lemur-stopwords.txt\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving raw.githubusercontent.com... 151.101.0.133, 151.101.64.133, 151.101.128.133, ...\n", + "Connecting to raw.githubusercontent.com|151.101.0.133|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 2747 (2.7K) [text/plain]\n", + "Saving to: ‘lemur-stopwords.txt’\n", + "\n", + "lemur-stopwords.txt 100%[===================>] 2.68K --.-KB/s in 0s \n", + "\n", + "Last-modified header missing -- time-stamps turned off.\n", + "2017-04-18 15:20:46 (90.4 MB/s) - ‘lemur-stopwords.txt’ saved [2747/2747]\n", + "\n" + ] + } + ], + "source": [ + "!wget -N https://raw.githubusercontent.com/meta-toolkit/meta/master/data/lemur-stopwords.txt" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2017-04-18 15:20:47-- https://meta-toolkit.org/data/2016-01-26/ceeaus.tar.gz\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving meta-toolkit.org... 50.116.41.177, 2600:3c02::f03c:91ff:feae:b777\n", + "Connecting to meta-toolkit.org|50.116.41.177|:443... connected.\n", + "HTTP request sent, awaiting response... 304 Not Modified\n", + "File ‘ceeaus.tar.gz’ not modified on server. Omitting download.\n", + "\n", + "ceeaus/\n", + "ceeaus/ceeaus.dat.names.gz\n", + "ceeaus/ceeaus.dat.gz\n", + "ceeaus/ceeaus.dat.names\n", + "ceeaus/line.toml\n", + "ceeaus/ceeaus.dat.labels\n", + "ceeaus/ceeaus-nationality-full-corpus.txt\n", + "ceeaus/gz.toml\n", + "ceeaus/qrels.txt\n", + "ceeaus/file.toml\n", + "ceeaus/ceeaus-full-corpus.txt\n", + "ceeaus/japanese/\n", + "ceeaus/japanese/ceejus_M_smk_174.txt\n", + "ceeaus/japanese/ceejus_S_smk_090.txt\n", + "ceeaus/japanese/ceejus_L_ptj_14.txt\n", + "ceeaus/japanese/ceejus_S_ptj_024.txt\n", + "ceeaus/japanese/ceejus_M_smk_068.txt\n", + "ceeaus/japanese/ceejus_S_smk_115.txt\n", + "ceeaus/japanese/ceejus_M_ptj_128.txt\n", + "ceeaus/japanese/ceejus_M_smk_071.txt\n", + "ceeaus/japanese/ceejus_S_ptj_102.txt\n", + "ceeaus/japanese/ceejus_S_smk_075.txt\n", + "ceeaus/japanese/ceejus_S_smk_119.txt\n", + "ceeaus/japanese/ceejus_L_smk_30.txt\n", + "ceeaus/japanese/ceejus_M_smk_069.txt\n", + "ceeaus/japanese/ceejus_M_smk_108.txt\n", + "ceeaus/japanese/ceejus_U_smk_07.txt\n", + "ceeaus/japanese/ceejus_M_smk_048.txt\n", + "ceeaus/japanese/ceejus_M_ptj_129.txt\n", + "ceeaus/japanese/ceejus_M_ptj_147.txt\n", + "ceeaus/japanese/ceejus_M_smk_144.txt\n", + "ceeaus/japanese/ceejus_S_ptj_050.txt\n", + "ceeaus/japanese/ceejus_M_smk_159.txt\n", + "ceeaus/japanese/ceejus_L_ptj_06.txt\n", + "ceeaus/japanese/ceejus_L_smk_32.txt\n", + "ceeaus/japanese/ceejus_M_smk_095.txt\n", + "ceeaus/japanese/ceejus_U_smk_02.txt\n", + "ceeaus/japanese/ceejus_M_smk_127.txt\n", + "ceeaus/japanese/ceejus_M_ptj_013.txt\n", + "ceeaus/japanese/ceejus_M_smk_122.txt\n", + "ceeaus/japanese/ceejus_M_ptj_068.txt\n", + "ceeaus/japanese/ceejus_M_smk_083.txt\n", + "ceeaus/japanese/ceejus_M_smk_053.txt\n", + "ceeaus/japanese/ceejus_S_smk_112.txt\n", + "ceeaus/japanese/ceejus_M_smk_054.txt\n", + "ceeaus/japanese/ceejus_M_smk_163.txt\n", + "ceeaus/japanese/ceejus_L_ptj_31.txt\n", + "ceeaus/japanese/ceejus_S_ptj_090.txt\n", + "ceeaus/japanese/ceejus_M_smk_009.txt\n", + "ceeaus/japanese/ceejus_M_ptj_166.txt\n", + "ceeaus/japanese/ceejus_M_smk_086.txt\n", + "ceeaus/japanese/ceejus_M_smk_124.txt\n", + "ceeaus/japanese/ceejus_M_ptj_041.txt\n", + "ceeaus/japanese/ceejus_S_smk_078.txt\n", + "ceeaus/japanese/ceejus_M_ptj_197.txt\n", + "ceeaus/japanese/ceejus_M_smk_013.txt\n", + "ceeaus/japanese/ceejus_S_smk_060.txt\n", + "ceeaus/japanese/ceejus_M_smk_146.txt\n", + "ceeaus/japanese/ceejus_M_ptj_057.txt\n", + "ceeaus/japanese/ceejus_M_smk_005.txt\n", + "ceeaus/japanese/ceejus_M_ptj_007.txt\n", + "ceeaus/japanese/ceejus_U_ptj_07.txt\n", + "ceeaus/japanese/ceejus_M_ptj_010.txt\n", + "ceeaus/japanese/ceejus_S_ptj_064.txt\n", + "ceeaus/japanese/ceejus_M_ptj_037.txt\n", + "ceeaus/japanese/ceejus_M_ptj_192.txt\n", + "ceeaus/japanese/ceejus_M_ptj_044.txt\n", + "ceeaus/japanese/ceejus_S_ptj_122.txt\n", + "ceeaus/japanese/ceejus_M_smk_128.txt\n", + "ceeaus/japanese/ceejus_M_ptj_090.txt\n", + "ceeaus/japanese/ceejus_M_ptj_189.txt\n", + "ceeaus/japanese/ceejus_M_smk_172.txt\n", + "ceeaus/japanese/ceejus_M_ptj_180.txt\n", + "ceeaus/japanese/ceejus_U_smk_04.txt\n", + "ceeaus/japanese/ceejus_L_smk_33.txt\n", + "ceeaus/japanese/ceejus_M_smk_171.txt\n", + "ceeaus/japanese/ceejus_S_ptj_072.txt\n", + "ceeaus/japanese/ceejus_M_smk_119.txt\n", + "ceeaus/japanese/ceejus_L_ptj_04.txt\n", + "ceeaus/japanese/ceejus_M_ptj_004.txt\n", + "ceeaus/japanese/ceejus_M_smk_061.txt\n", + "ceeaus/japanese/ceejus_S_ptj_103.txt\n", + "ceeaus/japanese/ceejus_L_smk_14.txt\n", + "ceeaus/japanese/ceejus_M_smk_106.txt\n", + "ceeaus/japanese/ceejus_M_smk_135.txt\n", + "ceeaus/japanese/ceejus_M_ptj_115.txt\n", + "ceeaus/japanese/ceejus_M_smk_187.txt\n", + "ceeaus/japanese/ceejus_M_smk_073.txt\n", + "ceeaus/japanese/ceejus_M_ptj_191.txt\n", + "ceeaus/japanese/ceejus_S_ptj_029.txt\n", + "ceeaus/japanese/ceejus_S_ptj_002.txt\n", + "ceeaus/japanese/ceejus_M_smk_041.txt\n", + "ceeaus/japanese/ceejus_M_ptj_015.txt\n", + "ceeaus/japanese/ceejus_M_ptj_084.txt\n", + "ceeaus/japanese/ceejus_M_ptj_064.txt\n", + "ceeaus/japanese/ceejus_M_ptj_042.txt\n", + "ceeaus/japanese/ceejus_M_ptj_102.txt\n", + "ceeaus/japanese/ceejus_M_smk_084.txt\n", + "ceeaus/japanese/ceejus_M_ptj_110.txt\n", + "ceeaus/japanese/ceejus_M_ptj_130.txt\n", + "ceeaus/japanese/ceejus_M_smk_072.txt\n", + "ceeaus/japanese/ceejus_M_ptj_048.txt\n", + "ceeaus/japanese/ceejus_M_ptj_119.txt\n", + "ceeaus/japanese/ceejus_M_smk_004.txt\n", + "ceeaus/japanese/ceejus_M_ptj_032.txt\n", + "ceeaus/japanese/ceejus_L_smk_10.txt\n", + "ceeaus/japanese/ceejus_M_ptj_185.txt\n", + "ceeaus/japanese/ceejus_S_smk_018.txt\n", + "ceeaus/japanese/ceejus_U_smk_03.txt\n", + "ceeaus/japanese/ceejus_M_smk_038.txt\n", + "ceeaus/japanese/ceejus_S_ptj_040.txt\n", + "ceeaus/japanese/ceejus_M_ptj_096.txt\n", + "ceeaus/japanese/ceejus_M_ptj_127.txt\n", + "ceeaus/japanese/ceejus_S_ptj_092.txt\n", + "ceeaus/japanese/ceejus_M_smk_055.txt\n", + "ceeaus/japanese/ceejus_S_ptj_071.txt\n", + "ceeaus/japanese/ceejus_M_smk_030.txt\n", + "ceeaus/japanese/ceejus_M_smk_011.txt\n", + "ceeaus/japanese/ceejus_M_smk_057.txt\n", + "ceeaus/japanese/ceejus_S_ptj_055.txt\n", + "ceeaus/japanese/ceejus_M_ptj_019.txt\n", + "ceeaus/japanese/ceejus_S_ptj_053.txt\n", + "ceeaus/japanese/ceejus_M_smk_165.txt\n", + "ceeaus/japanese/ceejus_U_smk_08.txt\n", + "ceeaus/japanese/ceejus_M_smk_002.txt\n", + "ceeaus/japanese/ceejus_M_ptj_145.txt\n", + "ceeaus/japanese/ceejus_M_smk_079.txt\n", + "ceeaus/japanese/ceejus_M_ptj_040.txt\n", + "ceeaus/japanese/ceejus_M_smk_032.txt\n", + "ceeaus/japanese/ceejus_S_smk_101.txt\n", + "ceeaus/japanese/ceejus_M_smk_081.txt\n", + "ceeaus/japanese/ceejus_S_smk_068.txt\n", + "ceeaus/japanese/ceejus_S_smk_067.txt\n", + "ceeaus/japanese/ceejus_M_smk_168.txt\n", + "ceeaus/japanese/ceejus_S_ptj_015.txt\n", + "ceeaus/japanese/ceejus_L_smk_04.txt\n", + "ceeaus/japanese/ceejus_S_smk_031.txt\n", + "ceeaus/japanese/ceejus_S_smk_071.txt\n", + "ceeaus/japanese/ceejus_U_ptj_05.txt\n", + "ceeaus/japanese/ceejus_M_ptj_124.txt\n", + "ceeaus/japanese/ceejus_M_smk_141.txt\n", + "ceeaus/japanese/ceejus_M_ptj_066.txt\n", + "ceeaus/japanese/ceejus_L_ptj_09.txt\n", + "ceeaus/japanese/ceejus_S_smk_019.txt\n", + "ceeaus/japanese/ceejus_S_ptj_028.txt\n", + "ceeaus/japanese/ceejus_M_smk_183.txt\n", + "ceeaus/japanese/ceejus_S_smk_042.txt\n", + "ceeaus/japanese/ceejus_M_smk_094.txt\n", + "ceeaus/japanese/ceejus_M_ptj_077.txt\n", + "ceeaus/japanese/ceejus_L_ptj_05.txt\n", + "ceeaus/japanese/ceejus_S_smk_056.txt\n", + "ceeaus/japanese/ceejus_M_smk_102.txt\n", + "ceeaus/japanese/ceejus_L_ptj_37.txt\n", + "ceeaus/japanese/ceejus_M_ptj_076.txt\n", + "ceeaus/japanese/ceejus_U_smk_15.txt\n", + "ceeaus/japanese/ceejus_M_ptj_046.txt\n", + "ceeaus/japanese/ceejus_M_smk_049.txt\n", + "ceeaus/japanese/ceejus_L_ptj_21.txt\n", + "ceeaus/japanese/ceejus_M_smk_051.txt\n", + "ceeaus/japanese/ceejus_M_ptj_176.txt\n", + "ceeaus/japanese/ceejus_S_smk_054.txt\n", + "ceeaus/japanese/ceejus_S_ptj_074.txt\n", + "ceeaus/japanese/ceejus_M_ptj_194.txt\n", + "ceeaus/japanese/ceejus_M_ptj_154.txt\n", + "ceeaus/japanese/ceejus_M_ptj_097.txt\n", + "ceeaus/japanese/ceejus_S_smk_110.txt\n", + "ceeaus/japanese/ceejus_M_smk_075.txt\n", + "ceeaus/japanese/ceejus_M_ptj_109.txt\n", + "ceeaus/japanese/ceejus_S_smk_048.txt\n", + "ceeaus/japanese/ceejus_M_smk_062.txt\n", + "ceeaus/japanese/ceejus_S_ptj_065.txt\n", + "ceeaus/japanese/ceejus_M_smk_046.txt\n", + "ceeaus/japanese/ceejus_M_ptj_088.txt\n", + "ceeaus/japanese/ceejus_M_smk_194.txt\n", + "ceeaus/japanese/ceejus_M_smk_078.txt\n", + "ceeaus/japanese/ceejus_M_ptj_156.txt\n", + "ceeaus/japanese/ceejus_M_smk_188.txt\n", + "ceeaus/japanese/ceejus_M_ptj_058.txt\n", + "ceeaus/japanese/ceejus_M_smk_162.txt\n", + "ceeaus/japanese/ceejus_M_smk_125.txt\n", + "ceeaus/japanese/ceejus_M_smk_160.txt\n", + "ceeaus/japanese/ceejus_M_smk_035.txt\n", + "ceeaus/japanese/ceejus_M_smk_158.txt\n", + "ceeaus/japanese/ceejus_L_smk_37.txt\n", + "ceeaus/japanese/ceejus_M_ptj_012.txt\n", + "ceeaus/japanese/ceejus_S_ptj_111.txt\n", + "ceeaus/japanese/ceejus_S_ptj_022.txt\n", + "ceeaus/japanese/ceejus_S_ptj_059.txt\n", + "ceeaus/japanese/ceejus_M_smk_169.txt\n", + "ceeaus/japanese/ceejus_L_smk_23.txt\n", + "ceeaus/japanese/ceejus_S_smk_022.txt\n", + "ceeaus/japanese/ceejus_L_ptj_41.txt\n", + "ceeaus/japanese/ceejus_L_ptj_35.txt\n", + "ceeaus/japanese/ceejus_M_ptj_164.txt\n", + "ceeaus/japanese/ceejus_M_ptj_018.txt\n", + "ceeaus/japanese/ceejus_M_ptj_093.txt\n", + "ceeaus/japanese/ceejus_M_ptj_141.txt\n", + "ceeaus/japanese/ceejus_M_ptj_059.txt\n", + "ceeaus/japanese/ceejus_S_smk_051.txt\n", + "ceeaus/japanese/ceejus_M_ptj_152.txt\n", + "ceeaus/japanese/ceejus_S_smk_011.txt\n", + "ceeaus/japanese/ceejus_M_smk_026.txt\n", + "ceeaus/japanese/ceejus_M_ptj_016.txt\n", + "ceeaus/japanese/ceejus_M_ptj_030.txt\n", + "ceeaus/japanese/ceejus_S_smk_106.txt\n", + "ceeaus/japanese/ceejus_M_ptj_049.txt\n", + "ceeaus/japanese/ceejus_M_smk_143.txt\n", + "ceeaus/japanese/ceejus_L_ptj_23.txt\n", + "ceeaus/japanese/ceejus_S_smk_083.txt\n", + "ceeaus/japanese/ceejus_M_smk_012.txt\n", + "ceeaus/japanese/ceejus_S_ptj_045.txt\n", + "ceeaus/japanese/ceejus_M_smk_192.txt\n", + "ceeaus/japanese/ceejus_L_ptj_03.txt\n", + "ceeaus/japanese/ceejus_M_ptj_092.txt\n", + "ceeaus/japanese/ceejus_M_smk_138.txt\n", + "ceeaus/japanese/ceejus_M_smk_080.txt\n", + "ceeaus/japanese/ceejus_M_ptj_144.txt\n", + "ceeaus/japanese/ceejus_S_ptj_073.txt\n", + "ceeaus/japanese/ceejus_M_ptj_163.txt\n", + "ceeaus/japanese/ceejus_M_smk_088.txt\n", + "ceeaus/japanese/ceejus_L_smk_09.txt\n", + "ceeaus/japanese/ceejus_M_ptj_061.txt\n", + "ceeaus/japanese/ceejus_M_ptj_009.txt\n", + "ceeaus/japanese/ceejus_U_ptj_03.txt\n", + "ceeaus/japanese/ceejus_M_smk_130.txt\n", + "ceeaus/japanese/ceejus_M_ptj_183.txt\n", + "ceeaus/japanese/ceejus_S_ptj_021.txt\n", + "ceeaus/japanese/ceejus_M_smk_184.txt\n", + "ceeaus/japanese/ceejus_M_smk_137.txt\n", + "ceeaus/japanese/ceejus_M_smk_064.txt\n", + "ceeaus/japanese/ceejus_S_smk_116.txt\n", + "ceeaus/japanese/ceejus_M_smk_112.txt\n", + "ceeaus/japanese/ceejus_M_ptj_078.txt\n", + "ceeaus/japanese/ceejus_S_smk_128.txt\n", + "ceeaus/japanese/ceejus_M_smk_129.txt\n", + "ceeaus/japanese/ceejus_M_smk_178.txt\n", + "ceeaus/japanese/ceejus_M_smk_036.txt\n", + "ceeaus/japanese/ceejus_M_smk_082.txt\n", + "ceeaus/japanese/ceejus_S_smk_012.txt\n", + "ceeaus/japanese/ceejus_S_ptj_078.txt\n", + "ceeaus/japanese/ceejus_S_ptj_086.txt\n", + "ceeaus/japanese/ceejus_M_smk_118.txt\n", + "ceeaus/japanese/ceejus_S_ptj_014.txt\n", + "ceeaus/japanese/ceejus_S_ptj_081.txt\n", + "ceeaus/japanese/ceejus_M_smk_024.txt\n", + "ceeaus/japanese/ceejus_U_ptj_06.txt\n", + "ceeaus/japanese/ceejus_M_smk_173.txt\n", + "ceeaus/japanese/ceejus_S_ptj_042.txt\n", + "ceeaus/japanese/ceejus_S_ptj_084.txt\n", + "ceeaus/japanese/ceejus_S_ptj_070.txt\n", + "ceeaus/japanese/ceejus_S_smk_118.txt\n", + "ceeaus/japanese/ceejus_M_ptj_056.txt\n", + "ceeaus/japanese/ceejus_S_smk_027.txt\n", + "ceeaus/japanese/ceejus_M_ptj_116.txt\n", + "ceeaus/japanese/ceejus_S_smk_044.txt\n", + "ceeaus/japanese/ceejus_S_ptj_124.txt\n", + "ceeaus/japanese/ceejus_M_smk_197.txt\n", + "ceeaus/japanese/ceejus_S_ptj_034.txt\n", + "ceeaus/japanese/ceejus_M_ptj_080.txt\n", + "ceeaus/japanese/ceejus_S_ptj_046.txt\n", + "ceeaus/japanese/ceejus_U_ptj_18.txt\n", + "ceeaus/japanese/ceejus_M_smk_017.txt\n", + "ceeaus/japanese/ceejus_S_ptj_095.txt\n", + "ceeaus/japanese/ceejus_U_ptj_11.txt\n", + "ceeaus/japanese/ceejus_L_smk_20.txt\n", + "ceeaus/japanese/ceejus_M_smk_010.txt\n", + "ceeaus/japanese/ceejus_M_ptj_071.txt\n", + "ceeaus/japanese/ceejus_M_ptj_085.txt\n", + "ceeaus/japanese/ceejus_S_ptj_044.txt\n", + "ceeaus/japanese/ceejus_M_smk_139.txt\n", + "ceeaus/japanese/ceejus_M_ptj_155.txt\n", + "ceeaus/japanese/ceejus_M_ptj_023.txt\n", + "ceeaus/japanese/ceejus_L_ptj_02.txt\n", + "ceeaus/japanese/ceejus_L_ptj_20.txt\n", + "ceeaus/japanese/ceejus_U_smk_16.txt\n", + "ceeaus/japanese/ceejus_S_ptj_119.txt\n", + "ceeaus/japanese/ceejus_M_ptj_123.txt\n", + "ceeaus/japanese/ceejus_M_ptj_003.txt\n", + "ceeaus/japanese/ceejus_S_ptj_104.txt\n", + "ceeaus/japanese/ceejus_M_smk_132.txt\n", + "ceeaus/japanese/ceejus_M_smk_033.txt\n", + "ceeaus/japanese/ceejus_M_ptj_065.txt\n", + "ceeaus/japanese/ceejus_S_ptj_099.txt\n", + "ceeaus/japanese/ceejus_S_ptj_058.txt\n", + "ceeaus/japanese/ceejus_S_ptj_114.txt\n", + "ceeaus/japanese/ceejus_S_ptj_123.txt\n", + "ceeaus/japanese/ceejus_M_ptj_120.txt\n", + "ceeaus/japanese/ceejus_M_smk_098.txt\n", + "ceeaus/japanese/ceejus_S_ptj_105.txt\n", + "ceeaus/japanese/ceejus_S_smk_072.txt\n", + "ceeaus/japanese/ceejus_S_ptj_051.txt\n", + "ceeaus/japanese/ceejus_L_ptj_07.txt\n", + "ceeaus/japanese/ceejus_S_smk_120.txt\n", + "ceeaus/japanese/ceejus_S_ptj_013.txt\n", + "ceeaus/japanese/ceejus_L_ptj_33.txt\n", + "ceeaus/japanese/ceejus_M_ptj_172.txt\n", + "ceeaus/japanese/ceejus_U_ptj_14.txt\n", + "ceeaus/japanese/ceejus_M_smk_155.txt\n", + "ceeaus/japanese/ceejus_M_smk_103.txt\n", + "ceeaus/japanese/ceejus_M_smk_116.txt\n", + "ceeaus/japanese/ceejus_S_smk_007.txt\n", + "ceeaus/japanese/ceejus_M_ptj_175.txt\n", + "ceeaus/japanese/ceejus_S_smk_074.txt\n", + "ceeaus/japanese/ceejus_M_smk_091.txt\n", + "ceeaus/japanese/ceejus_M_smk_001.txt\n", + "ceeaus/japanese/ceejus_M_ptj_182.txt\n", + "ceeaus/japanese/ceejus_M_ptj_108.txt\n", + "ceeaus/japanese/ceejus_M_smk_123.txt\n", + "ceeaus/japanese/ceejus_S_ptj_008.txt\n", + "ceeaus/japanese/ceejus_M_smk_066.txt\n", + "ceeaus/japanese/ceejus_S_smk_064.txt\n", + "ceeaus/japanese/ceejus_L_smk_03.txt\n", + "ceeaus/japanese/ceejus_M_smk_096.txt\n", + "ceeaus/japanese/ceejus_S_ptj_061.txt\n", + "ceeaus/japanese/ceejus_S_smk_004.txt\n", + "ceeaus/japanese/ceejus_M_smk_113.txt\n", + "ceeaus/japanese/ceejus_M_ptj_027.txt\n", + "ceeaus/japanese/ceejus_S_ptj_077.txt\n", + "ceeaus/japanese/ceejus_M_ptj_187.txt\n", + "ceeaus/japanese/ceejus_U_smk_14.txt\n", + "ceeaus/japanese/ceejus_S_ptj_047.txt\n", + "ceeaus/japanese/ceejus_M_ptj_117.txt\n", + "ceeaus/japanese/ceejus_M_ptj_050.txt\n", + "ceeaus/japanese/ceejus_S_ptj_043.txt\n", + "ceeaus/japanese/ceejus_S_ptj_125.txt\n", + "ceeaus/japanese/ceejus_M_smk_145.txt\n", + "ceeaus/japanese/ceejus_S_ptj_116.txt\n", + "ceeaus/japanese/ceejus_S_ptj_089.txt\n", + "ceeaus/japanese/ceejus_S_ptj_011.txt\n", + "ceeaus/japanese/ceejus_U_ptj_12.txt\n", + "ceeaus/japanese/ceejus_S_smk_070.txt\n", + "ceeaus/japanese/ceejus_U_ptj_13.txt\n", + "ceeaus/japanese/ceejus_U_smk_13.txt\n", + "ceeaus/japanese/ceejus_S_smk_001.txt\n", + "ceeaus/japanese/ceejus_M_ptj_179.txt\n", + "ceeaus/japanese/ceejus_U_ptj_01.txt\n", + "ceeaus/japanese/ceejus_M_ptj_171.txt\n", + "ceeaus/japanese/ceejus_M_ptj_195.txt\n", + "ceeaus/japanese/ceejus_M_ptj_022.txt\n", + "ceeaus/japanese/ceejus_L_smk_29.txt\n", + "ceeaus/japanese/ceejus_M_smk_150.txt\n", + "ceeaus/japanese/ceejus_S_smk_005.txt\n", + "ceeaus/japanese/ceejus_S_ptj_079.txt\n", + "ceeaus/japanese/ceejus_L_ptj_13.txt\n", + "ceeaus/japanese/ceejus_S_ptj_049.txt\n", + "ceeaus/japanese/ceejus_M_smk_040.txt\n", + "ceeaus/japanese/ceejus_S_ptj_106.txt\n", + "ceeaus/japanese/ceejus_S_smk_124.txt\n", + "ceeaus/japanese/ceejus_S_smk_055.txt\n", + "ceeaus/japanese/ceejus_S_ptj_019.txt\n", + "ceeaus/japanese/ceejus_M_ptj_137.txt\n", + "ceeaus/japanese/ceejus_S_ptj_027.txt\n", + "ceeaus/japanese/ceejus_M_smk_067.txt\n", + "ceeaus/japanese/ceejus_M_ptj_160.txt\n", + "ceeaus/japanese/ceejus_S_ptj_068.txt\n", + "ceeaus/japanese/ceejus_S_smk_016.txt\n", + "ceeaus/japanese/ceejus_L_smk_15.txt\n", + "ceeaus/japanese/ceejus_M_smk_142.txt\n", + "ceeaus/japanese/ceejus_S_smk_026.txt\n", + "ceeaus/japanese/ceejus_S_smk_082.txt\n", + "ceeaus/japanese/ceejus_S_smk_066.txt\n", + "ceeaus/japanese/ceejus_S_ptj_063.txt\n", + "ceeaus/japanese/ceejus_M_smk_003.txt\n", + "ceeaus/japanese/ceejus_M_smk_177.txt\n", + "ceeaus/japanese/ceejus_M_ptj_063.txt\n", + "ceeaus/japanese/ceejus_M_smk_007.txt\n", + "ceeaus/japanese/ceejus_L_ptj_32.txt\n", + "ceeaus/japanese/ceejus_M_ptj_025.txt\n", + "ceeaus/japanese/ceejus_M_ptj_036.txt\n", + "ceeaus/japanese/ceejus_M_ptj_029.txt\n", + "ceeaus/japanese/ceejus_U_smk_01.txt\n", + "ceeaus/japanese/ceejus_M_ptj_052.txt\n", + "ceeaus/japanese/ceejus_M_ptj_122.txt\n", + "ceeaus/japanese/ceejus_M_smk_100.txt\n", + "ceeaus/japanese/ceejus_S_ptj_030.txt\n", + "ceeaus/japanese/ceejus_S_ptj_001.txt\n", + "ceeaus/japanese/ceejus_M_ptj_151.txt\n", + "ceeaus/japanese/ceejus_S_smk_035.txt\n", + "ceeaus/japanese/ceejus_M_smk_107.txt\n", + "ceeaus/japanese/ceejus_M_smk_076.txt\n", + "ceeaus/japanese/ceejus_M_ptj_094.txt\n", + "ceeaus/japanese/ceejus_M_smk_186.txt\n", + "ceeaus/japanese/ceejus_S_smk_123.txt\n", + "ceeaus/japanese/ceejus_M_ptj_161.txt\n", + "ceeaus/japanese/ceejus_M_smk_157.txt\n", + "ceeaus/japanese/ceejus_S_smk_024.txt\n", + "ceeaus/japanese/ceejus_S_ptj_107.txt\n", + "ceeaus/japanese/ceejus_S_smk_063.txt\n", + "ceeaus/japanese/ceejus_S_smk_059.txt\n", + "ceeaus/japanese/ceejus_S_ptj_031.txt\n", + "ceeaus/japanese/ceejus_M_ptj_177.txt\n", + "ceeaus/japanese/ceejus_L_ptj_10.txt\n", + "ceeaus/japanese/ceejus_U_ptj_09.txt\n", + "ceeaus/japanese/ceejus_M_ptj_002.txt\n", + "ceeaus/japanese/ceejus_M_ptj_162.txt\n", + "ceeaus/japanese/ceejus_S_ptj_091.txt\n", + "ceeaus/japanese/ceejus_M_smk_134.txt\n", + "ceeaus/japanese/ceejus_S_ptj_017.txt\n", + "ceeaus/japanese/ceejus_S_smk_046.txt\n", + "ceeaus/japanese/ceejus_L_smk_16.txt\n", + "ceeaus/japanese/ceejus_U_ptj_10.txt\n", + "ceeaus/japanese/ceejus_L_smk_08.txt\n", + "ceeaus/japanese/ceejus_M_smk_070.txt\n", + "ceeaus/japanese/ceejus_M_ptj_073.txt\n", + "ceeaus/japanese/ceejus_S_ptj_016.txt\n", + "ceeaus/japanese/ceejus_M_ptj_034.txt\n", + "ceeaus/japanese/ceejus_M_smk_019.txt\n", + "ceeaus/japanese/ceejus_S_ptj_128.txt\n", + "ceeaus/japanese/ceejus_L_ptj_29.txt\n", + "ceeaus/japanese/ceejus_S_smk_102.txt\n", + "ceeaus/japanese/ceejus_M_smk_133.txt\n", + "ceeaus/japanese/ceejus_M_smk_195.txt\n", + "ceeaus/japanese/ceejus_M_ptj_142.txt\n", + "ceeaus/japanese/ceejus_S_smk_009.txt\n", + "ceeaus/japanese/ceejus_U_smk_17.txt\n", + "ceeaus/japanese/ceejus_L_ptj_01.txt\n", + "ceeaus/japanese/ceejus_S_ptj_052.txt\n", + "ceeaus/japanese/ceejus_M_smk_101.txt\n", + "ceeaus/japanese/ceejus_S_smk_023.txt\n", + "ceeaus/japanese/ceejus_M_smk_087.txt\n", + "ceeaus/japanese/ceejus_S_smk_021.txt\n", + "ceeaus/japanese/ceejus_M_ptj_105.txt\n", + "ceeaus/japanese/ceejus_S_smk_095.txt\n", + "ceeaus/japanese/ceejus_S_smk_093.txt\n", + "ceeaus/japanese/ceejus_M_smk_182.txt\n", + "ceeaus/japanese/ceejus_S_ptj_037.txt\n", + "ceeaus/japanese/ceejus_L_smk_26.txt\n", + "ceeaus/japanese/ceejus_M_ptj_062.txt\n", + "ceeaus/japanese/ceejus_M_ptj_051.txt\n", + "ceeaus/japanese/ceejus_S_smk_038.txt\n", + "ceeaus/japanese/ceejus_M_smk_060.txt\n", + "ceeaus/japanese/ceejus_M_ptj_150.txt\n", + "ceeaus/japanese/ceejus_S_smk_013.txt\n", + "ceeaus/japanese/ceejus_L_smk_38.txt\n", + "ceeaus/japanese/ceejus_L_ptj_30.txt\n", + "ceeaus/japanese/ceejus_S_ptj_113.txt\n", + "ceeaus/japanese/ceejus_S_smk_037.txt\n", + "ceeaus/japanese/ceejus_S_smk_033.txt\n", + "ceeaus/japanese/ceejus_M_ptj_100.txt\n", + "ceeaus/japanese/ceejus_M_ptj_132.txt\n", + "ceeaus/japanese/ceejus_S_smk_036.txt\n", + "ceeaus/japanese/ceejus_M_ptj_143.txt\n", + "ceeaus/japanese/ceejus_S_ptj_005.txt\n", + "ceeaus/japanese/ceejus_M_ptj_107.txt\n", + "ceeaus/japanese/ceejus_M_smk_117.txt\n", + "ceeaus/japanese/ceejus_S_ptj_026.txt\n", + "ceeaus/japanese/ceejus_S_ptj_115.txt\n", + "ceeaus/japanese/ceejus_M_smk_093.txt\n", + "ceeaus/japanese/ceejus_S_ptj_032.txt\n", + "ceeaus/japanese/ceejus_L_smk_27.txt\n", + "ceeaus/japanese/ceejus_U_smk_19.txt\n", + "ceeaus/japanese/ceejus_M_ptj_101.txt\n", + "ceeaus/japanese/ceejus_S_smk_077.txt\n", + "ceeaus/japanese/ceejus_S_smk_103.txt\n", + "ceeaus/japanese/ceejus_U_smk_10.txt\n", + "ceeaus/japanese/ceejus_M_ptj_125.txt\n", + "ceeaus/japanese/ceejus_M_smk_140.txt\n", + "ceeaus/japanese/ceejus_M_ptj_121.txt\n", + "ceeaus/japanese/ceejus_M_smk_109.txt\n", + "ceeaus/japanese/ceejus_M_smk_056.txt\n", + "ceeaus/japanese/ceejus_U_smk_06.txt\n", + "ceeaus/japanese/ceejus_S_ptj_023.txt\n", + "ceeaus/japanese/ceejus_M_smk_044.txt\n", + "ceeaus/japanese/ceejus_S_ptj_087.txt\n", + "ceeaus/japanese/ceejus_S_ptj_109.txt\n", + "ceeaus/japanese/ceejus_S_smk_117.txt\n", + "ceeaus/japanese/ceejus_M_smk_099.txt\n", + "ceeaus/japanese/ceejus_S_ptj_006.txt\n", + "ceeaus/japanese/ceejus_S_smk_104.txt\n", + "ceeaus/japanese/ceejus_M_smk_180.txt\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ceeaus/japanese/ceejus_L_smk_11.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_035.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_149.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_196.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_135.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_06.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_110.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_39.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_193.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_090.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_047.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_099.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_13.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_184.txt\r\n", + "ceeaus/japanese/ceejus_U_ptj_04.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_176.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_029.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_125.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_085.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_104.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_010.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_164.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_028.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_149.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_115.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_077.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_086.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_030.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_12.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_120.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_067.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_022.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_196.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_166.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_026.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_099.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_052.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_021.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_055.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_100.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_167.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_133.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_170.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_167.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_054.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_028.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_118.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_27.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_074.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_053.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_120.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_039.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_158.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_003.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_089.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_061.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_179.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_165.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_087.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_069.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_107.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_181.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_043.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_117.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_112.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_094.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_098.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_006.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_186.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_154.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_092.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_134.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_17.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_140.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_114.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_063.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_096.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_12.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_053.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_161.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_126.txt\r\n", + "ceeaus/japanese/ceejus_U_ptj_02.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_006.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_41.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_151.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_34.txt\r\n", + "ceeaus/japanese/ceejus_U_smk_18.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_152.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_127.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_098.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_104.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_010.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_041.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_38.txt\r\n", + "ceeaus/japanese/ceejus_U_smk_12.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_027.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_015.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_121.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_042.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_106.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_032.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_181.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_012.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_081.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_047.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_18.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_065.txt\r\n", + "ceeaus/japanese/ceejus_U_smk_05.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_25.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_033.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_015.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_136.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_038.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_121.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_138.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_139.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_193.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_105.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_169.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_111.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_122.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_065.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_057.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_050.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_014.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_01.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_127.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_097.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_108.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_060.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_173.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_025.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_113.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_174.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_039.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_18.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_047.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_082.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_054.txt\r\n", + "ceeaus/japanese/ceejus_U_ptj_19.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_037.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_083.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_017.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_07.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_043.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_093.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_088.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_16.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_025.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_22.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_111.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_21.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_118.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_033.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_058.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_24.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_079.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_40.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_020.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_105.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_136.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_014.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_25.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_023.txt\r\n", + "ceeaus/japanese/ceejus_U_smk_09.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_17.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_034.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_062.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_092.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_146.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_073.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_005.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_19.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_004.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_057.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_008.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_049.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_018.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_045.txt\r\n", + "ceeaus/japanese/ceejus_U_ptj_08.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_096.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_088.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_098.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_082.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_031.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_087.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_091.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_111.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_017.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_34.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_39.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_085.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_056.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_016.txt\r\n", + "ceeaus/japanese/ceejus_U_ptj_15.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_089.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_190.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_175.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_110.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_159.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_36.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_024.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_156.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_31.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_074.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_113.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_190.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_008.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_103.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_15.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_114.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_097.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_035.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_126.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_091.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_050.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_178.txt\r\n", + "ceeaus/japanese/ceejus_U_ptj_16.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_126.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_148.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_011.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_081.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_35.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_094.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_079.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_11.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_070.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_052.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_072.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_40.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_36.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_02.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_157.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_006.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_170.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_08.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_28.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_084.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_121.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_148.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_185.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_034.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_020.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_05.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_089.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_097.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_147.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_048.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_007.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_001.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_058.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_168.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_025.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_076.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_043.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_080.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_26.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_039.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_021.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_188.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_039.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_062.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_100.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_028.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_075.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_069.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_031.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_069.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_040.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_086.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_153.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_101.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_059.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_24.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_095.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_060.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_029.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_041.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_085.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_191.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_131.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_189.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_080.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_045.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_014.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_131.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_036.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_126.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_075.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_108.txt\r\n", + "ceeaus/japanese/ceejus_L_ptj_28.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_038.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_083.txt\r\n", + "ceeaus/japanese/ceejus_U_ptj_17.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_003.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_018.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_009.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_045.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_066.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_020.txt\r\n", + "ceeaus/japanese/ceejus_U_smk_11.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_19.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_076.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_067.txt\r\n", + "ceeaus/japanese/ceejus_M_smk_153.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_020.txt\r\n", + "ceeaus/japanese/ceejus_L_smk_22.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_002.txt\r\n", + "ceeaus/japanese/ceejus_S_smk_109.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_008.txt\r\n", + "ceeaus/japanese/ceejus_S_ptj_112.txt\r\n", + "ceeaus/japanese/ceejus_M_ptj_114.txt\r\n", + "ceeaus/english/\r\n", + "ceeaus/english/ceenas_smk_11.txt\r\n", + "ceeaus/english/ceenas_ptj_02.txt\r\n", + "ceeaus/english/ceenas_smk_20.txt\r\n", + "ceeaus/english/ceenas_smk_06.txt\r\n", + "ceeaus/english/ceenas_ptj_57.txt\r\n", + "ceeaus/english/ceenas_ptj_65.txt\r\n", + "ceeaus/english/ceenas_ptj_36.txt\r\n", + "ceeaus/english/ceenas_ptj_64.txt\r\n", + "ceeaus/english/ceenas_smk_08.txt\r\n", + "ceeaus/english/ceenas_ptj_42.txt\r\n", + "ceeaus/english/ceenas_ptj_14.txt\r\n", + "ceeaus/english/ceenas_ptj_63.txt\r\n", + "ceeaus/english/ceenas_ptj_45.txt\r\n", + "ceeaus/english/ceenas_ptj_60.txt\r\n", + "ceeaus/english/ceenas_ptj_31.txt\r\n", + "ceeaus/english/ceenas_smk_51.txt\r\n", + "ceeaus/english/ceenas_smk_60.txt\r\n", + "ceeaus/english/ceenas_ptj_37.txt\r\n", + "ceeaus/english/ceenas_ptj_22.txt\r\n", + "ceeaus/english/ceenas_ptj_24.txt\r\n", + "ceeaus/english/ceenas_smk_56.txt\r\n", + "ceeaus/english/ceenas_smk_37.txt\r\n", + "ceeaus/english/ceenas_ptj_71.txt\r\n", + "ceeaus/english/ceenas_ptj_62.txt\r\n", + "ceeaus/english/ceenas_smk_31.txt\r\n", + "ceeaus/english/ceenas_smk_66.txt\r\n", + "ceeaus/english/ceenas_smk_40.txt\r\n", + "ceeaus/english/ceenas_ptj_41.txt\r\n", + "ceeaus/english/ceenas_smk_42.txt\r\n", + "ceeaus/english/ceenas_smk_30.txt\r\n", + "ceeaus/english/ceenas_ptj_50.txt\r\n", + "ceeaus/english/ceenas_smk_29.txt\r\n", + "ceeaus/english/ceenas_ptj_34.txt\r\n", + "ceeaus/english/ceenas_smk_34.txt\r\n", + "ceeaus/english/ceenas_smk_45.txt\r\n", + "ceeaus/english/ceenas_ptj_08.txt\r\n", + "ceeaus/english/ceenas_ptj_05.txt\r\n", + "ceeaus/english/ceenas_smk_52.txt\r\n", + "ceeaus/english/ceenas_ptj_55.txt\r\n", + "ceeaus/english/ceenas_smk_02.txt\r\n", + "ceeaus/english/ceenas_ptj_30.txt\r\n", + "ceeaus/english/ceenas_ptj_09.txt\r\n", + "ceeaus/english/ceenas_smk_58.txt\r\n", + "ceeaus/english/ceenas_smk_71.txt\r\n", + "ceeaus/english/ceenas_ptj_04.txt\r\n", + "ceeaus/english/ceenas_smk_17.txt\r\n", + "ceeaus/english/ceenas_smk_69.txt\r\n", + "ceeaus/english/ceenas_ptj_73.txt\r\n", + "ceeaus/english/ceenas_ptj_35.txt\r\n", + "ceeaus/english/ceenas_smk_10.txt\r\n", + "ceeaus/english/ceenas_smk_27.txt\r\n", + "ceeaus/english/ceenas_ptj_18.txt\r\n", + "ceeaus/english/ceenas_ptj_19.txt\r\n", + "ceeaus/english/ceenas_ptj_26.txt\r\n", + "ceeaus/english/ceenas_smk_68.txt\r\n", + "ceeaus/english/ceenas_smk_24.txt\r\n", + "ceeaus/english/ceenas_smk_63.txt\r\n", + "ceeaus/english/ceenas_ptj_07.txt\r\n", + "ceeaus/english/ceenas_ptj_51.txt\r\n", + "ceeaus/english/ceenas_ptj_10.txt\r\n", + "ceeaus/english/ceenas_smk_39.txt\r\n", + "ceeaus/english/ceenas_ptj_66.txt\r\n", + "ceeaus/english/ceenas_smk_21.txt\r\n", + "ceeaus/english/ceenas_ptj_40.txt\r\n", + "ceeaus/english/ceenas_ptj_72.txt\r\n", + "ceeaus/english/ceenas_ptj_06.txt\r\n", + "ceeaus/english/ceenas_smk_09.txt\r\n", + "ceeaus/english/ceenas_smk_01.txt\r\n", + "ceeaus/english/ceenas_ptj_15.txt\r\n", + "ceeaus/english/ceenas_smk_04.txt\r\n", + "ceeaus/english/ceenas_ptj_32.txt\r\n", + "ceeaus/english/ceenas_smk_50.txt\r\n", + "ceeaus/english/ceenas_smk_54.txt\r\n", + "ceeaus/english/ceenas_ptj_12.txt\r\n", + "ceeaus/english/ceenas_ptj_17.txt\r\n", + "ceeaus/english/ceenas_smk_43.txt\r\n", + "ceeaus/english/ceenas_ptj_54.txt\r\n", + "ceeaus/english/ceenas_ptj_67.txt\r\n", + "ceeaus/english/ceenas_smk_05.txt\r\n", + "ceeaus/english/ceenas_smk_14.txt\r\n", + "ceeaus/english/ceenas_ptj_03.txt\r\n", + "ceeaus/english/ceenas_smk_35.txt\r\n", + "ceeaus/english/ceenas_ptj_29.txt\r\n", + "ceeaus/english/ceenas_ptj_70.txt\r\n", + "ceeaus/english/ceenas_smk_65.txt\r\n", + "ceeaus/english/ceenas_smk_28.txt\r\n", + "ceeaus/english/ceenas_ptj_13.txt\r\n", + "ceeaus/english/ceenas_smk_72.txt\r\n", + "ceeaus/english/ceenas_ptj_68.txt\r\n", + "ceeaus/english/ceenas_smk_64.txt\r\n", + "ceeaus/english/ceenas_ptj_20.txt\r\n", + "ceeaus/english/ceenas_smk_22.txt\r\n", + "ceeaus/english/ceenas_smk_07.txt\r\n", + "ceeaus/english/ceenas_ptj_46.txt\r\n", + "ceeaus/english/ceenas_smk_18.txt\r\n", + "ceeaus/english/ceenas_ptj_27.txt\r\n", + "ceeaus/english/ceenas_smk_73.txt\r\n", + "ceeaus/english/ceenas_smk_48.txt\r\n", + "ceeaus/english/ceenas_smk_36.txt\r\n", + "ceeaus/english/ceenas_smk_49.txt\r\n", + "ceeaus/english/ceenas_ptj_52.txt\r\n", + "ceeaus/english/ceenas_smk_13.txt\r\n", + "ceeaus/english/ceenas_ptj_16.txt\r\n", + "ceeaus/english/ceenas_smk_25.txt\r\n", + "ceeaus/english/ceenas_smk_53.txt\r\n", + "ceeaus/english/ceenas_smk_12.txt\r\n", + "ceeaus/english/ceenas_ptj_53.txt\r\n", + "ceeaus/english/ceenas_ptj_43.txt\r\n", + "ceeaus/english/ceenas_ptj_49.txt\r\n", + "ceeaus/english/ceenas_ptj_39.txt\r\n", + "ceeaus/english/ceenas_smk_70.txt\r\n", + "ceeaus/english/ceenas_ptj_69.txt\r\n", + "ceeaus/english/ceenas_smk_55.txt\r\n", + "ceeaus/english/ceenas_ptj_25.txt\r\n", + "ceeaus/english/ceenas_ptj_47.txt\r\n", + "ceeaus/english/ceenas_ptj_28.txt\r\n", + "ceeaus/english/ceenas_smk_47.txt\r\n", + "ceeaus/english/ceenas_ptj_48.txt\r\n", + "ceeaus/english/ceenas_smk_67.txt\r\n", + "ceeaus/english/ceenas_smk_32.txt\r\n", + "ceeaus/english/ceenas_smk_23.txt\r\n", + "ceeaus/english/ceenas_ptj_58.txt\r\n", + "ceeaus/english/ceenas_smk_38.txt\r\n", + "ceeaus/english/ceenas_smk_59.txt\r\n", + "ceeaus/english/ceenas_ptj_44.txt\r\n", + "ceeaus/english/ceenas_ptj_61.txt\r\n", + "ceeaus/english/ceenas_ptj_59.txt\r\n", + "ceeaus/english/ceenas_smk_57.txt\r\n", + "ceeaus/english/ceenas_ptj_38.txt\r\n", + "ceeaus/english/ceenas_ptj_11.txt\r\n", + "ceeaus/english/ceenas_smk_41.txt\r\n", + "ceeaus/english/ceenas_smk_26.txt\r\n", + "ceeaus/english/ceenas_smk_46.txt\r\n", + "ceeaus/english/ceenas_smk_62.txt\r\n", + "ceeaus/english/ceenas_ptj_56.txt\r\n", + "ceeaus/english/ceenas_smk_03.txt\r\n", + "ceeaus/english/ceenas_ptj_33.txt\r\n", + "ceeaus/english/ceenas_smk_19.txt\r\n", + "ceeaus/english/ceenas_smk_33.txt\r\n", + "ceeaus/english/ceenas_smk_61.txt\r\n", + "ceeaus/english/ceenas_ptj_21.txt\r\n", + "ceeaus/english/ceenas_smk_16.txt\r\n", + "ceeaus/english/ceenas_ptj_01.txt\r\n", + "ceeaus/english/ceenas_ptj_23.txt\r\n", + "ceeaus/english/ceenas_smk_44.txt\r\n", + "ceeaus/english/ceenas_smk_15.txt\r\n", + "ceeaus/ceeaus.dat.labels.gz\r\n", + "ceeaus/ceeaus.dat\r\n", + "ceeaus/chinese/\r\n", + "ceeaus/chinese/ceecus_smk_19.txt\r\n", + "ceeaus/chinese/ceecus_smk_05.txt\r\n", + "ceeaus/chinese/ceecus_smk_02.txt\r\n", + "ceeaus/chinese/ceecus_smk_29.txt\r\n", + "ceeaus/chinese/ceecus_smk_41.txt\r\n", + "ceeaus/chinese/ceecus_smk_16.txt\r\n", + "ceeaus/chinese/ceecus_ptj_02.txt\r\n", + "ceeaus/chinese/ceecus_ptj_31.txt\r\n", + "ceeaus/chinese/ceecus_smk_34.txt\r\n", + "ceeaus/chinese/ceecus_ptj_36.txt\r\n", + "ceeaus/chinese/ceecus_ptj_14.txt\r\n", + "ceeaus/chinese/ceecus_smk_38.txt\r\n", + "ceeaus/chinese/ceecus_ptj_07.txt\r\n", + "ceeaus/chinese/ceecus_smk_01.txt\r\n", + "ceeaus/chinese/ceecus_ptj_17.txt\r\n", + "ceeaus/chinese/ceecus_ptj_24.txt\r\n", + "ceeaus/chinese/ceecus_smk_26.txt\r\n", + "ceeaus/chinese/ceecus_ptj_38.txt\r\n", + "ceeaus/chinese/ceecus_ptj_22.txt\r\n", + "ceeaus/chinese/ceecus_smk_40.txt\r\n", + "ceeaus/chinese/ceecus_smk_46.txt\r\n", + "ceeaus/chinese/ceecus_ptj_25.txt\r\n", + "ceeaus/chinese/ceecus_smk_39.txt\r\n", + "ceeaus/chinese/ceecus_ptj_28.txt\r\n", + "ceeaus/chinese/ceecus_ptj_06.txt\r\n", + "ceeaus/chinese/ceecus_smk_07.txt\r\n", + "ceeaus/chinese/ceecus_ptj_30.txt\r\n", + "ceeaus/chinese/ceecus_smk_09.txt\r\n", + "ceeaus/chinese/ceecus_smk_11.txt\r\n", + "ceeaus/chinese/ceecus_smk_24.txt\r\n", + "ceeaus/chinese/ceecus_ptj_39.txt\r\n", + "ceeaus/chinese/ceecus_ptj_45.txt\r\n", + "ceeaus/chinese/ceecus_ptj_41.txt\r\n", + "ceeaus/chinese/ceecus_ptj_20.txt\r\n", + "ceeaus/chinese/ceecus_smk_27.txt\r\n", + "ceeaus/chinese/ceecus_smk_12.txt\r\n", + "ceeaus/chinese/ceecus_smk_30.txt\r\n", + "ceeaus/chinese/ceecus_ptj_33.txt\r\n", + "ceeaus/chinese/ceecus_ptj_16.txt\r\n", + "ceeaus/chinese/ceecus_smk_13.txt\r\n", + "ceeaus/chinese/ceecus_smk_25.txt\r\n", + "ceeaus/chinese/ceecus_smk_45.txt\r\n", + "ceeaus/chinese/ceecus_smk_36.txt\r\n", + "ceeaus/chinese/ceecus_ptj_27.txt\r\n", + "ceeaus/chinese/ceecus_smk_23.txt\r\n", + "ceeaus/chinese/ceecus_ptj_29.txt\r\n", + "ceeaus/chinese/ceecus_ptj_35.txt\r\n", + "ceeaus/chinese/ceecus_smk_08.txt\r\n", + "ceeaus/chinese/ceecus_ptj_21.txt\r\n", + "ceeaus/chinese/ceecus_smk_31.txt\r\n", + "ceeaus/chinese/ceecus_ptj_19.txt\r\n", + "ceeaus/chinese/ceecus_smk_17.txt\r\n", + "ceeaus/chinese/ceecus_smk_10.txt\r\n", + "ceeaus/chinese/ceecus_smk_37.txt\r\n", + "ceeaus/chinese/ceecus_smk_04.txt\r\n", + "ceeaus/chinese/ceecus_ptj_18.txt\r\n", + "ceeaus/chinese/ceecus_smk_35.txt\r\n", + "ceeaus/chinese/ceecus_smk_44.txt\r\n", + "ceeaus/chinese/ceecus_ptj_32.txt\r\n", + "ceeaus/chinese/ceecus_smk_43.txt\r\n", + "ceeaus/chinese/ceecus_ptj_11.txt\r\n", + "ceeaus/chinese/ceecus_ptj_23.txt\r\n", + "ceeaus/chinese/ceecus_smk_18.txt\r\n", + "ceeaus/chinese/ceecus_ptj_10.txt\r\n", + "ceeaus/chinese/ceecus_smk_06.txt\r\n", + "ceeaus/chinese/ceecus_ptj_05.txt\r\n", + "ceeaus/chinese/ceecus_ptj_42.txt\r\n", + "ceeaus/chinese/ceecus_ptj_01.txt\r\n", + "ceeaus/chinese/ceecus_smk_32.txt\r\n", + "ceeaus/chinese/ceecus_smk_42.txt\r\n", + "ceeaus/chinese/ceecus_smk_33.txt\r\n", + "ceeaus/chinese/ceecus_smk_20.txt\r\n", + "ceeaus/chinese/ceecus_smk_21.txt\r\n", + "ceeaus/chinese/ceecus_ptj_44.txt\r\n", + "ceeaus/chinese/ceecus_ptj_12.txt\r\n", + "ceeaus/chinese/ceecus_ptj_13.txt\r\n", + "ceeaus/chinese/ceecus_ptj_04.txt\r\n", + "ceeaus/chinese/ceecus_smk_22.txt\r\n", + "ceeaus/chinese/ceecus_ptj_03.txt\r\n", + "ceeaus/chinese/ceecus_smk_14.txt\r\n", + "ceeaus/chinese/ceecus_ptj_46.txt\r\n", + "ceeaus/chinese/ceecus_smk_03.txt\r\n", + "ceeaus/chinese/ceecus_ptj_43.txt\r\n", + "ceeaus/chinese/ceecus_smk_28.txt\r\n", + "ceeaus/chinese/ceecus_ptj_08.txt\r\n", + "ceeaus/chinese/ceecus_ptj_34.txt\r\n", + "ceeaus/chinese/ceecus_ptj_37.txt\r\n", + "ceeaus/chinese/ceecus_ptj_09.txt\r\n", + "ceeaus/chinese/ceecus_ptj_15.txt\r\n", + "ceeaus/chinese/ceecus_ptj_26.txt\r\n", + "ceeaus/chinese/ceecus_ptj_40.txt\r\n", + "ceeaus/chinese/ceecus_smk_15.txt\r\n" + ] + } + ], + "source": [ + "!wget -N https://meta-toolkit.org/data/2016-01-26/ceeaus.tar.gz\n", + "!tar xvf ceeaus.tar.gz" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's index this dataset. Since we are doing classification experiments, we will most likely be concerning ourselves with a `ForwardIndex`, since we want to map document ids to their feature vector representations." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "fidx = metapy.index.make_forward_index('ceeaus-config.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the feature set used for classification depends on your settings in the configuration file _at the time of indexing_. If you want to play with different feature sets, remember to change your `analyzer` pipeline in the configuration file, and also to **reindex** your documents!\n", + "\n", + "Here, we've just chosen simple unigram words. This is actually a surprisingly good baseline feature set for many text classification problems.\n", + "\n", + "Now that we have a `ForwardIndex` on disk, we need to load the documents we want to start playing with into memory. Since this is a small enough dataset, let's load the whole thing into memory at once.\n", + "\n", + "We need to decide what kind of dataset we're using. MeTA has classes for binary classification (`BinaryDataset`) and multi-class classification (`MulticlassDataset`), which you should choose from depending on the kind of classification problem you're dealing with. Let's see how many labels we have in our corpus." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fidx.num_labels()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since this is more than 2, we likely want a `MulticlassDataset` so we can learn a classifier that can predict which of these three labels a document should have. (But we might be interested in only determining one particular class from the rest, in which case we might actually want a `BinaryDataset`.)\n", + "\n", + "For now, let's focus on the multi-class case, as that likely makes the most sense for this kind of data. Let's load or documents." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1008" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dset = metapy.classify.MulticlassDataset(fidx)\n", + "len(dset)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have 1008 documents, split across three labels. What are our labels?" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'chinese', 'english', 'japanese'}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "set([dset.label(instance) for instance in dset])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This dataset is a small collection of essays written by a bunch of students with different first languages. Our goal will be to try to identify whether an essay was written by a native-Chinese speaker, a native-English speaker, or a native-Japanese speaker.\n", + "\n", + "Now, because these in-memory datasets can potentially be quite large, it's beneficial to not make unnecessary copies of them to, for example, create a new list that's shuffled that contains the same documents. In most cases, you'll be operating with a `DatasetView` (either `MulticlassDatasetView` or `BinaryDatasetView`) so that you can do things like shuffle or rotate the contents of a dataset without having to actually modify it. Doing so is pretty easy: you can use Python's slicing API, or you can just construct one directly." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "view = dset[0:len(dset)+1]\n", + "# or\n", + "view = metapy.classify.MulticlassDatasetView(dset)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can, for example, shuffle this view without changing the underlying datsaet." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "929 vs 0\n" + ] + } + ], + "source": [ + "view.shuffle()\n", + "print(\"{} vs {}\".format(view[0].id, dset[0].id))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The view has been shuffled and now has documents in random order (useful in many cases to make sure that you don't have clumps of the same-labeled documents together, or to just permute the documents in a stochastic learning algorithm), but the underlying dataset is still sorted by id.\n", + "\n", + "We can also use this slicing API to create a random training and testing set from our shuffled views (views also support slicing). Let's make a 75-25 split of training-testing data. (Note that's really important that we already shuffled the view!)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "training = view[0:int(0.75*len(view))]\n", + "testing = view[int(0.75*len(view)):len(view)+1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we're ready to train a classifier! Let's start with very simple one: [Naive Bayes](https://en.wikipedia.org/wiki/Naive_Bayes_classifier).\n", + "\n", + "In MeTA, construction of a classifier implies training of that model. Let's train a Naive Bayes classifier on our training view now." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "nb = metapy.classify.NaiveBayes(training)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now classify individual documents like so." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'english'" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nb.classify(testing[0].weights)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We might be more interested in how well we classify the testing set." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " chinese english japanese \n", + " ------------------------------\n", + " chinese | \u001b[1m0.75\u001b[22m - 0.25 \n", + " english | 0.0278 \u001b[1m0.917\u001b[22m 0.0556 \n", + " japanese | 0.015 - \u001b[1m0.985\u001b[22m \n", + "\n", + "\n" + ] + } + ], + "source": [ + "mtrx = nb.test(testing)\n", + "print(mtrx)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `test()` method of MeTA's classifiers returns to you a `ConfusionMatrix`, which contains useful information about what kinds of mistakes your classifier is making.\n", + "\n", + "(Note that, due to the random shuffling, you might see different results than we do here.)\n", + "\n", + "For example, we can see that this classifier seems to have some trouble with confusing native-Chinese students' essays with those of native-Japanese students. We can tell that by looking at the rows of the confusion matrix. Each row tells you what fraction of documents with that _true_ label were assigned the label for each column by the classifier. In the case of the native-Chinese label, we can see that 25% of the time they were miscategorized as being native-Japanese.\n", + "\n", + "The `ConfusionMatrix` also computes a lot of metrics that are commonly used in classifier evaluation." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "chinese 0.75 0.75 0.75 0.0635 \n", + "english 0.957 1 0.917 0.143 \n", + "japanese 0.978 0.97 0.985 0.794 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.96\u001b[22m \u001b[1m0.961\u001b[22m \u001b[1m0.96\u001b[22m \n", + "------------------------------------------------------------\n", + "252 predictions attempted, overall accuracy: 0.96\n", + "\n" + ] + } + ], + "source": [ + "mtrx.print_stats()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want to make sure that the classifier isn't overfitting to our training data, a common approach is to do [cross-validation](https://en.wikipedia.org/wiki/Cross-validation_(statistics)). Let's run CV for our Naive Bayes classifier across the whole dataset, using 5-folds, to get an idea of how well we might generalize to new data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "mtrx = metapy.classify.cross_validate(lambda fold: metapy.classify.NaiveBayes(fold), view, 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`cross_validate()` returns a `ConfusionMatrix` just like `test()` does. We give it a function to use to create the trained classifiers for each fold, and then pass in the dataset view containing all of our documents, and the number of folds we want to use.\n", + "\n", + "Let's see how we did." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " chinese english japanese \n", + " ------------------------------\n", + " chinese | \u001b[1m0.674\u001b[22m 0.0435 0.283 \n", + " english | 0.0137 \u001b[1m0.945\u001b[22m 0.0411 \n", + " japanese | 0.0013 0.00261 \u001b[1m0.996\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "chinese 0.79 0.954 0.674 0.0915 \n", + "english 0.952 0.958 0.945 0.145 \n", + "japanese 0.978 0.96 0.996 0.763 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.959\u001b[22m \u001b[1m0.959\u001b[22m \u001b[1m0.959\u001b[22m \n", + "------------------------------------------------------------\n", + "1005 predictions attempted, overall accuracy: 0.959\n", + "\n" + ] + } + ], + "source": [ + "print(mtrx)\n", + "mtrx.print_stats()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's do the same thing, but for an arguably stronger baseline: [SVM](https://en.wikipedia.org/wiki/Support_vector_machine).\n", + "\n", + "MeTA's implementation of SVM is actually an approximation using [stochastic gradient descent](https://en.wikipedia.org/wiki/Stochastic_gradient_descent) on the [hinge loss](https://en.wikipedia.org/wiki/Hinge_loss). It's implemented as a `BinaryClassifier`, so we will need to adapt it before it can be used to solve our multi-class clasification problem.\n", + "\n", + "MeTA provides two different adapters for this scenario: [One-vs-All](https://en.wikipedia.org/wiki/Multiclass_classification#One-vs.-rest) and [One-vs-One](https://en.wikipedia.org/wiki/Multiclass_classification#One-vs.-one)." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "ova = metapy.classify.OneVsAll(training, metapy.classify.SGD, loss_id='hinge')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We construct the `OneVsAll` reduction by providing it the training documents, the name of a binary classifier, and then (as keyword arguments) any additional arguments to that chosen classifier. In this case, we use `loss_id` to specify the loss function to use.\n", + "\n", + "We can now use `OneVsAll` just like any other classifier." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " chinese english japanese \n", + " ------------------------------\n", + " chinese | \u001b[1m0.75\u001b[22m - 0.25 \n", + " english | 0.0556 \u001b[1m0.806\u001b[22m 0.139 \n", + " japanese | - 0.005 \u001b[1m0.995\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "chinese 0.8 0.857 0.75 0.0635 \n", + "english 0.879 0.967 0.806 0.143 \n", + "japanese 0.975 0.957 0.995 0.794 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.952\u001b[22m \u001b[1m0.952\u001b[22m \u001b[1m0.952\u001b[22m \n", + "------------------------------------------------------------\n", + "252 predictions attempted, overall accuracy: 0.952\n", + "\n" + ] + } + ], + "source": [ + "mtrx = ova.test(testing)\n", + "print(mtrx)\n", + "mtrx.print_stats()" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " chinese english japanese \n", + " ------------------------------\n", + " chinese | \u001b[1m0.674\u001b[22m 0.0435 0.283 \n", + " english | 0.0137 \u001b[1m0.945\u001b[22m 0.0411 \n", + " japanese | 0.0013 0.00261 \u001b[1m0.996\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "chinese 0.79 0.954 0.674 0.0915 \n", + "english 0.952 0.958 0.945 0.145 \n", + "japanese 0.978 0.96 0.996 0.763 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.959\u001b[22m \u001b[1m0.959\u001b[22m \u001b[1m0.959\u001b[22m \n", + "------------------------------------------------------------\n", + "1005 predictions attempted, overall accuracy: 0.959\n", + "\n" + ] + } + ], + "source": [ + "mtrx = metapy.classify.cross_validate(lambda fold: metapy.classify.OneVsAll(fold, metapy.classify.SGD, loss_id='hinge'), view, 5)\n", + "print(mtrx)\n", + "mtrx.print_stats()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That should be enough to get you started! Try looking at `help(metapy.classify)` for a list of what's included in the bindings." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/metapy/tutorials/5-topic-modeling.ipynb b/metapy/tutorials/5-topic-modeling.ipynb new file mode 100644 index 0000000000..ab48572ba4 --- /dev/null +++ b/metapy/tutorials/5-topic-modeling.ipynb @@ -0,0 +1,812 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "First, let's import the Python bindings, as usual." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "import metapy" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'0.2.10'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "metapy.__version__ # you will want your version to be >= to this" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "If you would like to, you can inform MeTA to output log data to stderr like so:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "metapy.log_to_stderr()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's download a list of stopwords and a sample dataset to begin exploring MeTA's topic models." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2018-05-01 15:41:33-- https://raw.githubusercontent.com/meta-toolkit/meta/master/data/lemur-stopwords.txt\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.184.133\n", + "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.184.133|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 2747 (2.7K) [text/plain]\n", + "Saving to: ‘lemur-stopwords.txt’\n", + "\n", + "lemur-stopwords.txt 100%[===================>] 2.68K --.-KB/s in 0s \n", + "\n", + "Last-modified header missing -- time-stamps turned off.\n", + "2018-05-01 15:41:33 (45.5 MB/s) - ‘lemur-stopwords.txt’ saved [2747/2747]\n", + "\n" + ] + } + ], + "source": [ + "!wget -N https://raw.githubusercontent.com/meta-toolkit/meta/master/data/lemur-stopwords.txt" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2018-05-01 15:41:35-- https://meta-toolkit.org/data/2016-01-26/ceeaus.tar.gz\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving meta-toolkit.org (meta-toolkit.org)... 50.116.41.177, 2600:3c02::f03c:91ff:feae:b777\n", + "Connecting to meta-toolkit.org (meta-toolkit.org)|50.116.41.177|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 1182344 (1.1M) [application/octet-stream]\n", + "Saving to: ‘ceeaus.tar.gz’\n", + "\n", + "ceeaus.tar.gz 100%[===================>] 1.13M 2.30MB/s in 0.5s \n", + "\n", + "2018-05-01 15:41:36 (2.30 MB/s) - ‘ceeaus.tar.gz’ saved [1182344/1182344]\n", + "\n" + ] + } + ], + "source": [ + "!wget -N https://meta-toolkit.org/data/2016-01-26/ceeaus.tar.gz\n", + "!tar xf ceeaus.tar.gz" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We will need to index our data to proceed. We eventually want to be able to extract the bag-of-words representation for our individual documents, so we will want a `ForwardIndex` in this case." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " > Counting lines in file: [=================================] 100% ETA 00:00:00 \n", + "1525207335: [info] Creating forward index: ceeaus-idx/fwd (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/forward_index.cpp:239)\n", + " > Tokenizing Docs: [========================================] 100% ETA 00:00:00 \n", + " > Merging: [================================================] 100% ETA 00:00:00 \n", + "1525207335: [info] Done creating index: ceeaus-idx/fwd (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/forward_index.cpp:278)\n" + ] + } + ], + "source": [ + "fidx = metapy.index.make_forward_index('ceeaus-config.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Just like in classification, the feature set used for the topic modeling will be the feature set used at the time of indexing, so if you want to play with a different set of features (like bigram words), you will need to re-index your data.\n", + "\n", + "For now, we've just stuck with the default filter chain for unigram words, so we're operating in the traditional bag-of-words space.\n", + "\n", + "Let's load our documents into memory to run the topic model inference now." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Loading instances into memory: [> ] 0% ETA 00:00:00 \r", + " > Loading instances into memory: [==========================] 100% ETA 00:00:00 \n" + ] + } + ], + "source": [ + "dset = metapy.learn.Dataset(fidx)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's try to find some topics for this dataset. To do so, we're going to use a generative model called a topic model.\n", + "\n", + "There are many different topic models in the literature, but the most commonly used topic model is Latent Dirichlet Allocation. Here, we propose that there are K topics (represented with a categorical distribution over words) $\\phi_k$ from which all of our documents are genereated. These K topics are modeled as being sampled from a Dirichlet distribution with parameter $\\vec{\\alpha}$. Then, to generate a document $d$, we first sample a distribution over the K topics $\\theta_d$ from another Dirichlet distribution with parameter $\\vec{\\beta}$. Then, for each word in this document, we first sample a topic identifier $z \\sim \\theta_d$ and then the word by drawing from the topic we selected ($w \\sim \\phi_z$). Refer to the [Wikipedia article on LDA](https://en.wikipedia.org/wiki/Latent_Dirichlet_allocation) for more information.\n", + "\n", + "The goal of running inference for an LDA model is to infer the latent variables $\\phi_k$ and $\\theta_d$ for all of the $K$ topics and $D$ documents, respectively. MeTA provides a number of different inference algorithms for LDA, as each one entails a different set of trade-offs (inference in LDA is intractable, so all inference algorithms are approximations; different algorithms entail different approximation guarantees, running times, and required memroy consumption). For now, let's run a Variational Infernce algorithm called CVB0 to find two topics. (In practice you will likely be finding many more topics than just two, but this is a very small toy dataset.)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Initialization: [============================================] 100% ETA 00:00:00 \n", + "Iteration 1 maximum change in gamma: 1.78732 \n", + "Iteration 2 maximum change in gamma: 0.397587 \n", + "Iteration 3 maximum change in gamma: 0.585143 \n", + "Iteration 4 maximum change in gamma: 0.639287 \n", + "Iteration 5 maximum change in gamma: 0.543676 \n", + "Iteration 6 maximum change in gamma: 1.04887 \n", + "Iteration 7 maximum change in gamma: 1.26393 \n", + "Iteration 8 maximum change in gamma: 1.43444 \n", + "Iteration 9 maximum change in gamma: 1.36808 \n", + "Iteration 10 maximum change in gamma: 1.39221 \n", + "Iteration 11 maximum change in gamma: 1.3227 \n", + "Iteration 12 maximum change in gamma: 1.21134 \n", + "Iteration 13 maximum change in gamma: 0.759168 \n", + "Iteration 14 maximum change in gamma: 0.805964 \n", + "Iteration 15 maximum change in gamma: 0.802893 \n", + "Iteration 16 maximum change in gamma: 0.571095 \n", + "Iteration 17 maximum change in gamma: 0.516594 \n", + "Iteration 18 maximum change in gamma: 0.523159 \n", + "Iteration 19 maximum change in gamma: 0.275293 \n", + "Iteration 20 maximum change in gamma: 0.228512 \n", + "Iteration 21 maximum change in gamma: 0.237871 \n", + "Iteration 22 maximum change in gamma: 0.203393 \n", + "Iteration 23 maximum change in gamma: 0.214538 \n", + "Iteration 24 maximum change in gamma: 0.205745 \n", + "Iteration 25 maximum change in gamma: 0.169748 \n", + "Iteration 26 maximum change in gamma: 0.122061 \n", + "Iteration 27 maximum change in gamma: 0.119245 \n", + "Iteration 28 maximum change in gamma: 0.129667 \n", + "Iteration 29 maximum change in gamma: 0.134692 \n", + "Iteration 30 maximum change in gamma: 0.132623 \n", + "Iteration 31 maximum change in gamma: 0.129393 \n", + "Iteration 32 maximum change in gamma: 0.151032 \n", + "Iteration 33 maximum change in gamma: 0.164985 \n", + "Iteration 34 maximum change in gamma: 0.165914 \n", + "Iteration 35 maximum change in gamma: 0.152212 \n", + "Iteration 36 maximum change in gamma: 0.142474 \n", + "Iteration 37 maximum change in gamma: 0.171535 \n", + "Iteration 38 maximum change in gamma: 0.191064 \n", + "Iteration 39 maximum change in gamma: 0.192934 \n", + "Iteration 40 maximum change in gamma: 0.202834 \n", + "Iteration 41 maximum change in gamma: 0.220982 \n", + "Iteration 42 maximum change in gamma: 0.210217 \n", + "Iteration 43 maximum change in gamma: 0.213731 \n", + "Iteration 44 maximum change in gamma: 0.192772 \n", + "Iteration 45 maximum change in gamma: 0.15127 \n", + "Iteration 46 maximum change in gamma: 0.105296 \n", + "Iteration 47 maximum change in gamma: 0.0670212 \n", + "Iteration 48 maximum change in gamma: 0.0402179 \n", + "Iteration 49 maximum change in gamma: 0.0360913 \n", + "Iteration 50 maximum change in gamma: 0.0366095 \n", + "Iteration 51 maximum change in gamma: 0.037 \n", + "Iteration 52 maximum change in gamma: 0.0372273 \n", + "Iteration 53 maximum change in gamma: 0.0374239 \n", + "Iteration 54 maximum change in gamma: 0.0379712 \n", + "Iteration 55 maximum change in gamma: 0.0393836 \n", + "Iteration 56 maximum change in gamma: 0.0430323 \n", + "Iteration 57 maximum change in gamma: 0.0467638 \n", + "Iteration 58 maximum change in gamma: 0.0504449 \n", + "Iteration 59 maximum change in gamma: 0.0539003 \n", + "Iteration 60 maximum change in gamma: 0.0569188 \n", + "Iteration 61 maximum change in gamma: 0.0592677 \n", + "Iteration 62 maximum change in gamma: 0.0607189 \n", + "Iteration 63 maximum change in gamma: 0.0610821 \n", + "Iteration 64 maximum change in gamma: 0.0616854 \n", + "Iteration 65 maximum change in gamma: 0.0622165 \n", + "Iteration 66 maximum change in gamma: 0.0614795 \n", + "Iteration 67 maximum change in gamma: 0.0594567 \n", + "Iteration 68 maximum change in gamma: 0.0562496 \n", + "Iteration 69 maximum change in gamma: 0.0520662 \n", + "Iteration 70 maximum change in gamma: 0.0471889 \n", + "Iteration 71 maximum change in gamma: 0.0419296 \n", + "Iteration 72 maximum change in gamma: 0.0365863 \n", + "Iteration 73 maximum change in gamma: 0.0314094 \n", + "Iteration 74 maximum change in gamma: 0.0265839 \n", + "Iteration 75 maximum change in gamma: 0.0222263 \n", + "Iteration 76 maximum change in gamma: 0.0183923 \n", + "Iteration 77 maximum change in gamma: 0.0150897 \n", + "Iteration 78 maximum change in gamma: 0.0122935 \n", + "Iteration 79 maximum change in gamma: 0.00995884 \n", + "Iteration 80 maximum change in gamma: 0.00803111 \n", + "Iteration 81 maximum change in gamma: 0.00645346 \n", + "Iteration 82 maximum change in gamma: 0.00517133 \n", + "Iteration 83 maximum change in gamma: 0.0041351 \n", + "Iteration 84 maximum change in gamma: 0.00330117 \n", + "Iteration 85 maximum change in gamma: 0.00263226 \n", + "Iteration 86 maximum change in gamma: 0.00209708 \n", + "Iteration 87 maximum change in gamma: 0.00166969 \n", + "Iteration 88 maximum change in gamma: 0.00132887 \n", + "Iteration 89 maximum change in gamma: 0.00121476 \n", + "Iteration 90 maximum change in gamma: 0.00116639 \n", + "Iteration 91 maximum change in gamma: 0.00111979 \n", + "Iteration 92 maximum change in gamma: 0.00107491 \n", + "Iteration 93 maximum change in gamma: 0.00103169 \n", + "Iteration 94 maximum change in gamma: 0.00099009 \n", + "1525207346: [info] Finished maximum iterations, or found convergence! (/tmp/pip-req-build-m473bt6z/deps/meta/src/topics/lda_cvb.cpp:60)\n" + ] + } + ], + "source": [ + "lda_inf = metapy.topics.LDACollapsedVB(dset, num_topics=2, alpha=1.0, beta=0.01)\n", + "lda_inf.run(num_iters=1000)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "source": [ + "The above ran the CVB0 algorithm for 1000 iterations, or until an algorithm-specific convergence criterion was met. Now let's save the current estimate for our topics and topic proportions." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "lda_inf.save('lda-cvb0')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can interrogate the topic inference results by using the `TopicModel` query class. Let's load our inference results back in." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Loading topic term probabilities: [===========> ] 50% ETA 00:00:00 \r", + " > Loading topic term probabilities: [=======================] 100% ETA 00:00:00 \n", + " \r", + " > Loading document topic probabilities: [> ] 0% ETA 00:00:00 \r", + " > Loading document topic probabilities: [===================] 100% ETA 00:00:00 \n" + ] + } + ], + "source": [ + "model = metapy.topics.TopicModel('lda-cvb0')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's have a look at our topics. A typical way of doing this is to print the top $k$ words in each topic, so let's do that." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(3341, 0.1311039703325231),\n", + " (3045, 0.05434932034406297),\n", + " (2677, 0.036780095760011296),\n", + " (3346, 0.033492639884972024),\n", + " (281, 0.022530673690313033),\n", + " (3729, 0.015620482424303144),\n", + " (1953, 0.012780918673797484),\n", + " (707, 0.012635069663149857),\n", + " (592, 0.011987183284170312),\n", + " (2448, 0.01131774038055637)]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.top_k(tid=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The models operate on term ids instead of raw text strings, so let's convert this to a human readable format by using the vocabulary contained in our `ForwardIndex` to map the term ids to strings." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('smoke', 0.1311039703325231),\n", + " ('restaur', 0.05434932034406297),\n", + " ('peopl', 0.036780095760011296),\n", + " ('smoker', 0.033492639884972024),\n", + " ('ban', 0.022530673690313033),\n", + " ('think', 0.015620482424303144),\n", + " ('japan', 0.012780918673797484),\n", + " ('complet', 0.012635069663149857),\n", + " ('cigarett', 0.011987183284170312),\n", + " ('non', 0.01131774038055637)]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[(fidx.term_text(pr[0]), pr[1]) for pr in model.top_k(tid=0)]" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('time', 0.06705646364996719),\n", + " ('job', 0.056059299650279136),\n", + " ('part', 0.05222306274365633),\n", + " ('student', 0.046429384401537266),\n", + " ('colleg', 0.03488140708901945),\n", + " ('work', 0.029067480910345566),\n", + " ('money', 0.02885021953621179),\n", + " ('think', 0.0223313502030152),\n", + " ('import', 0.02075570151328543),\n", + " ('studi', 0.015483035500804767)]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[(fidx.term_text(pr[0]), pr[1]) for pr in model.top_k(tid=1)]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can pretty clearly see that this particular dataset was about two major issues: smoking in public and part time jobs for students. This dataset is actually a collection of essays written by students, and there just so happen to be two different topics they can choose from!\n", + "\n", + "The topics are pretty clear in this case, but in some cases it is also useful to score the terms in a topic using some function of the probability of the word in the topic and the probability of the word in the other topics. Intuitively, we might want to select words from each topic that best reflect that topic's content by picking words that both have high probability in that topic **and** have low probability in the other topics. In other words, we want to balance between high probability terms and highly specific terms (this is kind of like a tf-idf weighting). One such scoring function is provided by the toolkit in `BLTermScorer`, which implements a scoring function proposed by Blei and Lafferty." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('smoke', 0.8741642954704982),\n", + " ('restaur', 0.3174635157613981),\n", + " ('smoker', 0.20060264558827434),\n", + " ('ban', 0.12853037061168004),\n", + " ('cigarett', 0.06557603445386917),\n", + " ('non', 0.06128422163678793),\n", + " ('complet', 0.06105372135982501),\n", + " ('japan', 0.05846453427778453),\n", + " ('health', 0.05054834419152887),\n", + " ('seat', 0.04533989518585457)]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scorer = metapy.topics.BLTermScorer(model)\n", + "[(fidx.term_text(pr[0]), pr[1]) for pr in model.top_k(tid=0, scorer=scorer)]" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('job', 0.34822052999812314),\n", + " ('part', 0.31311071220949405),\n", + " ('student', 0.28328931730015805),\n", + " ('colleg', 0.20808996037214555),\n", + " ('time', 0.17797810952278859),\n", + " ('money', 0.16234681881133195),\n", + " ('work', 0.15585089245616857),\n", + " ('studi', 0.08228292617409116),\n", + " ('learn', 0.06491899302248028),\n", + " ('experi', 0.05494526738519956)]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[(fidx.term_text(pr[0]), pr[1]) for pr in model.top_k(tid=1, scorer=scorer)]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Here we can see that the uninformative word stem \"think\" was downweighted from the word list from each topic, since it had relatively high probability in either topic." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can also see the inferred topic distribution for each document." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.topic_distribution(0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "It looks like our first document was written by a student who chose the part-time job essay topic..." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.topic_distribution(900)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "...whereas this document looks like it was written by a student who chose the public smoking essay topic." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "source": [ + "We can also infer topics for a brand new document. First, let's create the document and use the forward index we loaded before to convert it to a feature vector:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "doc = metapy.index.Document()\n", + "doc.content(\"I think smoking in public is bad for others' health.\")\n", + "fvec = fidx.tokenize(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's load a topic model inferencer that uses the same CVB inference method we used earlier:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Loading topic term probabilities: [===========> ] 50% ETA 00:00:00 \r", + " > Loading topic term probabilities: [=======================] 100% ETA 00:00:00 \n" + ] + } + ], + "source": [ + "inferencer = metapy.topics.CVBInferencer('lda-cvb0.phi.bin', alpha=1.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's infer the topic proportions for the new document:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "proportions = inferencer.infer(fvec, max_iters=20, convergence=1e-4)\n", + "print(proportions)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/metapy/tutorials/KDD 2017.ipynb b/metapy/tutorials/KDD 2017.ipynb new file mode 100644 index 0000000000..36b99f8ad8 --- /dev/null +++ b/metapy/tutorials/KDD 2017.ipynb @@ -0,0 +1,4144 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "# Part 1: Feature Engineering for Text Data with MeTA" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "In this part of the tutorial, we'll explore how to go from raw text data to feature representations for documents using MeTA. Everything downstream depends on this representation, so it's important that we spend some time talking about the many different ways you can analyze documents into feature representations." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "First, we'll import the `metapy` python bindings." + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "import metapy" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "For reference, this tutorial was written agains the following metapy version:" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'0.2.6'" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "metapy.__version__" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "If you'd like, you can tell MeTA to log to stderr so you can get progress output when running long-running function calls." + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "metapy.log_to_stderr()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's create a document with some content." + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "doc = metapy.index.Document()\n", + "doc.content(\"I said that I can't believe that it only costs $19.95!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "MeTA provides a stream-based interface for performing document tokenization. Each stream starts off with a Tokenizer object, and in most cases you should use the [Unicode standard aware](http://site.icu-project.org) `ICUTokenizer`." + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "tok = metapy.analyzers.ICUTokenizer()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Tokenizers operate on raw text and provide an Iterable that spits out the individual text tokens. Let's try running just the `ICUTokenizer` to see what it does." + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['',\n", + " 'I',\n", + " 'said',\n", + " 'that',\n", + " 'I',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " '']" + ] + }, + "execution_count": 90, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok.set_content(doc.content()) # this could be any string\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "One thing that you likely immediately notice is the insertion of these pseudo-XML looking `` and `` tags. These are called \"sentence boundary tags\". As a side-effect, a default-construted `ICUTokenizer` discovers the sentences in a document by delimiting them with the sentence boundary tags. Let's try tokenizing a multi-sentence document to see what that looks like." + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['',\n", + " 'I',\n", + " 'said',\n", + " 'that',\n", + " 'I',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " '',\n", + " '',\n", + " 'I',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '$',\n", + " '30',\n", + " 'before',\n", + " '.',\n", + " '']" + ] + }, + "execution_count": 91, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "doc.content(\"I said that I can't believe that it only costs $19.95! I could only find it for more than $30 before.\")\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Most of the information retrieval techniques you have likely been learning about in this class don't need to concern themselves with finding the boundaries between separate sentences in a document, but later today we'll explore a scenario where this might matter more.\n", + "\n", + "Let's pass a flag to the `ICUTokenizer` constructor to disable sentence boundary tags for now." + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['I',\n", + " 'said',\n", + " 'that',\n", + " 'I',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " 'I',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '$',\n", + " '30',\n", + " 'before',\n", + " '.']" + ] + }, + "execution_count": 92, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.ICUTokenizer(suppress_tags=True)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "I mentioned earlier that MeTA treats tokenization as a *streaming* process, and that it *starts* with a tokenizer. As you've learned, for optimal search performance it's often beneficial to modify the raw underlying tokens of a document, and thus change its representation, before adding it to an inverted index structure for searching.\n", + "\n", + "The \"intermediate\" steps in the tokenization stream are represented with objects called Filters. Each filter consumes the content of a previous filter (or a tokenizer) and modifies the tokens coming out of the stream in some way.\n", + "\n", + "Let's start by using a simple filter that can help eliminate a lot of noise that we might encounter when tokenizing web documents: a `LengthFilter`." + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['said',\n", + " 'that',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '19.95',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '30',\n", + " 'before']" + ] + }, + "execution_count": 93, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.LengthFilter(tok, min=2, max=30)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Here, we can see that the `LengthFilter` is consuming our original `ICUTokenizer`. It modifies the token stream by only emitting tokens that are of a minimum length of 2 and a maximum length of 30. This can get rid of a lot of punctuation tokens, but also excessively long tokens such as URLs." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Another common trick is to remove stopwords. (Can anyone tell me what a stopword is?) In MeTA, this is done using a `ListFilter`." + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "File ‘lemur-stopwords.txt’ already there; not retrieving.\r\n", + "\r\n" + ] + }, + { + "data": { + "text/plain": [ + "[\"can't\", 'believe', 'costs', '19.95', 'find', '30']" + ] + }, + "execution_count": 94, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "!wget -nc https://raw.githubusercontent.com/meta-toolkit/meta/master/data/lemur-stopwords.txt\n", + "\n", + "tok = metapy.analyzers.ListFilter(tok, \"lemur-stopwords.txt\", metapy.analyzers.ListFilter.Type.Reject)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Here we've downloaded a common list of stopwords obtained from the [Lemur project](http://lemurproject.org) and created a `ListFilter` to reject any tokens that occur in that list of words.\n", + "\n", + "You can see how much of a difference removing stopwords can make on the size of a document's token stream! This translates to a lot of space savings in the inverted index as well." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Another common filter that people use is called a stemmer, or lemmatizer. This kind of filter tries to modify individual tokens in such a way that different inflected forms of a word all reduce to the same representation. This lets you, for example, find documents about a \"run\" when you search \"running\" or \"runs\". A common stemmer is the [Porter2 Stemmer](http://snowball.tartarus.org/algorithms/english/stemmer.html), which MeTA has an implementation of. Let's try it!" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[\"can't\", 'believ', 'cost', '19.95', 'find', '30']" + ] + }, + "execution_count": 95, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.Porter2Filter(tok)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Notice how \"believe\" becomes \"believ\" and \"costs\" becomes \"cost\". Stemming can help search by allowing queries to return more matched documents by relaxing what it means for a document to match a query term. Note that it's important to ensure that queries are tokenized in the *exact same way* as your documents were before indexing them. If you ignore this, your query is unlikely to contain the raw token \"believ\" and you'll miss a lot of results." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Finally, after you've got the token stream configured the way you'd like, it's time to analyze the document by consuming each token from its token stream and performing some actions based on these tokens. In the simplest case, which often is enough for \"good enough\" search results, our action can simply be counting how many times these tokens occur.\n", + "\n", + "For clarity, let's switch back to a simpler token stream first. Write me a token stream that tokenizes using the Unicode standard, and then lowercases each token. (Hint: `help(metapy.analyzers)`.)" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['i',\n", + " 'said',\n", + " 'that',\n", + " 'i',\n", + " \"can't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " 'i',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '$',\n", + " '30',\n", + " 'before',\n", + " '.']" + ] + }, + "execution_count": 96, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.ICUTokenizer(suppress_tags=True)\n", + "tok = metapy.analyzers.LowercaseFilter(tok)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's count how often each individual token appears in the stream. You might have called this representation the \"bag of words\" representation, but it is also often called \"unigram word counts\". In MeTA, classes that consume a token stream and emit a document representation are called Analyzers." + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I said that I can't believe that it only costs $19.95! I could only find it for more than $30 before.\n" + ] + }, + { + "data": { + "text/plain": [ + "{'!': 1,\n", + " '$': 2,\n", + " '.': 1,\n", + " '19.95': 1,\n", + " '30': 1,\n", + " 'before': 1,\n", + " 'believe': 1,\n", + " \"can't\": 1,\n", + " 'costs': 1,\n", + " 'could': 1,\n", + " 'find': 1,\n", + " 'for': 1,\n", + " 'i': 3,\n", + " 'it': 2,\n", + " 'more': 1,\n", + " 'only': 2,\n", + " 'said': 1,\n", + " 'than': 1,\n", + " 'that': 2}" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana = metapy.analyzers.NGramWordAnalyzer(1, tok)\n", + "print(doc.content())\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "If you noticed the name of the analyzer, you might have realized that you can count not just individual tokens, but groups of them. \"Unigram\" means \"1-gram\", and we count individual tokens. \"Bigram\" means \"2-gram\", and we count adjacent tokens together as a group. Let's try that now." + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{('!', 'i'): 1,\n", + " ('$', '19.95'): 1,\n", + " ('$', '30'): 1,\n", + " ('19.95', '!'): 1,\n", + " ('30', 'before'): 1,\n", + " ('before', '.'): 1,\n", + " ('believe', 'that'): 1,\n", + " (\"can't\", 'believe'): 1,\n", + " ('costs', '$'): 1,\n", + " ('could', 'only'): 1,\n", + " ('find', 'it'): 1,\n", + " ('for', 'more'): 1,\n", + " ('i', \"can't\"): 1,\n", + " ('i', 'could'): 1,\n", + " ('i', 'said'): 1,\n", + " ('it', 'for'): 1,\n", + " ('it', 'only'): 1,\n", + " ('more', 'than'): 1,\n", + " ('only', 'costs'): 1,\n", + " ('only', 'find'): 1,\n", + " ('said', 'that'): 1,\n", + " ('than', '$'): 1,\n", + " ('that', 'i'): 1,\n", + " ('that', 'it'): 1}" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana = metapy.analyzers.NGramWordAnalyzer(2, tok)\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now the individual \"tokens\" we're counting are pairs of tokens. You can analyze any n-gram of tokens you would like to in this way (and this is a simple way to attempt to support phrase search). Note, however, that as you increase the size of the n-grams you are counting, you are also increasing (exponentially!) the number of possible n-grams you could observe, so there's no free lunch here.\n", + "\n", + "This analysis pipeline feeds both the creation of the `InvertedIndex`, which is used for search applications, and the `ForwardIndex`, which is used for topic modeling and classification applications. For classification, sometimes looking at n-grams of characters is useful." + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{(' ', '$', '1', '9'): 1,\n", + " (' ', '$', '3', '0'): 1,\n", + " (' ', 'I', ' ', 'c'): 2,\n", + " (' ', 'b', 'e', 'f'): 1,\n", + " (' ', 'b', 'e', 'l'): 1,\n", + " (' ', 'c', 'a', 'n'): 1,\n", + " (' ', 'c', 'o', 's'): 1,\n", + " (' ', 'c', 'o', 'u'): 1,\n", + " (' ', 'f', 'i', 'n'): 1,\n", + " (' ', 'f', 'o', 'r'): 1,\n", + " (' ', 'i', 't', ' '): 2,\n", + " (' ', 'm', 'o', 'r'): 1,\n", + " (' ', 'o', 'n', 'l'): 2,\n", + " (' ', 's', 'a', 'i'): 1,\n", + " (' ', 't', 'h', 'a'): 3,\n", + " ('!', ' ', 'I', ' '): 1,\n", + " ('$', '1', '9', '.'): 1,\n", + " ('$', '3', '0', ' '): 1,\n", + " (\"'\", 't', ' ', 'b'): 1,\n", + " ('.', '9', '5', '!'): 1,\n", + " ('0', ' ', 'b', 'e'): 1,\n", + " ('1', '9', '.', '9'): 1,\n", + " ('3', '0', ' ', 'b'): 1,\n", + " ('5', '!', ' ', 'I'): 1,\n", + " ('9', '.', '9', '5'): 1,\n", + " ('9', '5', '!', ' '): 1,\n", + " ('I', ' ', 'c', 'a'): 1,\n", + " ('I', ' ', 'c', 'o'): 1,\n", + " ('I', ' ', 's', 'a'): 1,\n", + " ('a', 'i', 'd', ' '): 1,\n", + " ('a', 'n', ' ', '$'): 1,\n", + " ('a', 'n', \"'\", 't'): 1,\n", + " ('a', 't', ' ', 'I'): 1,\n", + " ('a', 't', ' ', 'i'): 1,\n", + " ('b', 'e', 'f', 'o'): 1,\n", + " ('b', 'e', 'l', 'i'): 1,\n", + " ('c', 'a', 'n', \"'\"): 1,\n", + " ('c', 'o', 's', 't'): 1,\n", + " ('c', 'o', 'u', 'l'): 1,\n", + " ('d', ' ', 'i', 't'): 1,\n", + " ('d', ' ', 'o', 'n'): 1,\n", + " ('d', ' ', 't', 'h'): 1,\n", + " ('e', ' ', 't', 'h'): 2,\n", + " ('e', 'f', 'o', 'r'): 1,\n", + " ('e', 'l', 'i', 'e'): 1,\n", + " ('e', 'v', 'e', ' '): 1,\n", + " ('f', 'i', 'n', 'd'): 1,\n", + " ('f', 'o', 'r', ' '): 1,\n", + " ('f', 'o', 'r', 'e'): 1,\n", + " ('h', 'a', 'n', ' '): 1,\n", + " ('h', 'a', 't', ' '): 2,\n", + " ('i', 'd', ' ', 't'): 1,\n", + " ('i', 'e', 'v', 'e'): 1,\n", + " ('i', 'n', 'd', ' '): 1,\n", + " ('i', 't', ' ', 'f'): 1,\n", + " ('i', 't', ' ', 'o'): 1,\n", + " ('l', 'd', ' ', 'o'): 1,\n", + " ('l', 'i', 'e', 'v'): 1,\n", + " ('l', 'y', ' ', 'c'): 1,\n", + " ('l', 'y', ' ', 'f'): 1,\n", + " ('m', 'o', 'r', 'e'): 1,\n", + " ('n', ' ', '$', '3'): 1,\n", + " ('n', \"'\", 't', ' '): 1,\n", + " ('n', 'd', ' ', 'i'): 1,\n", + " ('n', 'l', 'y', ' '): 2,\n", + " ('o', 'n', 'l', 'y'): 2,\n", + " ('o', 'r', ' ', 'm'): 1,\n", + " ('o', 'r', 'e', ' '): 1,\n", + " ('o', 'r', 'e', '.'): 1,\n", + " ('o', 's', 't', 's'): 1,\n", + " ('o', 'u', 'l', 'd'): 1,\n", + " ('r', ' ', 'm', 'o'): 1,\n", + " ('r', 'e', ' ', 't'): 1,\n", + " ('s', ' ', '$', '1'): 1,\n", + " ('s', 'a', 'i', 'd'): 1,\n", + " ('s', 't', 's', ' '): 1,\n", + " ('t', ' ', 'I', ' '): 1,\n", + " ('t', ' ', 'b', 'e'): 1,\n", + " ('t', ' ', 'f', 'o'): 1,\n", + " ('t', ' ', 'i', 't'): 1,\n", + " ('t', ' ', 'o', 'n'): 1,\n", + " ('t', 'h', 'a', 'n'): 1,\n", + " ('t', 'h', 'a', 't'): 2,\n", + " ('t', 's', ' ', '$'): 1,\n", + " ('u', 'l', 'd', ' '): 1,\n", + " ('v', 'e', ' ', 't'): 1,\n", + " ('y', ' ', 'c', 'o'): 1,\n", + " ('y', ' ', 'f', 'i'): 1}" + ] + }, + "execution_count": 99, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.CharacterTokenizer()\n", + "ana = metapy.analyzers.NGramWordAnalyzer(4, tok)\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Different analyzers can be combined together to create document representations that have many unique perspectives. Once things start to get more complicated, we recommend using a configuration file to specify each of the analyzers you wish to combine for your document representation." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's explore something a little bit different. MeTA also has a natural language processing (NLP) component, which currently supports two major NLP tasks: part-of-speech tagging and syntactic parsing.\n", + "\n", + "(Does anyone know what part-of-speech tagging is?) POS tagging is a task in NLP that involves identifying a type for each word in a sentence. For example, POS tagging can be used to identify all of the nouns in a sentence, or all of the verbs, or adjectives, or... This is useful as first step towards developing an understanding of the meaning of a particular sentence." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "MeTA places its POS tagging component in its \"sequences\" library. Let's play with some sequences first to get an idea of how they work. We'll start of by creating a sequence." + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "seq = metapy.sequence.Sequence()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, we can add individual words to this sequence. Sequences consist of a list of `Observation`s, which are essentially (word, tag) pairs. If we don't yet know the tags for a `Sequence`, we can just add individual words and leave the tags unset. Words are called \"symbols\" in the library terminology." + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(The, ???), (dog, ???), (ran, ???), (across, ???), (the, ???), (park, ???), (., ???)\n" + ] + } + ], + "source": [ + "for word in [\"The\", \"dog\", \"ran\", \"across\", \"the\", \"park\", \".\"]:\n", + " seq.add_symbol(word)\n", + "print(seq)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The printed form of the sequence shows that we do not yet know the tags for each word. Let's fill them in by using a pre-trained POS-tagger model that's distributed with MeTA." + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "File ‘greedy-perceptron-tagger.tar.gz’ already there; not retrieving.\n", + "\n", + "perceptron-tagger/\n", + "perceptron-tagger/feature.mapping.gz\n", + "perceptron-tagger/label.mapping\n", + "perceptron-tagger/tagger.model.gz\n" + ] + } + ], + "source": [ + "!wget -nc https://github.com/meta-toolkit/meta/releases/download/v3.0.1/greedy-perceptron-tagger.tar.gz\n", + "!tar xvf greedy-perceptron-tagger.tar.gz" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " > Loading feature mapping: [================================] 100% ETA 00:00:00 \n", + " \n" + ] + } + ], + "source": [ + "tagger = metapy.sequence.PerceptronTagger(\"perceptron-tagger/\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now let's fill in the missing tags in our sentence based on the best guess this model has." + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(The, DT), (dog, NN), (ran, VBD), (across, IN), (the, DT), (park, NN), (., .)\n" + ] + } + ], + "source": [ + "tagger.tag(seq)\n", + "print(seq)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Each tag indicates the type of a word, and this particular tagger was trained to output the tags present in the [Penn Treebank tagset](https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html).\n", + "\n", + "But what if we want to POS-tag a document?" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I said that I can't believe that it only costs $19.95! I could only find it for more than $30 before.\n" + ] + } + ], + "source": [ + "print(doc.content())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We need a way of going from a document to a list of `Sequence`s, each representing an individual sentence. I'll get you started." + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['',\n", + " 'I',\n", + " 'said',\n", + " 'that',\n", + " 'I',\n", + " 'ca',\n", + " \"n't\",\n", + " 'believe',\n", + " 'that',\n", + " 'it',\n", + " 'only',\n", + " 'costs',\n", + " '$',\n", + " '19.95',\n", + " '!',\n", + " '',\n", + " '',\n", + " 'I',\n", + " 'could',\n", + " 'only',\n", + " 'find',\n", + " 'it',\n", + " 'for',\n", + " 'more',\n", + " 'than',\n", + " '$',\n", + " '30',\n", + " 'before',\n", + " '.',\n", + " '']" + ] + }, + "execution_count": 106, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.ICUTokenizer() # keep sentence boundaries!\n", + "tok = metapy.analyzers.PennTreebankNormalizer(tok)\n", + "tok.set_content(doc.content())\n", + "[token for token in tok]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "(Notice that the `PennTreebankNormalizer` modifies some tokens to better match the conventions of the Penn Treebank training data. This should help improve performance a little.)\n", + "\n", + "Now, write me a function that can take a token stream that contains sentence boundary tags and returns a list of `Sequence` objects. Don't include the sentence boundary tags in the actual `Sequence` objects." + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "def extract_sequences(tok):\n", + " sequences = []\n", + " for token in tok:\n", + " if token == '':\n", + " sequences.append(metapy.sequence.Sequence())\n", + " elif token != '':\n", + " sequences[-1].add_symbol(token) \n", + " return sequences" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(I, PRP), (said, VBD), (that, IN), (I, PRP), (ca, MD), (n't, RB), (believe, VB), (that, IN), (it, PRP), (only, RB), (costs, VBZ), ($, $), (19.95, CD), (!, .)\n", + "(I, PRP), (could, MD), (only, RB), (find, VB), (it, PRP), (for, IN), (more, JJR), (than, IN), ($, $), (30, CD), (before, IN), (., .)\n" + ] + } + ], + "source": [ + "tok.set_content(doc.content())\n", + "for seq in extract_sequences(tok):\n", + " tagger.tag(seq)\n", + " print(seq)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "This is still a rather shallow understanding of these sentences. The next major leap is to parse these sequences of POS-tagged words to obtain a tree for each sentence. These trees, in our case, will represent the hierarchical phrase structure of a single sentence by grouping together tokens that belong to one phrase together, and showing how small phrases combine into larger phrases, and eventually a sentence.\n", + "\n", + "Let's try parsing the sentences in our document using a pre-tranned constituency parser that's distributed with MeTA." + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "File ‘greedy-constituency-parser.tar.gz’ already there; not retrieving.\n", + "\n", + "parser/\n", + "parser/parser.trans.gz\n", + "parser/parser.model.gz\n" + ] + } + ], + "source": [ + "!wget -nc https://github.com/meta-toolkit/meta/releases/download/v3.0.1/greedy-constituency-parser.tar.gz\n", + "!tar xvf greedy-constituency-parser.tar.gz" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "parser = metapy.parser.Parser(\"parser/\")" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I could only find it for more than $ 30 before .\n", + "(I, PRP), (could, MD), (only, RB), (find, VB), (it, PRP), (for, IN), (more, JJR), (than, IN), ($, $), (30, CD), (before, IN), (., .)\n", + "(ROOT\n", + " (S\n", + " (NP (PRP I))\n", + " (VP\n", + " (MD could)\n", + " (ADVP (RB only))\n", + " (VP\n", + " (VB find)\n", + " (NP (PRP it))\n", + " (PP\n", + " (IN for)\n", + " (NP\n", + " (QP\n", + " (JJR more)\n", + " (IN than)\n", + " ($ $)\n", + " (CD 30))))\n", + " (ADVP (IN before))))\n", + " (. .)))\n", + "\n" + ] + } + ], + "source": [ + "print(' '.join([obs.symbol for obs in seq]))\n", + "print(seq)\n", + "tree = parser.parse(seq)\n", + "print(tree.pretty_str())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "(You can also play with this with a [prettier online demo](https://meta-toolkit.org/nlp-demo.html).)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can now parse all of the sentences in our document." + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(ROOT\n", + " (S\n", + " (NP (PRP I))\n", + " (VP\n", + " (VBD said)\n", + " (SBAR\n", + " (IN that)\n", + " (S\n", + " (NP (PRP I))\n", + " (VP\n", + " (MD ca)\n", + " (RB n't)\n", + " (VP\n", + " (VB believe)\n", + " (SBAR\n", + " (IN that)\n", + " (S\n", + " (NP (PRP it))\n", + " (ADVP (RB only))\n", + " (VP\n", + " (VBZ costs)\n", + " (NP\n", + " ($ $)\n", + " (CD 19.95))))))))))\n", + " (. !)))\n", + "\n", + "(ROOT\n", + " (S\n", + " (NP (PRP I))\n", + " (VP\n", + " (MD could)\n", + " (ADVP (RB only))\n", + " (VP\n", + " (VB find)\n", + " (NP (PRP it))\n", + " (PP\n", + " (IN for)\n", + " (NP\n", + " (QP\n", + " (JJR more)\n", + " (IN than)\n", + " ($ $)\n", + " (CD 30))))\n", + " (ADVP (IN before))))\n", + " (. .)))\n", + "\n" + ] + } + ], + "source": [ + "tok.set_content(doc.content())\n", + "for seq in extract_sequences(tok):\n", + " tagger.tag(seq)\n", + " print(parser.parse(seq).pretty_str())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now that we know how POS-tagging and syntactic parsing works in MeTA, let's explore some features that we can add to our document representations using these techniques.\n", + "\n", + "The simplest feature we can imagine that uses the POS-taggged sequences might be n-grams of POS tags. (As a quick detour, we'll need to download and extract a CRF-based POS tagging model.)" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "File ‘crf.tar.gz’ already there; not retrieving.\r\n", + "\r\n" + ] + } + ], + "source": [ + "!wget -nc https://github.com/meta-toolkit/meta/releases/download/v3.0.1/crf.tar.gz\n", + "!tar xf crf.tar.gz" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, we can use the following analysis pipeline to get n-gram POS tag features by using the `NGRamPOSAnalyzer`:" + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " > Loading feature mapping: [================================] 100% ETA 00:00:00 \n", + " \n" + ] + }, + { + "data": { + "text/plain": [ + "{('$', 'CD'): 2,\n", + " ('CD', '.'): 1,\n", + " ('CD', 'RB'): 1,\n", + " ('IN', '$'): 1,\n", + " ('IN', 'JJR'): 1,\n", + " ('IN', 'PRP'): 2,\n", + " ('JJR', 'IN'): 1,\n", + " ('MD', 'RB'): 2,\n", + " ('PRP', 'IN'): 1,\n", + " ('PRP', 'MD'): 2,\n", + " ('PRP', 'RB'): 1,\n", + " ('PRP', 'VBD'): 1,\n", + " ('RB', '.'): 1,\n", + " ('RB', 'VB'): 2,\n", + " ('RB', 'VBZ'): 1,\n", + " ('VB', 'IN'): 1,\n", + " ('VB', 'PRP'): 1,\n", + " ('VBD', 'IN'): 1,\n", + " ('VBZ', '$'): 1}" + ] + }, + "execution_count": 114, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tok = metapy.analyzers.ICUTokenizer()\n", + "tok = metapy.analyzers.PennTreebankNormalizer(tok)\n", + "ana = metapy.analyzers.NGramPOSAnalyzer(2, tok, 'crf')\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can also parse the sentences in the document and extract a number of different structural features from the parse trees using a `TreeAnalyzer`." + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " > Loading feature mapping: [================================] 100% ETA 00:00:00 \n", + " \n" + ] + } + ], + "source": [ + "ana = metapy.analyzers.TreeAnalyzer(tok, 'perceptron-tagger', 'parser')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The `TreeAnalyzer` has a function `add()` that takes `TreeFeaturizer` subclasses. Conceptually, the extraction of structural features from parse trees looks something like this:\n", + "\n", + "1. The tokenizer is run until a full sentence is read.\n", + "2. The greedy perceptron tagger is run to tag the words in the sentence.\n", + "3. The shift-reduce constituency parser is run to produce a parse tree.\n", + "4. Each `TreeFeaturizer` that is part of the `TreeAnalayzer` is run over the parse tree to produce features.\n", + "\n", + "This process is repeated for each sentence found in the document.\n", + "\n", + "Let's try adding just one `TreeFeaturizer` to the analyzer for now and see what features we get." + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'depth-12': 1, 'depth-8': 1}" + ] + }, + "execution_count": 116, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana.add(metapy.analyzers.DepthFeaturizer())\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The featurizer we used here simply extracts the depth of each subtree and creates a new feature for each depth encountered.\n", + "\n", + "We can also see some features that utilize the structure of the trees if we use some different `TreeFeaturizer`s." + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " > Loading feature mapping: [================================] 100% ETA 00:00:00 \n", + " \n" + ] + }, + { + "data": { + "text/plain": [ + "{'subtree-($)': 2,\n", + " 'subtree-(.)': 2,\n", + " 'subtree-(ADVP (IN))': 1,\n", + " 'subtree-(ADVP (RB))': 2,\n", + " 'subtree-(CD)': 2,\n", + " 'subtree-(IN)': 5,\n", + " 'subtree-(JJR)': 1,\n", + " 'subtree-(MD)': 2,\n", + " 'subtree-(NP ($) (CD))': 1,\n", + " 'subtree-(NP (PRP))': 5,\n", + " 'subtree-(NP (QP))': 1,\n", + " 'subtree-(PP (IN) (NP))': 1,\n", + " 'subtree-(PRP)': 5,\n", + " 'subtree-(QP (JJR) (IN) ($) (CD))': 1,\n", + " 'subtree-(RB)': 3,\n", + " 'subtree-(ROOT (S))': 2,\n", + " 'subtree-(S (NP) (ADVP) (VP))': 1,\n", + " 'subtree-(S (NP) (VP) (.))': 2,\n", + " 'subtree-(S (NP) (VP))': 1,\n", + " 'subtree-(SBAR (IN) (S))': 2,\n", + " 'subtree-(VB)': 2,\n", + " 'subtree-(VBD)': 1,\n", + " 'subtree-(VBZ)': 1,\n", + " 'subtree-(VP (MD) (ADVP) (VP))': 1,\n", + " 'subtree-(VP (MD) (RB) (VP))': 1,\n", + " 'subtree-(VP (VB) (NP) (PP) (ADVP))': 1,\n", + " 'subtree-(VP (VB) (SBAR))': 1,\n", + " 'subtree-(VP (VBD) (SBAR))': 1,\n", + " 'subtree-(VP (VBZ) (NP))': 1}" + ] + }, + "execution_count": 117, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana = metapy.analyzers.TreeAnalyzer(tok, 'perceptron-tagger', 'parser')\n", + "ana.add(metapy.analyzers.SubtreeFeaturizer())\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The `SubtreeFeaturizer` creates a new feature for each unique subtree seen in the data, to a depth of 1. This can create quite a lot of features, but describes how the sentence is decomposed structureally. This kind of feature is also known as a \"rewrite rule\" feature.\n", + "\n", + "We can also ignore the labels of the subtrees entirely and just extract their structure if we use a `SkeletonFeaturizer`." + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " > Loading feature mapping: [================================] 100% ETA 00:00:00 \n", + " \n" + ] + }, + { + "data": { + "text/plain": [ + "{'(((())(()(()((())(()()(()(()((())(())(()(()())))))))))()))': 1,\n", + " '(((())(()(())(()(())(()((()()()())))(())))()))': 1,\n", + " '((()()()()))': 1,\n", + " '((())(()(()((())(()()(()(()((())(())(()(()())))))))))())': 1,\n", + " '((())(()(())(()(())(()((()()()())))(())))())': 1,\n", + " '((())(()()(()(()((())(())(()(()())))))))': 1,\n", + " '((())(())(()(()())))': 1,\n", + " '(()((()()()())))': 1,\n", + " '(()((())(()()(()(()((())(())(()(()()))))))))': 1,\n", + " '(()((())(())(()(()()))))': 1,\n", + " '(()(()((())(()()(()(()((())(())(()(()())))))))))': 1,\n", + " '(()(()((())(())(()(()())))))': 1,\n", + " '(()(()()))': 1,\n", + " '(()(())(()((()()()())))(()))': 1,\n", + " '(()(())(()(())(()((()()()())))(())))': 1,\n", + " '(()()(()(()((())(())(()(()()))))))': 1,\n", + " '(()()()())': 1,\n", + " '(()())': 1,\n", + " '(())': 8,\n", + " '()': 26}" + ] + }, + "execution_count": 118, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana = metapy.analyzers.TreeAnalyzer(tok, 'perceptron-tagger', 'parser')\n", + "ana.add(metapy.analyzers.SkeletonFeaturizer())\n", + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Play with the other featurizers to see what they do!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "In practice, it is often beneficial to combine multiple feature sets together. We can do this with a `MultiAnalyzer`. Let's combine unigram words, bigram POS tags, and rewrite rules for our document feature representation.\n", + "\n", + "We can certainly do this programmatically, but doing so can become tedious quite quickly. Instead, let's use MeTA's configuration file format to specify our analyzer, which we can then load in one line of code. MeTA uses [TOML](https://en.wikipedia.org/wiki/TOML) configuration files for all of its configuration. If you haven't heard of TOML before, don't panic! It's a very simple, readable format that looks like old school INI files.\n", + "\n", + "Let's create a simple configuration file now." + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "config = \"\"\"stop-words = \"lemur-stopwords.txt\"\n", + "\n", + "[[analyzers]]\n", + "method = \"ngram-word\"\n", + "ngram = 1\n", + "filter = \"default-unigram-chain\"\n", + "\n", + "[[analyzers]]\n", + "method = \"ngram-pos\"\n", + "ngram = 2\n", + "filter = [{type = \"icu-tokenizer\"}, {type = \"ptb-normalizer\"}]\n", + "crf-prefix = \"crf\"\n", + "\n", + "[[analyzers]]\n", + "method = \"tree\"\n", + "filter = [{type = \"icu-tokenizer\"}, {type = \"ptb-normalizer\"}]\n", + "features = [\"subtree\"]\n", + "tagger = \"perceptron-tagger/\"\n", + "parser = \"parser/\"\n", + "\"\"\"\n", + "with open('config.toml', 'w') as f:\n", + " f.write(config)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Each `[[analyzers]]` block defines another analyzer to combine for our feature representation. Since \"ngram-word\" is such a common analyzer, we have defined some default filter chains that can be used with shortcuts. \"default-unigram-chain\" is a filter chain suitable for unigram words; \"default-chain\" is a filter chain suitable for bigram words and above.\n", + "\n", + "We can now load an analyzer from this configuration file like so:" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " > Loading feature mapping: [================================] 100% ETA 00:00:00 \n", + " \n", + " > Loading feature mapping: [================================] 100% ETA 00:00:00 \n", + " \n" + ] + } + ], + "source": [ + "ana = metapy.analyzers.load('config.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now let's see what we get!" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'$_CD': 2,\n", + " 'CD_.': 1,\n", + " 'CD_RB': 1,\n", + " 'IN_$': 1,\n", + " 'IN_JJR': 1,\n", + " 'IN_PRP': 2,\n", + " 'JJR_IN': 1,\n", + " 'MD_RB': 2,\n", + " 'PRP_IN': 1,\n", + " 'PRP_MD': 2,\n", + " 'PRP_RB': 1,\n", + " 'PRP_VBD': 1,\n", + " 'RB_.': 1,\n", + " 'RB_VB': 2,\n", + " 'RB_VBZ': 1,\n", + " 'VBD_IN': 1,\n", + " 'VBZ_$': 1,\n", + " 'VB_IN': 1,\n", + " 'VB_PRP': 1,\n", + " 'believ': 1,\n", + " \"can't\": 1,\n", + " 'cost': 1,\n", + " 'find': 1,\n", + " 'subtree-($)': 2,\n", + " 'subtree-(.)': 2,\n", + " 'subtree-(ADVP (IN))': 1,\n", + " 'subtree-(ADVP (RB))': 2,\n", + " 'subtree-(CD)': 2,\n", + " 'subtree-(IN)': 5,\n", + " 'subtree-(JJR)': 1,\n", + " 'subtree-(MD)': 2,\n", + " 'subtree-(NP ($) (CD))': 1,\n", + " 'subtree-(NP (PRP))': 5,\n", + " 'subtree-(NP (QP))': 1,\n", + " 'subtree-(PP (IN) (NP))': 1,\n", + " 'subtree-(PRP)': 5,\n", + " 'subtree-(QP (JJR) (IN) ($) (CD))': 1,\n", + " 'subtree-(RB)': 3,\n", + " 'subtree-(ROOT (S))': 2,\n", + " 'subtree-(S (NP) (ADVP) (VP))': 1,\n", + " 'subtree-(S (NP) (VP) (.))': 2,\n", + " 'subtree-(S (NP) (VP))': 1,\n", + " 'subtree-(SBAR (IN) (S))': 2,\n", + " 'subtree-(VB)': 2,\n", + " 'subtree-(VBD)': 1,\n", + " 'subtree-(VBZ)': 1,\n", + " 'subtree-(VP (MD) (ADVP) (VP))': 1,\n", + " 'subtree-(VP (MD) (RB) (VP))': 1,\n", + " 'subtree-(VP (VB) (NP) (PP) (ADVP))': 1,\n", + " 'subtree-(VP (VB) (SBAR))': 1,\n", + " 'subtree-(VP (VBD) (SBAR))': 1,\n", + " 'subtree-(VP (VBZ) (NP))': 1}" + ] + }, + "execution_count": 121, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ana.analyze(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "# Part 2: Information Retrieval with MeTA" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "In this part of the tutorial, we'll play with the first major application of MeTA: search engines. We will be having the first contest in this part! Once we finish going through how to create an inverted index, search it, and evaluate retrieval algorithms, I will give you instructions on how to participate in the competition. There will be a leader board to keep track of the best submissions, and I intend on leaving it running until the end of the conference for people to play around with." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Let's get a publicly available retrieval dataset with relevance judgments first." + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2017-08-16 19:19:41-- https://meta-toolkit.org/data/2016-11-10/cranfield.tar.gz\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving meta-toolkit.org... 50.116.41.177, 2600:3c02::f03c:91ff:feae:b777\n", + "Connecting to meta-toolkit.org|50.116.41.177|:443... connected.\n", + "HTTP request sent, awaiting response... 304 Not Modified\n", + "File ‘cranfield.tar.gz’ not modified on server. Omitting download.\n", + "\n" + ] + } + ], + "source": [ + "!wget -N https://meta-toolkit.org/data/2016-11-10/cranfield.tar.gz\n", + "!tar xf cranfield.tar.gz" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We're going to add a flag to our corpus' configuration file to force it to store full text for later." + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "with open('cranfield/tutorial.toml', 'w') as f:\n", + " f.write('type = \"line-corpus\"\\n')\n", + " f.write('store-full-text = true\\n')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's set up a MeTA configuration file up to index the `cranfield` dataset we just downloaded using the default unigram words filter chain." + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "config = \"\"\"prefix = \".\" # tells MeTA where to search for datasets\n", + "\n", + "dataset = \"cranfield\" # a subfolder under the prefix directory\n", + "corpus = \"tutorial.toml\" # a configuration file for the corpus specifying its format & additional args\n", + "\n", + "index = \"cranfield-idx\" # subfolder of the current working directory to place index files\n", + "\n", + "query-judgements = \"cranfield/cranfield-qrels.txt\" # file containing the relevance judgments for this dataset\n", + "\n", + "stop-words = \"lemur-stopwords.txt\"\n", + "\n", + "[[analyzers]]\n", + "method = \"ngram-word\"\n", + "ngram = 1\n", + "filter = \"default-unigram-chain\"\n", + "\"\"\"\n", + "with open('cranfield-config.toml', 'w') as f:\n", + " f.write(config)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Let's index our data using the `InvertedIndex` format. In a search engine, we want to quickly determine what documents mention a specific query term, so the `InvertedIndex` stores a mapping from term to a list of documents that contain that term (along with how many times they do)." + ] + }, + { + "cell_type": "code", + "execution_count": 125, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1502921982: [info] Loading index from disk: cranfield-idx/inv (/tmp/pip-bneszy3v-build/deps/meta/src/index/inverted_index.cpp:171)\n", + "1502921982: [info] Loading index from disk: cranfield-idx/inv (/tmp/pip-bneszy3v-build/deps/meta/src/index/inverted_index.cpp:171)\n" + ] + } + ], + "source": [ + "inv_idx = metapy.index.make_inverted_index('cranfield-config.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "This may take a minute at first, since the index needs to be built. Subsequent calls to `make_inverted_index` with this config file will simply load the index, which will not take any time.\n", + "\n", + "Here's how we can interact with the index object:" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1400" + ] + }, + "execution_count": 126, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "inv_idx.num_docs()" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4137" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "inv_idx.unique_terms()" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "87.17857360839844" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "inv_idx.avg_doc_length()" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "122050" + ] + }, + "execution_count": 129, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "inv_idx.total_corpus_terms()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Let's search our index. We'll start by creating a ranker:" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "ranker = metapy.index.OkapiBM25()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now we need a query. Let's create an example query." + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "query = metapy.index.Document()\n", + "query.content(\"flow equilibrium\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now we can use this to search our index like so:" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(235, 6.424363136291504),\n", + " (1009, 6.096038818359375),\n", + " (1229, 5.877272129058838),\n", + " (1251, 5.866937160491943),\n", + " (316, 5.859640121459961)]" + ] + }, + "execution_count": 132, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "top_docs = ranker.score(inv_idx, query, num_results=5)\n", + "top_docs" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We are returned a ranked list of *(doc_id, score)* pairs. The scores are from the ranker, which in this case was Okapi BM25. Since the `tutorial.toml` file we created for the cranfield dataset has `store-full-text = true`, we can verify the content of our top documents by inspecting the document metadata field \"content\"." + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1. criteria for thermodynamic equilibrium in gas flow . when gases flow at high velocity, the rates of internal processes may not be fast enough to maintain thermodynamic equilibrium . by defining quasi-equilibrium in flow as the condition in which the...\n", + "\n", + "2. free-flight measurements of the static and dynamic . air-flow properties in nozzles were calculated and charted for equilibrium flow and two types of frozen flows . in one type of frozen flow, air was assumed to be in equilibrium from the nozzle res...\n", + "\n", + "3. hypersonic nozzle expansion of air with atom recombination present . an experimental investigation on the expansion of high- temperature, high-pressure air to hypersonic flow mach numbers in a conical nozzle of a hypersonic shock tunnel has been carr...\n", + "\n", + "4. on the approach to chemical and vibrational equilibrium behind a strong normal shock wave . the concurrent approach to chemical and vibrational equilibrium of a pure diatomic gas passing through a strong normal shock wave is investigated . it is dem...\n", + "\n", + "5. non-equilibrium flow of an ideal dissociating gas . the theory of an'ideal dissociating'gas developed by lighthill/1957/for conditions of thermodynamic equilibrium is extended to non-equilibrium conditions by postulating a simple rate equation for th...\n", + "\n" + ] + } + ], + "source": [ + "for num, (d_id, _) in enumerate(top_docs):\n", + " content = inv_idx.metadata(d_id).get('content')\n", + " print(\"{}. {}...\\n\".format(num + 1, content[0:250]))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Since we have the queries file and relevance judgements, we can do an IR evaluation." + ] + }, + { + "cell_type": "code", + "execution_count": 134, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "ev = metapy.index.IREval('cranfield-config.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We will loop over the queries file and add each result to the `IREval` object `ev`." + ] + }, + { + "cell_type": "code", + "execution_count": 135, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Query 1 average precision: 0.24166666666666664\n", + "Query 2 average precision: 0.4196428571428571\n", + "Query 3 average precision: 0.6383928571428572\n", + "Query 4 average precision: 0.25\n", + "Query 5 average precision: 0.3333333333333333\n", + "Query 6 average precision: 0.125\n", + "Query 7 average precision: 0.11666666666666665\n", + "Query 8 average precision: 0.1\n", + "Query 9 average precision: 0.6388888888888888\n", + "Query 10 average precision: 0.0625\n", + "Query 11 average precision: 0.09285714285714286\n", + "Query 12 average precision: 0.18\n", + "Query 13 average precision: 0.0\n", + "Query 14 average precision: 0.5\n", + "Query 15 average precision: 1.0\n", + "Query 16 average precision: 0.16666666666666666\n", + "Query 17 average precision: 0.08333333333333333\n", + "Query 18 average precision: 0.3333333333333333\n", + "Query 19 average precision: 0.0\n", + "Query 20 average precision: 0.4302469135802469\n", + "Query 21 average precision: 0.0\n", + "Query 22 average precision: 0.0\n", + "Query 23 average precision: 0.19952380952380952\n", + "Query 24 average precision: 0.3333333333333333\n", + "Query 25 average precision: 0.6507936507936507\n", + "Query 26 average precision: 0.19444444444444442\n", + "Query 27 average precision: 0.12962962962962962\n", + "Query 28 average precision: 0.0\n", + "Query 29 average precision: 0.35\n", + "Query 30 average precision: 0.023809523809523808\n", + "Query 31 average precision: 0.0\n", + "Query 32 average precision: 0.1111111111111111\n", + "Query 33 average precision: 0.6388888888888888\n", + "Query 34 average precision: 0.1111111111111111\n", + "Query 35 average precision: 0.0\n", + "Query 36 average precision: 0.5\n", + "Query 37 average precision: 0.0\n", + "Query 38 average precision: 0.0\n", + "Query 39 average precision: 0.1\n", + "Query 40 average precision: 0.045\n", + "Query 41 average precision: 0.6666666666666666\n", + "Query 42 average precision: 0.16714285714285712\n", + "Query 43 average precision: 0.4583333333333333\n", + "Query 44 average precision: 0.0\n", + "Query 45 average precision: 0.1\n", + "Query 46 average precision: 0.4058333333333334\n", + "Query 47 average precision: 0.27341269841269844\n", + "Query 48 average precision: 0.17666666666666667\n", + "Query 49 average precision: 0.1\n", + "Query 50 average precision: 0.05555555555555555\n", + "Query 51 average precision: 0.4730952380952381\n", + "Query 52 average precision: 0.47916666666666663\n", + "Query 53 average precision: 0.15222222222222223\n", + "Query 54 average precision: 0.05555555555555555\n", + "Query 55 average precision: 0.19444444444444445\n", + "Query 56 average precision: 0.1\n", + "Query 57 average precision: 0.03333333333333333\n", + "Query 58 average precision: 0.0380952380952381\n", + "Query 59 average precision: 0.027777777777777776\n", + "Query 60 average precision: 0.42000000000000004\n", + "Query 61 average precision: 0.5638888888888889\n", + "Query 62 average precision: 0.0\n", + "Query 63 average precision: 0.0\n", + "Query 64 average precision: 0.5\n", + "Query 65 average precision: 0.24\n", + "Query 66 average precision: 0.02857142857142857\n", + "Query 67 average precision: 0.575\n", + "Query 68 average precision: 0.04\n", + "Query 69 average precision: 0.02857142857142857\n", + "Query 70 average precision: 0.05\n", + "Query 71 average precision: 0.017857142857142856\n", + "Query 72 average precision: 0.12\n", + "Query 73 average precision: 0.4680952380952381\n", + "Query 74 average precision: 0.020833333333333332\n", + "Query 75 average precision: 0.0\n", + "Query 76 average precision: 0.07142857142857142\n", + "Query 77 average precision: 0.2333333333333333\n", + "Query 78 average precision: 0.7222222222222222\n", + "Query 79 average precision: 0.0\n", + "Query 80 average precision: 0.0\n", + "Query 81 average precision: 0.75\n", + "Query 82 average precision: 0.24\n", + "Query 83 average precision: 0.0625\n", + "Query 84 average precision: 0.3\n", + "Query 85 average precision: 0.25\n", + "Query 86 average precision: 0.5833333333333333\n", + "Query 87 average precision: 0.0\n", + "Query 88 average precision: 0.6496031746031746\n", + "Query 89 average precision: 0.05555555555555555\n", + "Query 90 average precision: 0.15607142857142856\n", + "Query 91 average precision: 0.2577160493827161\n", + "Query 92 average precision: 0.5014285714285714\n", + "Query 93 average precision: 0.5\n", + "Query 94 average precision: 0.5264285714285715\n", + "Query 95 average precision: 0.5\n", + "Query 96 average precision: 0.38976190476190475\n", + "Query 97 average precision: 0.15416666666666665\n", + "Query 98 average precision: 0.0\n", + "Query 99 average precision: 0.18333333333333335\n", + "Query 100 average precision: 0.16666666666666663\n", + "Query 101 average precision: 0.6958333333333333\n", + "Query 102 average precision: 0.3214285714285714\n", + "Query 103 average precision: 0.0\n", + "Query 104 average precision: 0.06666666666666667\n", + "Query 105 average precision: 0.3833333333333333\n", + "Query 106 average precision: 0.38571428571428573\n", + "Query 107 average precision: 0.17261904761904762\n", + "Query 108 average precision: 0.5901360544217686\n", + "Query 109 average precision: 0.0\n", + "Query 110 average precision: 0.125\n", + "Query 111 average precision: 0.08333333333333333\n", + "Query 112 average precision: 0.25\n", + "Query 113 average precision: 0.08333333333333333\n", + "Query 114 average precision: 0.0\n", + "Query 115 average precision: 0.05\n", + "Query 116 average precision: 0.05\n", + "Query 117 average precision: 0.0\n", + "Query 118 average precision: 0.21666666666666667\n", + "Query 119 average precision: 1.0\n", + "Query 120 average precision: 0.39589947089947086\n", + "Query 121 average precision: 0.369047619047619\n", + "Query 122 average precision: 0.21164021164021163\n", + "Query 123 average precision: 0.0\n", + "Query 124 average precision: 0.0\n", + "Query 125 average precision: 0.2095238095238095\n", + "Query 126 average precision: 0.20833333333333331\n", + "Query 127 average precision: 0.05\n", + "Query 128 average precision: 0.0\n", + "Query 129 average precision: 0.369047619047619\n", + "Query 130 average precision: 0.5\n", + "Query 131 average precision: 0.10238095238095238\n", + "Query 132 average precision: 0.48476190476190484\n", + "Query 133 average precision: 0.05215419501133787\n", + "Query 134 average precision: 0.25\n", + "Query 135 average precision: 0.3839285714285714\n", + "Query 136 average precision: 0.3333333333333333\n", + "Query 137 average precision: 0.225\n", + "Query 138 average precision: 0.1\n", + "Query 139 average precision: 0.0\n", + "Query 140 average precision: 0.13888888888888887\n", + "Query 141 average precision: 0.075\n", + "Query 142 average precision: 0.0\n", + "Query 143 average precision: 0.7\n", + "Query 144 average precision: 0.28439153439153436\n", + "Query 145 average precision: 0.21995464852607707\n", + "Query 146 average precision: 0.5833333333333333\n", + "Query 147 average precision: 0.22666666666666666\n", + "Query 148 average precision: 0.16666666666666666\n", + "Query 149 average precision: 0.24861111111111106\n", + "Query 150 average precision: 0.8333333333333333\n", + "Query 151 average precision: 0.0\n", + "Query 152 average precision: 0.0\n", + "Query 153 average precision: 0.2738095238095238\n", + "Query 154 average precision: 0.8333333333333333\n", + "Query 155 average precision: 0.125\n", + "Query 156 average precision: 0.5607142857142857\n", + "Query 157 average precision: 0.29861111111111105\n", + "Query 158 average precision: 0.3625\n", + "Query 159 average precision: 0.043402777777777776\n", + "Query 160 average precision: 0.1\n", + "Query 161 average precision: 0.5\n", + "Query 162 average precision: 0.10416666666666666\n", + "Query 163 average precision: 0.24444444444444446\n", + "Query 164 average precision: 0.31805555555555554\n", + "Query 165 average precision: 0.5833333333333333\n", + "Query 166 average precision: 0.013888888888888888\n", + "Query 167 average precision: 0.5\n", + "Query 168 average precision: 0.08333333333333333\n", + "Query 169 average precision: 0.25\n", + "Query 170 average precision: 0.5694444444444444\n", + "Query 171 average precision: 0.6388888888888888\n", + "Query 172 average precision: 0.6791666666666667\n", + "Query 173 average precision: 1.0\n", + "Query 174 average precision: 0.03333333333333333\n", + "Query 175 average precision: 0.02\n", + "Query 176 average precision: 0.0\n", + "Query 177 average precision: 0.5888888888888889\n", + "Query 178 average precision: 0.3333333333333333\n", + "Query 179 average precision: 0.29166666666666663\n", + "Query 180 average precision: 0.33095238095238094\n", + "Query 181 average precision: 0.2\n", + "Query 182 average precision: 0.5833333333333333\n", + "Query 183 average precision: 0.5580952380952381\n", + "Query 184 average precision: 0.21428571428571427\n", + "Query 185 average precision: 0.6388888888888888\n", + "Query 186 average precision: 0.16619047619047617\n", + "Query 187 average precision: 0.13888888888888887\n", + "Query 188 average precision: 0.3196428571428571\n", + "Query 189 average precision: 0.05952380952380952\n", + "Query 190 average precision: 0.3\n", + "Query 191 average precision: 0.05333333333333333\n", + "Query 192 average precision: 0.5666666666666667\n", + "Query 193 average precision: 0.8282627865961198\n", + "Query 194 average precision: 0.041666666666666664\n", + "Query 195 average precision: 0.05555555555555555\n", + "Query 196 average precision: 0.11666666666666665\n", + "Query 197 average precision: 0.5555555555555555\n", + "Query 198 average precision: 0.44375\n", + "Query 199 average precision: 0.025\n", + "Query 200 average precision: 0.1851851851851852\n", + "Query 201 average precision: 0.3583333333333333\n", + "Query 202 average precision: 0.19166666666666665\n", + "Query 203 average precision: 0.1595238095238095\n", + "Query 204 average precision: 0.0\n", + "Query 205 average precision: 0.75\n", + "Query 206 average precision: 0.2619047619047619\n", + "Query 207 average precision: 0.14444444444444443\n", + "Query 208 average precision: 0.6916666666666668\n", + "Query 209 average precision: 0.05555555555555556\n", + "Query 210 average precision: 0.27777777777777773\n", + "Query 211 average precision: 0.0125\n", + "Query 212 average precision: 0.4891666666666666\n", + "Query 213 average precision: 0.4625\n", + "Query 214 average precision: 0.125\n", + "Query 215 average precision: 0.0\n", + "Query 216 average precision: 0.0\n", + "Query 217 average precision: 0.2\n", + "Query 218 average precision: 0.24285714285714283\n", + "Query 219 average precision: 0.0\n", + "Query 220 average precision: 0.13333333333333333\n", + "Query 221 average precision: 0.275\n", + "Query 222 average precision: 0.5978835978835979\n", + "Query 223 average precision: 0.44166666666666665\n", + "Query 224 average precision: 0.04285714285714286\n", + "Query 225 average precision: 0.1775\n" + ] + } + ], + "source": [ + "num_results = 10\n", + "with open('cranfield/cranfield-queries.txt') as query_file:\n", + " for query_num, line in enumerate(query_file):\n", + " query.content(line.strip())\n", + " results = ranker.score(inv_idx, query, num_results) \n", + " avg_p = ev.avg_p(results, query_num + 1, num_results)\n", + " print(\"Query {} average precision: {}\".format(query_num + 1, avg_p))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Afterwards, we can get the mean average precision of all the queries." + ] + }, + { + "cell_type": "code", + "execution_count": 136, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0.25511867318944054" + ] + }, + "execution_count": 136, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ev.map()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "In the competition, you should try experimenting with different rankers, ranker parameters, tokenization, and filters. What combination can give you the best results?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Lastly, it's possible to define your own ranking function in Python." + ] + }, + { + "cell_type": "code", + "execution_count": 137, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "class SimpleRanker(metapy.index.RankingFunction): \n", + " \"\"\" \n", + " Create a new ranking function in Python that can be used in MeTA. \n", + " \"\"\" \n", + " def __init__(self, some_param=1.0): \n", + " self.param = some_param\n", + " # You *must* invoke the base class __init__() here!\n", + " super(SimpleRanker, self).__init__() \n", + " \n", + " def score_one(self, sd):\n", + " \"\"\"\n", + " You need to override this function to return a score for a single term.\n", + " For fields available in the score_data sd object,\n", + " @see https://meta-toolkit.org/doxygen/structmeta_1_1index_1_1score__data.html\n", + " \"\"\"\n", + " return (self.param + sd.doc_term_count) / (self.param * sd.doc_unique_terms + sd.doc_size)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "**COMPETITION TIME**" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "# Part 3: Document Classification with MeTA" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "In this part of the tutorial, we'll play with the next major application for MeTA: creating classifiers. We will be having the second contest in this part! Once we finish going through how to create a forward index, train classifiers on top of it, and perform classifier evaluation and cross validation, I will give you instructions on how to participate in the competition (it will be similar to the first competition). Again, there will be another leader board to keep track of the best submissions, and I intend on leaving it running until the end of the conference for people to play around with." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Let's switch back to using the `ceeaus` dataset we downloaded before. If you're just joining us, grab it now:" + ] + }, + { + "cell_type": "code", + "execution_count": 138, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2017-08-16 19:19:42-- https://meta-toolkit.org/data/2016-01-26/ceeaus.tar.gz\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving meta-toolkit.org... 50.116.41.177, 2600:3c02::f03c:91ff:feae:b777\n", + "Connecting to meta-toolkit.org|50.116.41.177|:443... connected.\n", + "HTTP request sent, awaiting response... 304 Not Modified\n", + "File ‘ceeaus.tar.gz’ not modified on server. Omitting download.\n", + "\n" + ] + } + ], + "source": [ + "!wget -N https://meta-toolkit.org/data/2016-01-26/ceeaus.tar.gz\n", + "!tar xf ceeaus.tar.gz" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We'll also need our standard stopword list. Grab it now if you don't already have it:" + ] + }, + { + "cell_type": "code", + "execution_count": 139, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2017-08-16 19:19:43-- https://raw.githubusercontent.com/meta-toolkit/meta/master/data/lemur-stopwords.txt\n", + "Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'\n", + "Resolving raw.githubusercontent.com... 151.101.0.133, 151.101.64.133, 151.101.128.133, ...\n", + "Connecting to raw.githubusercontent.com|151.101.0.133|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 2747 (2.7K) [text/plain]\n", + "Saving to: ‘lemur-stopwords.txt’\n", + "\n", + "lemur-stopwords.txt 100%[===================>] 2.68K --.-KB/s in 0s \n", + "\n", + "Last-modified header missing -- time-stamps turned off.\n", + "2017-08-16 19:19:43 (63.8 MB/s) - ‘lemur-stopwords.txt’ saved [2747/2747]\n", + "\n" + ] + } + ], + "source": [ + "!wget -N https://raw.githubusercontent.com/meta-toolkit/meta/master/data/lemur-stopwords.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Let's create our MeTA configuration file for this part of the tutorial. We'll be using standard unigram words for now, but you're strongly encouraged to play with different features for the competition!" + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "config = \"\"\"prefix = \".\"\n", + "dataset = \"ceeaus\"\n", + "corpus = \"line.toml\"\n", + "index = \"ceeaus-idx\"\n", + "stop-words = \"lemur-stopwords.txt\"\n", + "\n", + "[[analyzers]]\n", + "method = \"ngram-word\"\n", + "ngram = 1\n", + "filter = \"default-unigram-chain\"\n", + "\"\"\"\n", + "with open('ceeaus-config.toml', 'w') as f:\n", + " f.write(config)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's index this dataset. Since we are doing classification experiments, we will most likely be concerning ourselves with a `ForwardIndex`, since we want to map document ids to their feature vector representations." + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1502921983: [info] Loading index from disk: ceeaus-idx/fwd (/tmp/pip-bneszy3v-build/deps/meta/src/index/forward_index.cpp:171)\n", + "1502921983: [info] Loading index from disk: ceeaus-idx/fwd (/tmp/pip-bneszy3v-build/deps/meta/src/index/forward_index.cpp:171)\n" + ] + } + ], + "source": [ + "fidx = metapy.index.make_forward_index('ceeaus-config.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Note that the feature set used for classification depends on your settings in the configuration file _at the time of indexing_. If you want to play with different feature sets, remember to change your `analyzer` pipeline in the configuration file, and also to **reindex** your documents!\n", + "\n", + "Here, we've just chosen simple unigram words. This is actually a surprisingly good baseline feature set for many text classification problems.\n", + "\n", + "Now that we have a `ForwardIndex` on disk, we need to load the documents we want to start playing with into memory. Since this is a small enough dataset, let's load the whole thing into memory at once.\n", + "\n", + "We need to decide what kind of dataset we're using. MeTA has classes for binary classification (`BinaryDataset`) and multi-class classification (`MulticlassDataset`), which you should choose from depending on the kind of classification problem you're dealing with. Let's see how many labels we have in our corpus." + ] + }, + { + "cell_type": "code", + "execution_count": 142, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 142, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fidx.num_labels()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Since this is more than 2, we likely want a `MulticlassDataset` so we can learn a classifier that can predict which of these three labels a document should have. (But we might be interested in only determining one particular class from the rest, in which case we might actually want a `BinaryDataset`.)\n", + "\n", + "For now, let's focus on the multi-class case, as that likely makes the most sense for this kind of data. Let's load or documents." + ] + }, + { + "cell_type": "code", + "execution_count": 143, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Loading instances into memory: [> ] 0% ETA 00:00:00 \r", + " > Loading instances into memory: [> ] 0% ETA 00:00:00 \r", + " > Loading instances into memory: [==========================] 100% ETA 00:00:00 \r", + " > Loading instances into memory: [==========================] 100% ETA 00:00:00 \n", + " \n" + ] + }, + { + "data": { + "text/plain": [ + "1008" + ] + }, + "execution_count": 143, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dset = metapy.classify.MulticlassDataset(fidx)\n", + "len(dset)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We have 1008 documents, split across three labels. What are our labels?" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'chinese', 'english', 'japanese'}" + ] + }, + "execution_count": 144, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "set([dset.label(instance) for instance in dset])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "This dataset is a small collection of essays written by a bunch of students with different first languages. Our goal will be to try to identify whether an essay was written by a native-Chinese speaker, a native-English speaker, or a native-Japanese speaker.\n", + "\n", + "Now, because these in-memory datasets can potentially be quite large, it's beneficial to not make unnecessary copies of them to, for example, create a new list that's shuffled that contains the same documents. In most cases, you'll be operating with a `DatasetView` (either `MulticlassDatasetView` or `BinaryDatasetView`) so that you can do things like shuffle or rotate the contents of a dataset without having to actually modify it. Doing so is pretty easy: you can use Python's slicing API, or you can just construct one directly." + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "view = dset[0:len(dset)+1]\n", + "# or\n", + "view = metapy.classify.MulticlassDatasetView(dset)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now we can, for example, shuffle this view without changing the underlying datsaet." + ] + }, + { + "cell_type": "code", + "execution_count": 146, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "869 vs 0\n" + ] + } + ], + "source": [ + "view.shuffle()\n", + "print(\"{} vs {}\".format(view[0].id, dset[0].id))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The view has been shuffled and now has documents in random order (useful in many cases to make sure that you don't have clumps of the same-labeled documents together, or to just permute the documents in a stochastic learning algorithm), but the underlying dataset is still sorted by id.\n", + "\n", + "We can also use this slicing API to create a random training and testing set from our shuffled views (views also support slicing). Let's make a 75-25 split of training-testing data. (Note that's really important that we already shuffled the view!)" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "training = view[0:int(0.75*len(view))]\n", + "testing = view[int(0.75*len(view)):]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, we're ready to train a classifier! Let's start with very simple one: [Naive Bayes](https://en.wikipedia.org/wiki/Naive_Bayes_classifier).\n", + "\n", + "In MeTA, construction of a classifier implies training of that model. Let's train a Naive Bayes classifier on our training view now." + ] + }, + { + "cell_type": "code", + "execution_count": 148, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "nb = metapy.classify.NaiveBayes(training)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can now classify individual documents like so." + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'japanese'" + ] + }, + "execution_count": 149, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nb.classify(testing[0].weights)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We might be more interested in how well we classify the testing set." + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " chinese english japanese \n", + " ------------------------------\n", + " chinese | \u001b[1m0.96\u001b[22m - 0.04 \n", + " english | - \u001b[1m0.909\u001b[22m 0.0909 \n", + " japanese | 0.0155 0.0155 \u001b[1m0.969\u001b[22m \n", + "\n", + "\n" + ] + } + ], + "source": [ + "mtrx = nb.test(testing)\n", + "print(mtrx)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The `test()` method of MeTA's classifiers returns to you a `ConfusionMatrix`, which contains useful information about what kinds of mistakes your classifier is making.\n", + "\n", + "(Note that, due to the random shuffling, you might see different results than we do here.)\n", + "\n", + "For example, we can see that this classifier seems to have some trouble with confusing native-Chinese students' essays with those of native-Japanese students. We can tell that by looking at the rows of the confusion matrix. Each row tells you what fraction of documents with that _true_ label were assigned the label for each column by the classifier. In the case of the native-Chinese label, we can see that 25% of the time they were miscategorized as being native-Japanese.\n", + "\n", + "The `ConfusionMatrix` also computes a lot of metrics that are commonly used in classifier evaluation." + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "chinese 0.923 0.889 0.96 0.0992 \n", + "english 0.909 0.909 0.909 0.131 \n", + "japanese 0.974 0.979 0.969 0.77 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.961\u001b[22m \u001b[1m0.961\u001b[22m \u001b[1m0.96\u001b[22m \n", + "------------------------------------------------------------\n", + "252 predictions attempted, overall accuracy: 0.96\n", + "\n" + ] + } + ], + "source": [ + "mtrx.print_stats()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "If we want to make sure that the classifier isn't overfitting to our training data, a common approach is to do [cross-validation](https://en.wikipedia.org/wiki/Cross-validation_(statistics)). Let's run CV for our Naive Bayes classifier across the whole dataset, using 5-folds, to get an idea of how well we might generalize to new data." + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1502921983: [info] Cross-validating fold 1/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 1/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 2/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 2/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 3/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 3/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 4/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 4/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 5/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 5/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n" + ] + } + ], + "source": [ + "mtrx = metapy.classify.cross_validate(lambda fold: metapy.classify.NaiveBayes(fold), view, 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "`cross_validate()` returns a `ConfusionMatrix` just like `test()` does. We give it a function to use to create the trained classifiers for each fold, and then pass in the dataset view containing all of our documents, and the number of folds we want to use.\n", + "\n", + "Let's see how we did." + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " chinese english japanese \n", + " ------------------------------\n", + " chinese | \u001b[1m0.868\u001b[22m 0.011 0.121 \n", + " english | 0.0342 \u001b[1m0.918\u001b[22m 0.0479 \n", + " japanese | 0.0195 0.00911 \u001b[1m0.971\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "chinese 0.832 0.798 0.868 0.0905 \n", + "english 0.931 0.944 0.918 0.145 \n", + "japanese 0.974 0.976 0.971 0.764 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.955\u001b[22m \u001b[1m0.956\u001b[22m \u001b[1m0.954\u001b[22m \n", + "------------------------------------------------------------\n", + "1005 predictions attempted, overall accuracy: 0.954\n", + "\n" + ] + } + ], + "source": [ + "print(mtrx)\n", + "mtrx.print_stats()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now let's do the same thing, but for an arguably stronger baseline: [SVM](https://en.wikipedia.org/wiki/Support_vector_machine).\n", + "\n", + "MeTA's implementation of SVM is actually an approximation using [stochastic gradient descent](https://en.wikipedia.org/wiki/Stochastic_gradient_descent) on the [hinge loss](https://en.wikipedia.org/wiki/Hinge_loss). It's implemented as a `BinaryClassifier`, so we will need to adapt it before it can be used to solve our multi-class clasification problem.\n", + "\n", + "MeTA provides two different adapters for this scenario: [One-vs-All](https://en.wikipedia.org/wiki/Multiclass_classification#One-vs.-rest) and [One-vs-One](https://en.wikipedia.org/wiki/Multiclass_classification#One-vs.-one)." + ] + }, + { + "cell_type": "code", + "execution_count": 154, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "ova = metapy.classify.OneVsAll(training, metapy.classify.SGD, loss_id='hinge')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We construct the `OneVsAll` reduction by providing it the training documents, the name of a binary classifier, and then (as keyword arguments) any additional arguments to that chosen classifier. In this case, we use `loss_id` to specify the loss function to use.\n", + "\n", + "We can now use `OneVsAll` just like any other classifier." + ] + }, + { + "cell_type": "code", + "execution_count": 155, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " chinese english japanese \n", + " ------------------------------\n", + " chinese | \u001b[1m0.72\u001b[22m - 0.28 \n", + " english | - \u001b[1m0.909\u001b[22m 0.0909 \n", + " japanese | - 0.0103 \u001b[1m0.99\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "chinese 0.837 1 0.72 0.0992 \n", + "english 0.923 0.938 0.909 0.131 \n", + "japanese 0.97 0.95 0.99 0.77 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.953\u001b[22m \u001b[1m0.954\u001b[22m \u001b[1m0.952\u001b[22m \n", + "------------------------------------------------------------\n", + "252 predictions attempted, overall accuracy: 0.952\n", + "\n" + ] + } + ], + "source": [ + "mtrx = ova.test(testing)\n", + "print(mtrx)\n", + "mtrx.print_stats()" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " chinese english japanese \n", + " ------------------------------\n", + " chinese | \u001b[1m0.835\u001b[22m 0.022 0.143 \n", + " english | - \u001b[1m0.911\u001b[22m 0.089 \n", + " japanese | 0.00391 0.00651 \u001b[1m0.99\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "chinese 0.894 0.962 0.835 0.0905 \n", + "english 0.93 0.95 0.911 0.145 \n", + "japanese 0.978 0.967 0.99 0.764 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.964\u001b[22m \u001b[1m0.964\u001b[22m \u001b[1m0.964\u001b[22m \n", + "------------------------------------------------------------\n", + "1005 predictions attempted, overall accuracy: 0.964\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1502921983: [info] Cross-validating fold 1/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 1/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 2/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 2/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 3/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 3/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 4/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 4/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 5/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n", + "1502921983: [info] Cross-validating fold 5/5 (/tmp/pip-bneszy3v-build/deps/meta/include/meta/classify/classifier/classifier.h:103)\n" + ] + } + ], + "source": [ + "mtrx = metapy.classify.cross_validate(lambda fold: metapy.classify.OneVsAll(fold, metapy.classify.SGD, loss_id='hinge'), view, 5)\n", + "print(mtrx)\n", + "mtrx.print_stats()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "That should be enough to get you started! Try looking at `help(metapy.classify)` for a list of what's included in the bindings." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "source": [ + "**COMPETITION TIME**" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "# Part 4: Topic Modeling" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "In this part of the tutorial we will discuss how to run a topic model over data indexed as a `ForwardIndex`." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We will need to index our data to proceed. We eventually want to be able to extract the bag-of-words representation for our individual documents, so we will want a `ForwardIndex` in this case." + ] + }, + { + "cell_type": "code", + "execution_count": 157, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1502921983: [info] Loading index from disk: ceeaus-idx/fwd (/tmp/pip-bneszy3v-build/deps/meta/src/index/forward_index.cpp:171)\n", + "1502921983: [info] Loading index from disk: ceeaus-idx/fwd (/tmp/pip-bneszy3v-build/deps/meta/src/index/forward_index.cpp:171)\n" + ] + } + ], + "source": [ + "fidx = metapy.index.make_forward_index('ceeaus-config.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Just like in classification, the feature set used for the topic modeling will be the feature set used at the time of indexing, so if you want to play with a different set of features (like bigram words), you will need to re-index your data.\n", + "\n", + "For now, we've just stuck with the default filter chain for unigram words, so we're operating in the traditional bag-of-words space.\n", + "\n", + "Let's load our documents into memory to run the topic model inference now." + ] + }, + { + "cell_type": "code", + "execution_count": 158, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Loading instances into memory: [> ] 0% ETA 00:00:00 \r", + " > Loading instances into memory: [> ] 0% ETA 00:00:00 \r", + " > Loading instances into memory: [==========================] 100% ETA 00:00:00 \r", + " > Loading instances into memory: [==========================] 100% ETA 00:00:00 \n", + " \n" + ] + } + ], + "source": [ + "dset = metapy.learn.Dataset(fidx)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's try to find some topics for this dataset. To do so, we're going to use a generative model called a topic model.\n", + "\n", + "There are many different topic models in the literature, but the most commonly used topic model is Latent Dirichlet Allocation. Here, we propose that there are K topics (represented with a categorical distribution over words) $\\phi_k$ from which all of our documents are genereated. These K topics are modeled as being sampled from a Dirichlet distribution with parameter $\\vec{\\alpha}$. Then, to generate a document $d$, we first sample a distribution over the K topics $\\theta_d$ from another Dirichlet distribution with parameter $\\vec{\\beta}$. Then, for each word in this document, we first sample a topic identifier $z \\sim \\theta_d$ and then the word by drawing from the topic we selected ($w \\sim \\phi_z$). Refer to the [Wikipedia article on LDA](https://en.wikipedia.org/wiki/Latent_Dirichlet_allocation) for more information.\n", + "\n", + "The goal of running inference for an LDA model is to infer the latent variables $\\phi_k$ and $\\theta_d$ for all of the $K$ topics and $D$ documents, respectively. MeTA provides a number of different inference algorithms for LDA, as each one entails a different set of trade-offs (inference in LDA is intractable, so all inference algorithms are approximations; different algorithms entail different approximation guarantees, running times, and required memroy consumption). For now, let's run a Variational Infernce algorithm called CVB0 to find two topics. (In practice you will likely be finding many more topics than just two, but this is a very small toy dataset.)" + ] + }, + { + "cell_type": "code", + "execution_count": 159, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Initialization: [============================================] 100% ETA 00:00:00 \n", + " \n", + "Iteration 1 maximum change in gamma: 1.94892 \n", + "Iteration 1 maximum change in gamma: 1.94892 \n", + "Iteration 2 maximum change in gamma: 0.489304 \n", + "Iteration 2 maximum change in gamma: 0.489304 \n", + "Iteration 3 maximum change in gamma: 0.353439 \n", + "Iteration 3 maximum change in gamma: 0.353439 \n", + "Iteration 4 maximum change in gamma: 0.437895 \n", + "Iteration 4 maximum change in gamma: 0.437895 \n", + "Iteration 5 maximum change in gamma: 0.646495 \n", + "Iteration 5 maximum change in gamma: 0.646495 \n", + "Iteration 6 maximum change in gamma: 1.08145 \n", + "Iteration 6 maximum change in gamma: 1.08145 \n", + "Iteration 7 maximum change in gamma: 1.37714 \n", + "Iteration 7 maximum change in gamma: 1.37714 \n", + "Iteration 8 maximum change in gamma: 1.5234 \n", + "Iteration 8 maximum change in gamma: 1.5234 \n", + "Iteration 9 maximum change in gamma: 1.41999 \n", + "Iteration 9 maximum change in gamma: 1.41999 \n", + "Iteration 10 maximum change in gamma: 1.35315 \n", + "Iteration 10 maximum change in gamma: 1.35315 \n", + "Iteration 11 maximum change in gamma: 1.16084 \n", + "Iteration 11 maximum change in gamma: 1.16084 \n", + "Iteration 12 maximum change in gamma: 0.985118 \n", + "Iteration 12 maximum change in gamma: 0.985118 \n", + "Iteration 13 maximum change in gamma: 0.529624 \n", + "Iteration 13 maximum change in gamma: 0.529624 \n", + "Iteration 14 maximum change in gamma: 0.505101 \n", + "Iteration 14 maximum change in gamma: 0.505101 \n", + "Iteration 15 maximum change in gamma: 0.357362 \n", + "Iteration 15 maximum change in gamma: 0.357362 \n", + "Iteration 16 maximum change in gamma: 0.33901 \n", + "Iteration 16 maximum change in gamma: 0.33901 \n", + "Iteration 17 maximum change in gamma: 0.277928 \n", + "Iteration 17 maximum change in gamma: 0.277928 \n", + "Iteration 18 maximum change in gamma: 0.242615 \n", + "Iteration 18 maximum change in gamma: 0.242615 \n", + "Iteration 19 maximum change in gamma: 0.237642 \n", + "Iteration 19 maximum change in gamma: 0.237642 \n", + "Iteration 20 maximum change in gamma: 0.198027 \n", + "Iteration 20 maximum change in gamma: 0.198027 \n", + "Iteration 21 maximum change in gamma: 0.192858 \n", + "Iteration 21 maximum change in gamma: 0.192858 \n", + "Iteration 22 maximum change in gamma: 0.185038 \n", + "Iteration 22 maximum change in gamma: 0.185038 \n", + "Iteration 23 maximum change in gamma: 0.168724 \n", + "Iteration 23 maximum change in gamma: 0.168724 \n", + "Iteration 24 maximum change in gamma: 0.157681 \n", + "Iteration 24 maximum change in gamma: 0.157681 \n", + "Iteration 25 maximum change in gamma: 0.13898 \n", + "Iteration 25 maximum change in gamma: 0.13898 \n", + "Iteration 26 maximum change in gamma: 0.131065 \n", + "Iteration 26 maximum change in gamma: 0.131065 \n", + "Iteration 27 maximum change in gamma: 0.126334 \n", + "Iteration 27 maximum change in gamma: 0.126334 \n", + "Iteration 28 maximum change in gamma: 0.148569 \n", + "Iteration 28 maximum change in gamma: 0.148569 \n", + "Iteration 29 maximum change in gamma: 0.177806 \n", + "Iteration 29 maximum change in gamma: 0.177806 \n", + "Iteration 30 maximum change in gamma: 0.19599 \n", + "Iteration 30 maximum change in gamma: 0.19599 \n", + "Iteration 31 maximum change in gamma: 0.195208 \n", + "Iteration 31 maximum change in gamma: 0.195208 \n", + "Iteration 32 maximum change in gamma: 0.207592 \n", + "Iteration 32 maximum change in gamma: 0.207592 \n", + "Iteration 33 maximum change in gamma: 0.222097 \n", + "Iteration 33 maximum change in gamma: 0.222097 \n", + "Iteration 34 maximum change in gamma: 0.209845 \n", + "Iteration 34 maximum change in gamma: 0.209845 \n", + "Iteration 35 maximum change in gamma: 0.211747 \n", + "Iteration 35 maximum change in gamma: 0.211747 \n", + "Iteration 36 maximum change in gamma: 0.185753 \n", + "Iteration 36 maximum change in gamma: 0.185753 \n", + "Iteration 37 maximum change in gamma: 0.142088 \n", + "Iteration 37 maximum change in gamma: 0.142088 \n", + "Iteration 38 maximum change in gamma: 0.096915 \n", + "Iteration 38 maximum change in gamma: 0.096915 \n", + "Iteration 39 maximum change in gamma: 0.0608104 \n", + "Iteration 39 maximum change in gamma: 0.0608104 \n", + "Iteration 40 maximum change in gamma: 0.0361621 \n", + "Iteration 40 maximum change in gamma: 0.0361621 \n", + "Iteration 41 maximum change in gamma: 0.0208601 \n", + "Iteration 41 maximum change in gamma: 0.0208601 \n", + "Iteration 42 maximum change in gamma: 0.0192793 \n", + "Iteration 42 maximum change in gamma: 0.0192793 \n", + "Iteration 43 maximum change in gamma: 0.0184543 \n", + "Iteration 43 maximum change in gamma: 0.0184543 \n", + "Iteration 44 maximum change in gamma: 0.0176882 \n", + "Iteration 44 maximum change in gamma: 0.0176882 \n", + "Iteration 45 maximum change in gamma: 0.0169772 \n", + "Iteration 45 maximum change in gamma: 0.0169772 \n", + "Iteration 46 maximum change in gamma: 0.0163172 \n", + "Iteration 46 maximum change in gamma: 0.0163172 \n", + "Iteration 47 maximum change in gamma: 0.0157038 \n", + "Iteration 47 maximum change in gamma: 0.0157038 \n", + "Iteration 48 maximum change in gamma: 0.0151331 \n", + "Iteration 48 maximum change in gamma: 0.0151331 \n", + "Iteration 49 maximum change in gamma: 0.0146011 \n", + "Iteration 49 maximum change in gamma: 0.0146011 \n", + "Iteration 50 maximum change in gamma: 0.0141041 \n", + "Iteration 50 maximum change in gamma: 0.0141041 \n", + "Iteration 51 maximum change in gamma: 0.0136389 \n", + "Iteration 51 maximum change in gamma: 0.0136389 \n", + "Iteration 52 maximum change in gamma: 0.0132024 \n", + "Iteration 52 maximum change in gamma: 0.0132024 \n", + "Iteration 53 maximum change in gamma: 0.0127917 \n", + "Iteration 53 maximum change in gamma: 0.0127917 \n", + "Iteration 54 maximum change in gamma: 0.0124045 \n", + "Iteration 54 maximum change in gamma: 0.0124045 \n", + "Iteration 55 maximum change in gamma: 0.0120384 \n", + "Iteration 55 maximum change in gamma: 0.0120384 \n", + "Iteration 56 maximum change in gamma: 0.0116915 \n", + "Iteration 56 maximum change in gamma: 0.0116915 \n", + "Iteration 57 maximum change in gamma: 0.0113617 \n", + "Iteration 57 maximum change in gamma: 0.0113617 \n", + "Iteration 58 maximum change in gamma: 0.0110477 \n", + "Iteration 58 maximum change in gamma: 0.0110477 \n", + "Iteration 59 maximum change in gamma: 0.0107477 \n", + "Iteration 59 maximum change in gamma: 0.0107477 \n", + "Iteration 60 maximum change in gamma: 0.0104606 \n", + "Iteration 60 maximum change in gamma: 0.0104606 \n", + "Iteration 61 maximum change in gamma: 0.0101851 \n", + "Iteration 61 maximum change in gamma: 0.0101851 \n", + "Iteration 62 maximum change in gamma: 0.00992002 \n", + "Iteration 62 maximum change in gamma: 0.00992002 \n", + "Iteration 63 maximum change in gamma: 0.00966452 \n", + "Iteration 63 maximum change in gamma: 0.00966452 \n", + "Iteration 64 maximum change in gamma: 0.00941766 \n", + "Iteration 64 maximum change in gamma: 0.00941766 \n", + "Iteration 65 maximum change in gamma: 0.00917865 \n", + "Iteration 65 maximum change in gamma: 0.00917865 \n", + "Iteration 66 maximum change in gamma: 0.00908822 \n", + "Iteration 66 maximum change in gamma: 0.00908822 \n", + "Iteration 67 maximum change in gamma: 0.0091286 \n", + "Iteration 67 maximum change in gamma: 0.0091286 \n", + "Iteration 68 maximum change in gamma: 0.00916622 \n", + "Iteration 68 maximum change in gamma: 0.00916622 \n", + "Iteration 69 maximum change in gamma: 0.00920064 \n", + "Iteration 69 maximum change in gamma: 0.00920064 \n", + "Iteration 70 maximum change in gamma: 0.00923141 \n", + "Iteration 70 maximum change in gamma: 0.00923141 \n", + "Iteration 71 maximum change in gamma: 0.00925807 \n", + "Iteration 71 maximum change in gamma: 0.00925807 \n", + "Iteration 72 maximum change in gamma: 0.00928021 \n", + "Iteration 72 maximum change in gamma: 0.00928021 \n", + "Iteration 73 maximum change in gamma: 0.00929737 \n", + "Iteration 73 maximum change in gamma: 0.00929737 \n", + "Iteration 74 maximum change in gamma: 0.00930916 \n", + "Iteration 74 maximum change in gamma: 0.00930916 \n", + "Iteration 75 maximum change in gamma: 0.00931517 \n", + "Iteration 75 maximum change in gamma: 0.00931517 \n", + "Iteration 76 maximum change in gamma: 0.00931502 \n", + "Iteration 76 maximum change in gamma: 0.00931502 \n", + "Iteration 77 maximum change in gamma: 0.00930835 \n", + "Iteration 77 maximum change in gamma: 0.00930835 \n", + "Iteration 78 maximum change in gamma: 0.00929481 \n", + "Iteration 78 maximum change in gamma: 0.00929481 \n", + "Iteration 79 maximum change in gamma: 0.00927412 \n", + "Iteration 79 maximum change in gamma: 0.00927412 \n", + "Iteration 80 maximum change in gamma: 0.00924599 \n", + "Iteration 80 maximum change in gamma: 0.00924599 \n", + "Iteration 81 maximum change in gamma: 0.00921019 \n", + "Iteration 81 maximum change in gamma: 0.00921019 \n", + "Iteration 82 maximum change in gamma: 0.00916651 \n", + "Iteration 82 maximum change in gamma: 0.00916651 \n", + "Iteration 83 maximum change in gamma: 0.00911479 \n", + "Iteration 83 maximum change in gamma: 0.00911479 \n", + "Iteration 84 maximum change in gamma: 0.00905492 \n", + "Iteration 84 maximum change in gamma: 0.00905492 \n", + "Iteration 85 maximum change in gamma: 0.00898683 \n", + "Iteration 85 maximum change in gamma: 0.00898683 \n", + "Iteration 86 maximum change in gamma: 0.00891048 \n", + "Iteration 86 maximum change in gamma: 0.00891048 \n", + "Iteration 87 maximum change in gamma: 0.00882591 \n", + "Iteration 87 maximum change in gamma: 0.00882591 \n", + "Iteration 88 maximum change in gamma: 0.00873318 \n", + "Iteration 88 maximum change in gamma: 0.00873318 \n", + "Iteration 89 maximum change in gamma: 0.0086324 \n", + "Iteration 89 maximum change in gamma: 0.0086324 \n", + "Iteration 90 maximum change in gamma: 0.00852376 \n", + "Iteration 90 maximum change in gamma: 0.00852376 \n", + "Iteration 91 maximum change in gamma: 0.00840745 \n", + "Iteration 91 maximum change in gamma: 0.00840745 \n", + "Iteration 92 maximum change in gamma: 0.00828374 \n", + "Iteration 92 maximum change in gamma: 0.00828374 \n", + "Iteration 93 maximum change in gamma: 0.00815293 \n", + "Iteration 93 maximum change in gamma: 0.00815293 \n", + "Iteration 94 maximum change in gamma: 0.00801536 \n", + "Iteration 94 maximum change in gamma: 0.00801536 \n", + "Iteration 95 maximum change in gamma: 0.00787141 \n", + "Iteration 95 maximum change in gamma: 0.00787141 \n", + "Iteration 96 maximum change in gamma: 0.00772149 \n", + "Iteration 96 maximum change in gamma: 0.00772149 \n", + "Iteration 97 maximum change in gamma: 0.00756605 \n", + "Iteration 97 maximum change in gamma: 0.00756605 \n", + "Iteration 98 maximum change in gamma: 0.00740556 \n", + "Iteration 98 maximum change in gamma: 0.00740556 \n", + "Iteration 99 maximum change in gamma: 0.0072405 \n", + "Iteration 99 maximum change in gamma: 0.0072405 \n", + "Iteration 100 maximum change in gamma: 0.00707137 \n", + "Iteration 100 maximum change in gamma: 0.00707137 \n", + "Iteration 101 maximum change in gamma: 0.0068987 \n", + "Iteration 101 maximum change in gamma: 0.0068987 \n", + "Iteration 102 maximum change in gamma: 0.00672302 \n", + "Iteration 102 maximum change in gamma: 0.00672302 \n", + "Iteration 103 maximum change in gamma: 0.00654484 \n", + "Iteration 103 maximum change in gamma: 0.00654484 \n", + "Iteration 104 maximum change in gamma: 0.00636471 \n", + "Iteration 104 maximum change in gamma: 0.00636471 \n", + "Iteration 105 maximum change in gamma: 0.00618313 \n", + "Iteration 105 maximum change in gamma: 0.00618313 \n", + "Iteration 106 maximum change in gamma: 0.00600062 \n", + "Iteration 106 maximum change in gamma: 0.00600062 \n", + "Iteration 107 maximum change in gamma: 0.00581768 \n", + "Iteration 107 maximum change in gamma: 0.00581768 \n", + "Iteration 108 maximum change in gamma: 0.00563479 \n", + "Iteration 108 maximum change in gamma: 0.00563479 \n", + "Iteration 109 maximum change in gamma: 0.00545242 \n", + "Iteration 109 maximum change in gamma: 0.00545242 \n", + "Iteration 110 maximum change in gamma: 0.00527099 \n", + "Iteration 110 maximum change in gamma: 0.00527099 \n", + "Iteration 111 maximum change in gamma: 0.00509093 \n", + "Iteration 111 maximum change in gamma: 0.00509093 \n", + "Iteration 112 maximum change in gamma: 0.00491263 \n", + "Iteration 112 maximum change in gamma: 0.00491263 \n", + "Iteration 113 maximum change in gamma: 0.00473645 \n", + "Iteration 113 maximum change in gamma: 0.00473645 \n", + "Iteration 114 maximum change in gamma: 0.00456272 \n", + "Iteration 114 maximum change in gamma: 0.00456272 \n", + "Iteration 115 maximum change in gamma: 0.00439176 \n", + "Iteration 115 maximum change in gamma: 0.00439176 \n", + "Iteration 116 maximum change in gamma: 0.00422383 \n", + "Iteration 116 maximum change in gamma: 0.00422383 \n", + "Iteration 117 maximum change in gamma: 0.00405918 \n", + "Iteration 117 maximum change in gamma: 0.00405918 \n", + "Iteration 118 maximum change in gamma: 0.00389803 \n", + "Iteration 118 maximum change in gamma: 0.00389803 \n", + "Iteration 119 maximum change in gamma: 0.00374058 \n", + "Iteration 119 maximum change in gamma: 0.00374058 \n", + "Iteration 120 maximum change in gamma: 0.00358697 \n", + "Iteration 120 maximum change in gamma: 0.00358697 \n", + "Iteration 121 maximum change in gamma: 0.00343736 \n", + "Iteration 121 maximum change in gamma: 0.00343736 \n", + "Iteration 122 maximum change in gamma: 0.00329185 \n", + "Iteration 122 maximum change in gamma: 0.00329185 \n", + "Iteration 123 maximum change in gamma: 0.00315053 \n", + "Iteration 123 maximum change in gamma: 0.00315053 \n", + "Iteration 124 maximum change in gamma: 0.00301346 \n", + "Iteration 124 maximum change in gamma: 0.00301346 \n", + "Iteration 125 maximum change in gamma: 0.00288069 \n", + "Iteration 125 maximum change in gamma: 0.00288069 \n", + "Iteration 126 maximum change in gamma: 0.00275224 \n", + "Iteration 126 maximum change in gamma: 0.00275224 \n", + "Iteration 127 maximum change in gamma: 0.00262812 \n", + "Iteration 127 maximum change in gamma: 0.00262812 \n", + "Iteration 128 maximum change in gamma: 0.00250831 \n", + "Iteration 128 maximum change in gamma: 0.00250831 \n", + "Iteration 129 maximum change in gamma: 0.00239279 \n", + "Iteration 129 maximum change in gamma: 0.00239279 \n", + "Iteration 130 maximum change in gamma: 0.00228152 \n", + "Iteration 130 maximum change in gamma: 0.00228152 \n", + "Iteration 131 maximum change in gamma: 0.00217445 \n", + "Iteration 131 maximum change in gamma: 0.00217445 \n", + "Iteration 132 maximum change in gamma: 0.00207151 \n", + "Iteration 132 maximum change in gamma: 0.00207151 \n", + "Iteration 133 maximum change in gamma: 0.00197264 \n", + "Iteration 133 maximum change in gamma: 0.00197264 \n", + "Iteration 134 maximum change in gamma: 0.00187775 \n", + "Iteration 134 maximum change in gamma: 0.00187775 \n", + "Iteration 135 maximum change in gamma: 0.00178675 \n", + "Iteration 135 maximum change in gamma: 0.00178675 \n", + "Iteration 136 maximum change in gamma: 0.00169956 \n", + "Iteration 136 maximum change in gamma: 0.00169956 \n", + "Iteration 137 maximum change in gamma: 0.00161608 \n", + "Iteration 137 maximum change in gamma: 0.00161608 \n", + "Iteration 138 maximum change in gamma: 0.00153619 \n", + "Iteration 138 maximum change in gamma: 0.00153619 \n", + "Iteration 139 maximum change in gamma: 0.00145981 \n", + "Iteration 139 maximum change in gamma: 0.00145981 \n", + "Iteration 140 maximum change in gamma: 0.00138681 \n", + "Iteration 140 maximum change in gamma: 0.00138681 \n", + "Iteration 141 maximum change in gamma: 0.0013171 \n", + "Iteration 141 maximum change in gamma: 0.0013171 \n", + "Iteration 142 maximum change in gamma: 0.00125055 \n", + "Iteration 142 maximum change in gamma: 0.00125055 \n", + "Iteration 143 maximum change in gamma: 0.00118707 \n", + "Iteration 143 maximum change in gamma: 0.00118707 \n", + "Iteration 144 maximum change in gamma: 0.00112654 \n", + "Iteration 144 maximum change in gamma: 0.00112654 \n", + "Iteration 145 maximum change in gamma: 0.00106885 \n", + "Iteration 145 maximum change in gamma: 0.00106885 \n", + "Iteration 146 maximum change in gamma: 0.00101389 \n", + "Iteration 146 maximum change in gamma: 0.00101389 \n", + "Iteration 147 maximum change in gamma: 0.000961562 \n", + "Iteration 147 maximum change in gamma: 0.000961562 \n", + "1502921989: [info] Finished maximum iterations, or found convergence! (/tmp/pip-bneszy3v-build/deps/meta/src/topics/lda_cvb.cpp:60)\n", + "1502921989: [info] Finished maximum iterations, or found convergence! (/tmp/pip-bneszy3v-build/deps/meta/src/topics/lda_cvb.cpp:60)\n" + ] + } + ], + "source": [ + "lda_inf = metapy.topics.LDACollapsedVB(dset, num_topics=2, alpha=1.0, beta=0.01)\n", + "lda_inf.run(num_iters=1000)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "source": [ + "The above ran the CVB0 algorithm for 1000 iterations, or until an algorithm-specific convergence criterion was met. Now let's save the current estimate for our topics and topic proportions." + ] + }, + { + "cell_type": "code", + "execution_count": 160, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "lda_inf.save('lda-cvb0')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can interrogate the topic inference results by using the `TopicModel` query class. Let's load our inference results back in." + ] + }, + { + "cell_type": "code", + "execution_count": 161, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Loading topic term probabilities: [===========> ] 50% ETA 00:00:00 \r", + " > Loading topic term probabilities: [===========> ] 50% ETA 00:00:00 \r", + " > Loading topic term probabilities: [=======================] 100% ETA 00:00:00 \r", + " > Loading topic term probabilities: [=======================] 100% ETA 00:00:00 \n", + " \n", + " \r", + " > Loading document topic probabilities: [> ] 0% ETA 00:00:00 \r", + " > Loading document topic probabilities: [> ] 0% ETA 00:00:00 \r", + " > Loading document topic probabilities: [===================] 100% ETA 00:00:00 \r", + " > Loading document topic probabilities: [===================] 100% ETA 00:00:00 \n", + " \n" + ] + } + ], + "source": [ + "model = metapy.topics.TopicModel('lda-cvb0')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Now, let's have a look at our topics. A typical way of doing this is to print the top $k$ words in each topic, so let's do that." + ] + }, + { + "cell_type": "code", + "execution_count": 162, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(3759, 0.06705637112528769),\n", + " (1968, 0.05605930810442864),\n", + " (2635, 0.05222307061872271),\n", + " (3549, 0.04642939140343873),\n", + " (665, 0.03488141234942433),\n", + " (4157, 0.02906748539640022),\n", + " (2322, 0.02885022388702368),\n", + " (3729, 0.022331344581221765),\n", + " (1790, 0.020755699719924883),\n", + " (3554, 0.015483037834133842)]" + ] + }, + "execution_count": 162, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.top_k(tid=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "The models operate on term ids instead of raw text strings, so let's convert this to a human readable format by using the vocabulary contained in our `ForwardIndex` to map the term ids to strings." + ] + }, + { + "cell_type": "code", + "execution_count": 163, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('time', 0.06705637112528769),\n", + " ('job', 0.05605930810442864),\n", + " ('part', 0.05222307061872271),\n", + " ('student', 0.04642939140343873),\n", + " ('colleg', 0.03488141234942433),\n", + " ('work', 0.02906748539640022),\n", + " ('money', 0.02885022388702368),\n", + " ('think', 0.022331344581221765),\n", + " ('import', 0.020755699719924883),\n", + " ('studi', 0.015483037834133842)]" + ] + }, + "execution_count": 163, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[(fidx.term_text(pr[0]), pr[1]) for pr in model.top_k(tid=0)]" + ] + }, + { + "cell_type": "code", + "execution_count": 164, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('smoke', 0.13110394941553408),\n", + " ('restaur', 0.054349311633512025),\n", + " ('peopl', 0.036780087802958536),\n", + " ('smoker', 0.03349263454160484),\n", + " ('ban', 0.022530670096022554),\n", + " ('think', 0.015620489442527752),\n", + " ('japan', 0.012780916901417468),\n", + " ('complet', 0.012635067649017825),\n", + " ('cigarett', 0.011987181371938055),\n", + " ('non', 0.011317738574939687)]" + ] + }, + "execution_count": 164, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[(fidx.term_text(pr[0]), pr[1]) for pr in model.top_k(tid=1)]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can pretty clearly see that this particular dataset was about two major issues: part time jobs for students and smoking in public. This dataset is actually a collection of essays written by students, and there just so happen to be two different topics they can choose from!\n", + "\n", + "The topics are pretty clear in this case, but in some cases it is also useful to score the terms in a topic using some function of the probability of the word in the topic and the probability of the word in the other topics. Intuitively, we might want to select words from each topic that best reflect that topic's content by picking words that both have high probability in that topic **and** have low probability in the other topics. In other words, we want to balance between high probability terms and highly specific terms (this is kind of like a tf-idf weighting). One such scoring function is provided by the toolkit in `BLTermScorer`, which implements a scoring function proposed by Blei and Lafferty." + ] + }, + { + "cell_type": "code", + "execution_count": 165, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('job', 0.34822058296128233),\n", + " ('part', 0.31311075688049606),\n", + " ('student', 0.2832893627599442),\n", + " ('colleg', 0.20809000481963835),\n", + " ('time', 0.17796675292712294),\n", + " ('money', 0.16234684321361126),\n", + " ('work', 0.1558533795913366),\n", + " ('studi', 0.08228291023281153),\n", + " ('learn', 0.06491900298193354),\n", + " ('experi', 0.054945276562063716)]" + ] + }, + "execution_count": 165, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scorer = metapy.topics.BLTermScorer(model)\n", + "[(fidx.term_text(pr[0]), pr[1]) for pr in model.top_k(tid=0, scorer=scorer)]" + ] + }, + { + "cell_type": "code", + "execution_count": 166, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('smoke', 0.874164081128221),\n", + " ('restaur', 0.31746129947227786),\n", + " ('smoker', 0.20060262327581713),\n", + " ('ban', 0.128530349360076),\n", + " ('cigarett', 0.06557605570188008),\n", + " ('non', 0.061284206154067045),\n", + " ('complet', 0.0610537364588466),\n", + " ('japan', 0.0584657324517579),\n", + " ('health', 0.05054833214552534),\n", + " ('seat', 0.04533989023870699)]" + ] + }, + "execution_count": 166, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[(fidx.term_text(pr[0]), pr[1]) for pr in model.top_k(tid=1, scorer=scorer)]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Here we can see that the uninformative word stem \"think\" was downweighted from the word list from each topic, since it had relatively high probability in either topic." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "We can also see the inferred topic distribution for each document." + ] + }, + { + "cell_type": "code", + "execution_count": 167, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 167, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.topic_distribution(0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "It looks like our first document was written by a student who chose the part-time job essay topic..." + ] + }, + { + "cell_type": "code", + "execution_count": 168, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 168, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.topic_distribution(900)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "...whereas this document looks like it was written by a student who chose the public smoking essay topic." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/metapy/tutorials/apnews-config.toml b/metapy/tutorials/apnews-config.toml new file mode 100644 index 0000000000..c03e911368 --- /dev/null +++ b/metapy/tutorials/apnews-config.toml @@ -0,0 +1,16 @@ +prefix = "." +dataset = "apnews" +corpus = "line.toml" +index = "idx" +query-judgements = "qrels.txt" + +[[analyzers]] +method = "ngram-word" +ngram = 1 +filter = [{type = "icu-tokenizer", suppress-tags = true}, {type = "lowercase"}] + +[ranker] +method = "bm25" +k1 = 1.2 +b = 0.75 +k3 = 500 diff --git a/metapy/tutorials/ceeaus-config.toml b/metapy/tutorials/ceeaus-config.toml new file mode 100644 index 0000000000..3a3eb912ea --- /dev/null +++ b/metapy/tutorials/ceeaus-config.toml @@ -0,0 +1,10 @@ +prefix = "." +dataset = "ceeaus" +corpus = "line.toml" +index = "ceeaus-idx" +stop-words = "lemur-stopwords.txt" + +[[analyzers]] +method = "ngram-word" +ngram = 1 +filter = "default-unigram-chain" diff --git a/metapy/tutorials/config.toml b/metapy/tutorials/config.toml new file mode 100644 index 0000000000..575e98c4a0 --- /dev/null +++ b/metapy/tutorials/config.toml @@ -0,0 +1,4 @@ +[[analyzers]] +method = "ngram-word" +ngram = 1 +filter = [{type = "icu-tokenizer"}, {type = "lowercase"}] diff --git a/metapy/tutorials/sigir18-topic-models/sigir18-retrieval.ipynb b/metapy/tutorials/sigir18-topic-models/sigir18-retrieval.ipynb new file mode 100644 index 0000000000..838407dca2 --- /dev/null +++ b/metapy/tutorials/sigir18-topic-models/sigir18-retrieval.ipynb @@ -0,0 +1,983 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Exercise 1: Pseudo-feedback with Two-component Mixture Model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, let's import the Python bindings for MeTA:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import metapy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you don't have `metapy` installed, you can install it with a\n", + "\n", + "```bash\n", + "pip install metapy\n", + "```\n", + "\n", + "on the command line on Linux, macOS, or Windows for either Python 2.7 or Python 3.x. (I will be using Python 3.6 in this tutorial.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Double-check that you are running the latest version. Right now, that should be `0.2.10`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'0.2.10'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "metapy.__version__" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's set MeTA to log to standard error so we can see progress output for long-running commands. (Only do this once, or you'll get double the output.)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "metapy.log_to_stderr()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's download all of the files we need for the tutorial." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import urllib.request\n", + "import os\n", + "import tarfile\n", + "\n", + "if not os.path.exists('sigir18-tutorial.tar.gz'):\n", + " urllib.request.urlretrieve('https://meta-toolkit.org/data/2018-06-25/sigir18-tutorial.tar.gz',\n", + " 'sigir18-tutorial.tar.gz')\n", + " \n", + "if not os.path.exists('data'):\n", + " with tarfile.open('sigir18-tutorial.tar.gz', 'r:gz') as files:\n", + " files.extractall()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's index our data using the `InvertedIndex` format. In a search engine, we want to quickly determine what documents mention a specific query term, so the `InvertedIndex` stores a mapping from term to a list of documents that contain that term (along with how many times they do)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Counting lines in file: [> ] 0% ETA 00:00:00 \r", + " > Counting lines in file: [=================================] 100% ETA 00:00:00 \n", + "1529953996: [info] Creating index: cranfield-idx/inv (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/inverted_index.cpp:119)\n", + " \r", + " > Tokenizing Docs: [> ] 0% ETA 00:00:00 \n", + "1529953996: [warning] Empty document (id = 470) generated! (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/inverted_index.cpp:228)\n", + " \n", + "1529953996: [warning] Empty document (id = 994) generated! (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/inverted_index.cpp:228)\n", + " \r", + " > Tokenizing Docs: [========================================] 100% ETA 00:00:00 \n", + " \r", + " > Merging: [> ] 0% ETA 00:00:00 \r", + " > Merging: [================================================] 100% ETA 00:00:00 \n", + "1529953996: [info] Created uncompressed postings file cranfield-idx/inv/postings.index (197.770000 KB) (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/inverted_index.cpp:148)\n", + " \r", + " > Compressing postings: [> ] 0% ETA 00:00:00 \r", + " > Compressing postings: [===================================] 100% ETA 00:00:00 \n", + "1529953996: [info] Created compressed postings file (168.060000 KB) (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/inverted_index.cpp:279)\n", + "1529953996: [info] Done creating index: cranfield-idx/inv (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/inverted_index.cpp:166)\n" + ] + } + ], + "source": [ + "inv_idx = metapy.index.make_inverted_index('cranfield.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This may take a minute at first, since the index needs to be built. Subsequent calls to `make_inverted_index` with this config file will simply load the index, which will not take any time.\n", + "\n", + "Here's how we can interact with the index object:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1400" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "inv_idx.num_docs()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4137" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "inv_idx.unique_terms()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "87.17857360839844" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "inv_idx.avg_doc_length()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "122050" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "inv_idx.total_corpus_terms()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's search our index. We'll start by creating a ranker:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "ranker = metapy.index.DirichletPrior()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we need a query. Let's create an example query." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "query = metapy.index.Document()\n", + "query.content(\"flow equilibrium\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can use this to search our index like so:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(235, 1.2931444644927979),\n", + " (1251, 1.256299614906311),\n", + " (316, 1.1081531047821045),\n", + " (655, 1.0878994464874268),\n", + " (574, 1.076568841934204)]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "top_docs = ranker.score(inv_idx, query, num_results=5)\n", + "top_docs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are returned a ranked list of *(doc_id, score)* pairs. The scores are from the ranker, which in this case was Okapi BM25. Since the `tutorial.toml` file we created for the cranfield dataset has `store-full-text = true`, we can verify the content of our top documents by inspecting the document metadata field \"content\"." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1. criteria for thermodynamic equilibrium in gas flow . when gases flow at high velocity, the rates of internal processes may not be fast enough to maintain thermodynamic equilibrium . by defining quasi-equilibrium in flow as the condition in which the...\n", + "\n", + "2. on the approach to chemical and vibrational equilibrium behind a strong normal shock wave . the concurrent approach to chemical and vibrational equilibrium of a pure diatomic gas passing through a strong normal shock wave is investigated . it is dem...\n", + "\n", + "3. non-equilibrium flow of an ideal dissociating gas . the theory of an'ideal dissociating'gas developed by lighthill/1957/for conditions of thermodynamic equilibrium is extended to non-equilibrium conditions by postulating a simple rate equation for th...\n", + "\n", + "4. departure from dissociation equilibrium in a hypersonic nozzle . the equations of motion for the flow of an ideal dissociating gas through a nearly conical nozzle have been solved numerically, assuming a simple equation for the rate of dissociation, ...\n", + "\n", + "5. atomic recombination in a hypersonic wind tunnel nozzle . the flow of an ideal dissociating gas through a nearly conical nozzle is considered . the equations of one-dimensional motion are solved numerically assuming a simple rate equation together wi...\n", + "\n" + ] + } + ], + "source": [ + "for num, (d_id, _) in enumerate(top_docs):\n", + " content = inv_idx.metadata(d_id).get('content')\n", + " print(\"{}. {}...\\n\".format(num + 1, content[0:250]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since we have the queries file and relevance judgements, we can do an IR evaluation." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "ev = metapy.index.IREval('cranfield.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will loop over the queries file and add each result to the `IREval` object `ev`." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Query 1 average precision: 0.19\n", + "Query 2 average precision: 0.5433333333333332\n", + "Query 3 average precision: 0.6541666666666666\n", + "Query 4 average precision: 0.5\n", + "Query 5 average precision: 0.35\n", + "Query 6 average precision: 0.0625\n", + "Query 7 average precision: 0.10666666666666666\n", + "Query 8 average precision: 0.0\n", + "Query 9 average precision: 0.6984126984126983\n", + "Query 10 average precision: 0.0625\n", + "Query 11 average precision: 0.028571428571428574\n", + "Query 12 average precision: 0.18\n", + "Query 13 average precision: 0.0\n", + "Query 14 average precision: 0.5\n", + "Query 15 average precision: 0.7\n", + "Query 16 average precision: 0.08333333333333333\n", + "Query 17 average precision: 0.07142857142857142\n", + "Query 18 average precision: 0.3333333333333333\n", + "Query 19 average precision: 0.0\n", + "Query 20 average precision: 0.2685185185185185\n", + "Query 21 average precision: 0.0\n", + "Query 22 average precision: 0.0\n", + "Query 23 average precision: 0.04722222222222222\n", + "Query 24 average precision: 0.3333333333333333\n", + "Query 25 average precision: 0.6507936507936507\n", + "Query 26 average precision: 0.13888888888888887\n", + "Query 27 average precision: 0.0\n", + "Query 28 average precision: 0.0\n", + "Query 29 average precision: 0.14166666666666666\n", + "Query 30 average precision: 0.11904761904761904\n", + "Query 31 average precision: 0.0\n", + "Query 32 average precision: 0.023809523809523808\n", + "Query 33 average precision: 0.5317460317460317\n", + "Query 34 average precision: 0.20555555555555557\n", + "Query 35 average precision: 0.0\n", + "Query 36 average precision: 0.25\n", + "Query 37 average precision: 0.05555555555555555\n", + "Query 38 average precision: 0.01111111111111111\n", + "Query 39 average precision: 0.12857142857142856\n", + "Query 40 average precision: 0.07222222222222222\n", + "Query 41 average precision: 0.7666666666666666\n", + "Query 42 average precision: 0.1638095238095238\n", + "Query 43 average precision: 0.48333333333333334\n", + "Query 44 average precision: 0.0\n", + "Query 45 average precision: 0.155\n", + "Query 46 average precision: 0.5380952380952382\n", + "Query 47 average precision: 0.15083333333333332\n", + "Query 48 average precision: 0.1433333333333333\n", + "Query 49 average precision: 0.0\n", + "Query 50 average precision: 0.0\n", + "Query 51 average precision: 0.16666666666666666\n", + "Query 52 average precision: 0.027777777777777776\n", + "Query 53 average precision: 0.15857142857142856\n", + "Query 54 average precision: 0.05555555555555555\n", + "Query 55 average precision: 0.11499999999999999\n", + "Query 56 average precision: 0.05\n", + "Query 57 average precision: 0.01\n", + "Query 58 average precision: 0.15873015873015872\n", + "Query 59 average precision: 0.03571428571428571\n", + "Query 60 average precision: 0.4666666666666667\n", + "Query 61 average precision: 0.45999999999999996\n", + "Query 62 average precision: 0.0\n", + "Query 63 average precision: 0.0\n", + "Query 64 average precision: 0.5\n", + "Query 65 average precision: 0.0\n", + "Query 66 average precision: 0.0\n", + "Query 67 average precision: 0.0365079365079365\n", + "Query 68 average precision: 0.1\n", + "Query 69 average precision: 0.06666666666666667\n", + "Query 70 average precision: 0.1\n", + "Query 71 average precision: 0.03125\n", + "Query 72 average precision: 0.0\n", + "Query 73 average precision: 0.2861111111111111\n", + "Query 74 average precision: 0.020833333333333332\n", + "Query 75 average precision: 0.03333333333333333\n", + "Query 76 average precision: 0.028571428571428574\n", + "Query 77 average precision: 0.28888888888888886\n", + "Query 78 average precision: 0.6666666666666666\n", + "Query 79 average precision: 0.0\n", + "Query 80 average precision: 0.0\n", + "Query 81 average precision: 0.25\n", + "Query 82 average precision: 0.09\n", + "Query 83 average precision: 0.0625\n", + "Query 84 average precision: 0.3\n", + "Query 85 average precision: 0.05\n", + "Query 86 average precision: 0.41666666666666663\n", + "Query 87 average precision: 0.0\n", + "Query 88 average precision: 0.594047619047619\n", + "Query 89 average precision: 0.075\n", + "Query 90 average precision: 0.19\n", + "Query 91 average precision: 0.0873015873015873\n", + "Query 92 average precision: 0.4726984126984126\n", + "Query 93 average precision: 0.5\n", + "Query 94 average precision: 0.4\n", + "Query 95 average precision: 0.5\n", + "Query 96 average precision: 0.4463095238095239\n", + "Query 97 average precision: 0.15416666666666665\n", + "Query 98 average precision: 0.0\n", + "Query 99 average precision: 0.19642857142857142\n", + "Query 100 average precision: 0.2185185185185185\n", + "Query 101 average precision: 0.6180555555555555\n", + "Query 102 average precision: 0.08333333333333333\n", + "Query 103 average precision: 0.05555555555555555\n", + "Query 104 average precision: 0.1\n", + "Query 105 average precision: 0.35333333333333333\n", + "Query 106 average precision: 0.24666666666666667\n", + "Query 107 average precision: 0.10476190476190476\n", + "Query 108 average precision: 0.6261904761904761\n", + "Query 109 average precision: 0.0\n", + "Query 110 average precision: 0.0\n", + "Query 111 average precision: 0.07619047619047618\n", + "Query 112 average precision: 0.3611111111111111\n", + "Query 113 average precision: 0.10416666666666666\n", + "Query 114 average precision: 0.0\n", + "Query 115 average precision: 0.0\n", + "Query 116 average precision: 0.03333333333333333\n", + "Query 117 average precision: 0.0\n", + "Query 118 average precision: 0.041666666666666664\n", + "Query 119 average precision: 0.5\n", + "Query 120 average precision: 0.17724867724867724\n", + "Query 121 average precision: 0.4768707482993197\n", + "Query 122 average precision: 0.05925925925925926\n", + "Query 123 average precision: 0.0\n", + "Query 124 average precision: 0.0\n", + "Query 125 average precision: 0.02\n", + "Query 126 average precision: 0.20833333333333331\n", + "Query 127 average precision: 0.025\n", + "Query 128 average precision: 0.0\n", + "Query 129 average precision: 0.4773809523809524\n", + "Query 130 average precision: 0.3933333333333333\n", + "Query 131 average precision: 0.09375\n", + "Query 132 average precision: 0.6592063492063491\n", + "Query 133 average precision: 0.12976190476190477\n", + "Query 134 average precision: 0.5\n", + "Query 135 average precision: 0.38690476190476186\n", + "Query 136 average precision: 0.03333333333333333\n", + "Query 137 average precision: 0.1875\n", + "Query 138 average precision: 0.25\n", + "Query 139 average precision: 0.0\n", + "Query 140 average precision: 0.10833333333333334\n", + "Query 141 average precision: 0.05555555555555555\n", + "Query 142 average precision: 0.0\n", + "Query 143 average precision: 0.6111111111111112\n", + "Query 144 average precision: 0.14722222222222223\n", + "Query 145 average precision: 0.07142857142857142\n", + "Query 146 average precision: 0.41666666666666663\n", + "Query 147 average precision: 0.14666666666666667\n", + "Query 148 average precision: 0.125\n", + "Query 149 average precision: 0.18285714285714286\n", + "Query 150 average precision: 1.0\n", + "Query 151 average precision: 0.0\n", + "Query 152 average precision: 0.0\n", + "Query 153 average precision: 0.19999999999999998\n", + "Query 154 average precision: 1.0\n", + "Query 155 average precision: 0.06481481481481481\n", + "Query 156 average precision: 0.6365476190476189\n", + "Query 157 average precision: 0.43809523809523804\n", + "Query 158 average precision: 0.175\n", + "Query 159 average precision: 0.015625\n", + "Query 160 average precision: 0.2\n", + "Query 161 average precision: 0.43333333333333335\n", + "Query 162 average precision: 0.020833333333333332\n", + "Query 163 average precision: 0.21666666666666667\n", + "Query 164 average precision: 0.40208333333333335\n", + "Query 165 average precision: 0.16666666666666666\n", + "Query 166 average precision: 0.0\n", + "Query 167 average precision: 0.325\n", + "Query 168 average precision: 0.08333333333333333\n", + "Query 169 average precision: 0.125\n", + "Query 170 average precision: 0.4611111111111111\n", + "Query 171 average precision: 0.4888888888888889\n", + "Query 172 average precision: 0.5416666666666666\n", + "Query 173 average precision: 0.8333333333333333\n", + "Query 174 average precision: 0.03333333333333333\n", + "Query 175 average precision: 0.02222222222222222\n", + "Query 176 average precision: 0.0\n", + "Query 177 average precision: 0.475\n", + "Query 178 average precision: 0.49166666666666664\n", + "Query 179 average precision: 0.125\n", + "Query 180 average precision: 0.34523809523809523\n", + "Query 181 average precision: 0.2\n", + "Query 182 average precision: 0.7\n", + "Query 183 average precision: 0.5308730158730158\n", + "Query 184 average precision: 0.06938775510204082\n", + "Query 185 average precision: 0.6388888888888888\n", + "Query 186 average precision: 0.016666666666666666\n", + "Query 187 average precision: 0.16666666666666666\n", + "Query 188 average precision: 0.09\n", + "Query 189 average precision: 0.015873015873015872\n", + "Query 190 average precision: 0.1\n", + "Query 191 average precision: 0.014285714285714285\n", + "Query 192 average precision: 0.5\n", + "Query 193 average precision: 0.6481481481481481\n", + "Query 194 average precision: 0.08888888888888889\n", + "Query 195 average precision: 0.1111111111111111\n", + "Query 196 average precision: 0.03333333333333333\n", + "Query 197 average precision: 0.6666666666666666\n", + "Query 198 average precision: 0.3125\n", + "Query 199 average precision: 0.05208333333333333\n", + "Query 200 average precision: 0.24074074074074073\n", + "Query 201 average precision: 0.3\n", + "Query 202 average precision: 0.26\n", + "Query 203 average precision: 0.07222222222222222\n", + "Query 204 average precision: 0.0\n", + "Query 205 average precision: 0.75\n", + "Query 206 average precision: 0.3333333333333333\n", + "Query 207 average precision: 0.15\n", + "Query 208 average precision: 0.6829365079365081\n", + "Query 209 average precision: 0.02\n", + "Query 210 average precision: 0.27777777777777773\n", + "Query 211 average precision: 0.0125\n", + "Query 212 average precision: 0.36666666666666664\n", + "Query 213 average precision: 0.5583333333333333\n", + "Query 214 average precision: 0.08333333333333333\n", + "Query 215 average precision: 0.0\n", + "Query 216 average precision: 0.0\n", + "Query 217 average precision: 0.05833333333333333\n", + "Query 218 average precision: 0.0\n", + "Query 219 average precision: 0.014285714285714285\n", + "Query 220 average precision: 0.05333333333333333\n", + "Query 221 average precision: 0.24333333333333332\n", + "Query 222 average precision: 0.5148148148148147\n", + "Query 223 average precision: 0.44375\n", + "Query 224 average precision: 0.0\n", + "Query 225 average precision: 0.13333333333333333\n" + ] + } + ], + "source": [ + "def evaluate_ranker(ranker, ev, num_results):\n", + " ev.reset_stats()\n", + " with open('data/cranfield/cranfield-queries.txt') as query_file:\n", + " for query_num, line in enumerate(query_file):\n", + " query.content(line.strip())\n", + " results = ranker.score(inv_idx, query, num_results) \n", + " avg_p = ev.avg_p(results, query_num + 1, num_results)\n", + " print(\"Query {} average precision: {}\".format(query_num + 1, avg_p))\n", + " \n", + "evaluate_ranker(ranker, ev, 10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Afterwards, we can get the mean average precision of all the queries." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MAP: 0.21512203955656342\n" + ] + } + ], + "source": [ + "dp_map = ev.map()\n", + "print(\"MAP: {}\".format(dp_map))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's use the two-component mixture model we discussed as an implementation of pseudo-feedback for retrieval and see if it helps improve performance. The actual ranking function used here is KL-divergence, where the query model is adjusted to include pseudo-feedback from the retrieved documents.\n", + "\n", + "In order to work, the ranker needs to be able to quickly determine what words were used in the feedback document set. The `InvertedIndex` does not provide fast access to this (since it is a mapping from term to documents, rather than from documents to terms), so we will want to first create a `ForwardIndex` to get the document -> terms mapping." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Counting lines in file: [> ] 0% ETA 00:00:00 \r", + " > Counting lines in file: [=================================] 100% ETA 00:00:00 \n", + "1529954010: [info] Creating forward index: cranfield-idx/fwd (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/forward_index.cpp:239)\n", + " \r", + " > Tokenizing Docs: [> ] 0% ETA 00:00:00 \n", + "1529954010: [warning] Empty document (id = 470) generated! (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/forward_index.cpp:335)\n", + " \n", + "1529954010: [warning] Empty document (id = 994) generated! (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/forward_index.cpp:335)\n", + " \r", + " > Tokenizing Docs: [========================================] 100% ETA 00:00:00 \n", + " \r", + " > Merging: [> ] 0% ETA 00:00:00 \r", + " > Merging: [================================================] 100% ETA 00:00:00 \n", + "1529954010: [info] Done creating index: cranfield-idx/fwd (/tmp/pip-req-build-m473bt6z/deps/meta/src/index/forward_index.cpp:278)\n" + ] + } + ], + "source": [ + "fwd_idx = metapy.index.make_forward_index('cranfield.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can construct the KL-divergence pseudo-feedback ranker. The main components are:\n", + "1. The forward index\n", + "2. A base language-model ranker (here we'll use `DirichletPrior`)\n", + "3. $\\alpha$, the query interpolation parameter (how strongly do we prefer terms from the feedback model? default 0.5)\n", + "4. $\\lambda$, the language-model interpolation parameter (how strong is the background model in the two-component mixture? default 0.5)\n", + "5. $k$, the number of documents to retrieve for the feedback set (default 10)\n", + "6. `max_terms`, the number of terms from the feedback model to incorporate into the new query model (default 50) " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "feedback = metapy.index.KLDivergencePRF(fwd_idx, metapy.index.DirichletPrior())" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Query 1 average precision: 0.13999999999999999\n", + "Query 2 average precision: 0.524047619047619\n", + "Query 3 average precision: 0.6642857142857143\n", + "Query 4 average precision: 0.5\n", + "Query 5 average precision: 0.6875\n", + "Query 6 average precision: 0.0625\n", + "Query 7 average precision: 0.11666666666666665\n", + "Query 8 average precision: 0.0\n", + "Query 9 average precision: 0.49999999999999994\n", + "Query 10 average precision: 0.0625\n", + "Query 11 average precision: 0.023809523809523808\n", + "Query 12 average precision: 0.15714285714285714\n", + "Query 13 average precision: 0.0\n", + "Query 14 average precision: 0.5\n", + "Query 15 average precision: 0.6428571428571428\n", + "Query 16 average precision: 0.05555555555555555\n", + "Query 17 average precision: 0.05\n", + "Query 18 average precision: 0.16666666666666666\n", + "Query 19 average precision: 0.0\n", + "Query 20 average precision: 0.33201058201058203\n", + "Query 21 average precision: 0.0\n", + "Query 22 average precision: 0.0\n", + "Query 23 average precision: 0.075\n", + "Query 24 average precision: 0.38888888888888884\n", + "Query 25 average precision: 0.7530864197530864\n", + "Query 26 average precision: 0.061111111111111116\n", + "Query 27 average precision: 0.0\n", + "Query 28 average precision: 0.0\n", + "Query 29 average precision: 0.091005291005291\n", + "Query 30 average precision: 0.19999999999999998\n", + "Query 31 average precision: 0.0\n", + "Query 32 average precision: 0.023809523809523808\n", + "Query 33 average precision: 0.6666666666666666\n", + "Query 34 average precision: 0.21031746031746032\n", + "Query 35 average precision: 0.03333333333333333\n", + "Query 36 average precision: 0.6\n", + "Query 37 average precision: 0.1111111111111111\n", + "Query 38 average precision: 0.02\n", + "Query 39 average precision: 0.12857142857142856\n", + "Query 40 average precision: 0.07222222222222222\n", + "Query 41 average precision: 0.7916666666666666\n", + "Query 42 average precision: 0.14523809523809522\n", + "Query 43 average precision: 0.3333333333333333\n", + "Query 44 average precision: 0.0\n", + "Query 45 average precision: 0.13999999999999999\n", + "Query 46 average precision: 0.49071428571428566\n", + "Query 47 average precision: 0.14027777777777778\n", + "Query 48 average precision: 0.1433333333333333\n", + "Query 49 average precision: 0.0\n", + "Query 50 average precision: 0.0\n", + "Query 51 average precision: 0.22999999999999998\n", + "Query 52 average precision: 0.08125\n", + "Query 53 average precision: 0.15\n", + "Query 54 average precision: 0.037037037037037035\n", + "Query 55 average precision: 0.11833333333333333\n", + "Query 56 average precision: 0.05\n", + "Query 57 average precision: 0.0125\n", + "Query 58 average precision: 0.16666666666666666\n", + "Query 59 average precision: 0.03571428571428571\n", + "Query 60 average precision: 0.45999999999999996\n", + "Query 61 average precision: 0.4083333333333333\n", + "Query 62 average precision: 0.0\n", + "Query 63 average precision: 0.0\n", + "Query 64 average precision: 0.5\n", + "Query 65 average precision: 0.0\n", + "Query 66 average precision: 0.0\n", + "Query 67 average precision: 0.03111111111111111\n", + "Query 68 average precision: 0.06666666666666667\n", + "Query 69 average precision: 0.2\n", + "Query 70 average precision: 0.1\n", + "Query 71 average precision: 0.041666666666666664\n", + "Query 72 average precision: 0.0\n", + "Query 73 average precision: 0.38916666666666666\n", + "Query 74 average precision: 0.05555555555555555\n", + "Query 75 average precision: 0.02222222222222222\n", + "Query 76 average precision: 0.02040816326530612\n", + "Query 77 average precision: 0.34027777777777773\n", + "Query 78 average precision: 0.7916666666666666\n", + "Query 79 average precision: 0.0\n", + "Query 80 average precision: 0.0\n", + "Query 81 average precision: 0.25\n", + "Query 82 average precision: 0.07333333333333333\n", + "Query 83 average precision: 0.05\n", + "Query 84 average precision: 0.2375\n", + "Query 85 average precision: 0.05\n", + "Query 86 average precision: 0.30952380952380953\n", + "Query 87 average precision: 0.0\n", + "Query 88 average precision: 0.594047619047619\n", + "Query 89 average precision: 0.10833333333333334\n", + "Query 90 average precision: 0.1875\n", + "Query 91 average precision: 0.1111111111111111\n", + "Query 92 average precision: 0.5747619047619048\n", + "Query 93 average precision: 0.5\n", + "Query 94 average precision: 0.4\n", + "Query 95 average precision: 0.5\n", + "Query 96 average precision: 0.6042063492063492\n", + "Query 97 average precision: 0.24166666666666664\n", + "Query 98 average precision: 0.0\n", + "Query 99 average precision: 0.25\n", + "Query 100 average precision: 0.25555555555555554\n", + "Query 101 average precision: 0.5444444444444444\n", + "Query 102 average precision: 0.08333333333333333\n", + "Query 103 average precision: 0.1\n", + "Query 104 average precision: 0.1\n", + "Query 105 average precision: 0.4333333333333333\n", + "Query 106 average precision: 0.3746031746031746\n", + "Query 107 average precision: 0.1619047619047619\n", + "Query 108 average precision: 0.5488095238095239\n", + "Query 109 average precision: 0.0\n", + "Query 110 average precision: 0.0\n", + "Query 111 average precision: 0.014285714285714287\n", + "Query 112 average precision: 0.3611111111111111\n", + "Query 113 average precision: 0.10555555555555556\n", + "Query 114 average precision: 0.0\n", + "Query 115 average precision: 0.0\n", + "Query 116 average precision: 0.02857142857142857\n", + "Query 117 average precision: 0.0\n", + "Query 118 average precision: 0.037037037037037035\n", + "Query 119 average precision: 0.3333333333333333\n", + "Query 120 average precision: 0.1527777777777778\n", + "Query 121 average precision: 0.42857142857142855\n", + "Query 122 average precision: 0.07777777777777778\n", + "Query 123 average precision: 0.0\n", + "Query 124 average precision: 0.0\n", + "Query 125 average precision: 0.03333333333333333\n", + "Query 126 average precision: 0.20833333333333331\n", + "Query 127 average precision: 0.02222222222222222\n", + "Query 128 average precision: 0.0\n", + "Query 129 average precision: 0.6738095238095239\n", + "Query 130 average precision: 0.55\n", + "Query 131 average precision: 0.18333333333333335\n", + "Query 132 average precision: 0.7254365079365078\n", + "Query 133 average precision: 0.18010204081632653\n", + "Query 134 average precision: 0.5\n", + "Query 135 average precision: 0.37351190476190477\n", + "Query 136 average precision: 0.047619047619047616\n", + "Query 137 average precision: 0.1125\n", + "Query 138 average precision: 0.5\n", + "Query 139 average precision: 0.0\n", + "Query 140 average precision: 0.10833333333333334\n", + "Query 141 average precision: 0.041666666666666664\n", + "Query 142 average precision: 0.0\n", + "Query 143 average precision: 0.39285714285714285\n", + "Query 144 average precision: 0.20555555555555557\n", + "Query 145 average precision: 0.07142857142857142\n", + "Query 146 average precision: 0.30952380952380953\n", + "Query 147 average precision: 0.14999999999999997\n", + "Query 148 average precision: 0.075\n", + "Query 149 average precision: 0.17666666666666667\n", + "Query 150 average precision: 1.0\n", + "Query 151 average precision: 0.0\n", + "Query 152 average precision: 0.0\n", + "Query 153 average precision: 0.2571428571428571\n", + "Query 154 average precision: 1.0\n", + "Query 155 average precision: 0.06666666666666667\n", + "Query 156 average precision: 0.7532142857142856\n", + "Query 157 average precision: 0.40555555555555556\n", + "Query 158 average precision: 0.19375\n", + "Query 159 average precision: 0.020833333333333332\n", + "Query 160 average precision: 0.2\n", + "Query 161 average precision: 0.3611111111111111\n", + "Query 162 average precision: 0.013888888888888888\n", + "Query 163 average precision: 0.19444444444444442\n", + "Query 164 average precision: 0.40208333333333335\n", + "Query 165 average precision: 0.125\n", + "Query 166 average precision: 0.0\n", + "Query 167 average precision: 0.5\n", + "Query 168 average precision: 0.08333333333333333\n", + "Query 169 average precision: 0.25\n", + "Query 170 average precision: 0.46990740740740744\n", + "Query 171 average precision: 0.5555555555555555\n", + "Query 172 average precision: 0.5583333333333333\n", + "Query 173 average precision: 0.7\n", + "Query 174 average precision: 0.03333333333333333\n", + "Query 175 average precision: 0.02857142857142857\n", + "Query 176 average precision: 0.0\n", + "Query 177 average precision: 0.475\n", + "Query 178 average precision: 0.75\n", + "Query 179 average precision: 0.25\n", + "Query 180 average precision: 0.3880952380952381\n", + "Query 181 average precision: 0.1\n", + "Query 182 average precision: 0.7\n", + "Query 183 average precision: 0.6842063492063492\n", + "Query 184 average precision: 0.05215419501133787\n", + "Query 185 average precision: 0.6296296296296297\n", + "Query 186 average precision: 0.04722222222222222\n", + "Query 187 average precision: 0.125\n", + "Query 188 average precision: 0.19\n", + "Query 189 average precision: 0.022222222222222223\n", + "Query 190 average precision: 0.05\n", + "Query 191 average precision: 0.05357142857142857\n", + "Query 192 average precision: 0.575\n", + "Query 193 average precision: 0.6565255731922398\n", + "Query 194 average precision: 0.19999999999999998\n", + "Query 195 average precision: 0.3333333333333333\n", + "Query 196 average precision: 0.05\n", + "Query 197 average precision: 0.6666666666666666\n", + "Query 198 average precision: 0.1875\n", + "Query 199 average precision: 0.048611111111111105\n", + "Query 200 average precision: 0.40740740740740744\n", + "Query 201 average precision: 0.33999999999999997\n", + "Query 202 average precision: 0.22666666666666666\n", + "Query 203 average precision: 0.07333333333333333\n", + "Query 204 average precision: 0.0\n", + "Query 205 average precision: 0.7\n", + "Query 206 average precision: 0.38888888888888884\n", + "Query 207 average precision: 0.3\n", + "Query 208 average precision: 0.7345238095238096\n", + "Query 209 average precision: 0.03333333333333333\n", + "Query 210 average precision: 0.27777777777777773\n", + "Query 211 average precision: 0.025\n", + "Query 212 average precision: 0.36666666666666664\n", + "Query 213 average precision: 0.49309523809523814\n", + "Query 214 average precision: 0.08333333333333333\n", + "Query 215 average precision: 0.0\n", + "Query 216 average precision: 0.0\n", + "Query 217 average precision: 0.07857142857142857\n", + "Query 218 average precision: 0.0\n", + "Query 219 average precision: 0.014285714285714285\n", + "Query 220 average precision: 0.07333333333333333\n", + "Query 221 average precision: 0.24333333333333332\n", + "Query 222 average precision: 0.5238095238095238\n", + "Query 223 average precision: 0.4583333333333333\n", + "Query 224 average precision: 0.0\n", + "Query 225 average precision: 0.15\n" + ] + } + ], + "source": [ + "evaluate_ranker(feedback, ev, 10)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Feedback MAP: 0.22816526133086987\n", + "DP MAP: 0.21512203955656342\n" + ] + } + ], + "source": [ + "fb_map = ev.map()\n", + "print(\"Feedback MAP: {}\".format(fb_map))\n", + "print(\"DP MAP: {}\".format(dp_map))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/metapy/tutorials/sigir18-topic-models/sigir18-topic-models.ipynb b/metapy/tutorials/sigir18-topic-models/sigir18-topic-models.ipynb new file mode 100644 index 0000000000..84ad41f4c4 --- /dev/null +++ b/metapy/tutorials/sigir18-topic-models/sigir18-topic-models.ipynb @@ -0,0 +1,1188 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Exercise 2: Topic Model Inference in LDA" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, let's import the Python bindings for MeTA:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import metapy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you don't have `metapy` installed, you can install it with a\n", + "\n", + "```bash\n", + "pip install metapy\n", + "```\n", + "\n", + "on the command line on Linux, macOS, or Windows for either Python 2.7 or Python 3.x. (I will be using Python 3.6 in this tutorial.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Double-check that you are running the latest version. Right now, that should be `0.2.10`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'0.2.11'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "metapy.__version__" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's set MeTA to log to standard error so we can see progress output for long-running commands. (Only do this once, or you'll get double the output.)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "metapy.log_to_stderr()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's download all of the files we need for the tutorial." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import urllib.request\n", + "import os\n", + "import tarfile\n", + "\n", + "if not os.path.exists('sigir18-tutorial.tar.gz'):\n", + " urllib.request.urlretrieve('https://meta-toolkit.org/data/2018-06-25/sigir18-tutorial.tar.gz',\n", + " 'sigir18-tutorial.tar.gz')\n", + " \n", + "if not os.path.exists('data'):\n", + " with tarfile.open('sigir18-tutorial.tar.gz', 'r:gz') as files:\n", + " files.extractall()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The tutorial files come with a dataset consisting of four years of NIPS proceedings (full text): 2002, 2007, 2012, and 2017.\n", + "\n", + "To start, we first want to understand what topics are being discussed in NIPS in these for years. To do that, we'll first index the dataset in the `ForwardIndex` format (we want to map documents to the terms that they contain)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1530029662: [info] Creating forward index: nips-idx/fwd (/tmp/pip-req-build-s8007td9/deps/meta/src/index/forward_index.cpp:239)\n", + " > Tokenizing Docs: [===================================> ] 88% ETA 00:00:00 \n", + "1530029664: [warning] Empty document (id = 1435) generated! (/tmp/pip-req-build-s8007td9/deps/meta/src/index/forward_index.cpp:335)\n", + " > Tokenizing Docs: [========================================] 100% ETA 00:00:00 \n", + " > Merging: [================================================] 100% ETA 00:00:00 \n", + "1530029664: [info] Done creating index: nips-idx/fwd (/tmp/pip-req-build-s8007td9/deps/meta/src/index/forward_index.cpp:278)\n" + ] + } + ], + "source": [ + "fidx = metapy.index.make_forward_index('nips.toml')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's load in all of the documents into memory so we can start to infer a topic model. I'm going to load them in as a `MulticlassDataset` because each document here has been associated with a label (the year it came from), but you could also load them in as just a standard `Dataset` with no associated labels if you don't plan to use them." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Loading instances into memory: [> ] 0% ETA 00:00:00 \r", + " > Loading instances into memory: [==========================] 100% ETA 00:00:00 \n" + ] + } + ], + "source": [ + "dset = metapy.classify.MulticlassDataset(fidx)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the documents loaded into memory, we can start to run LDA inference on them to infer the topics and their coverage in each of the documents. There are several choices for inference algorithm in MeTA, so in general you can just pick your favorite. Here, I'm going to pick a parallelized version of Gibbs sampling.\n", + "\n", + "The below will run the sampler for either 1000 iterations or until the log likelihood ($\\log P(W \\mid Z)$) stabilizes, whichever comes first. (If you want to disable the convergence checking and just run the sampler for a fixed number of iterations, you can add the parameter `convergence=0`.)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Initialization log likelihood (log P(W|Z)): -3.05507e+07 \n", + "Iteration 1 log likelihood (log P(W|Z)): -3.05155e+07 \n", + "Iteration 2 log likelihood (log P(W|Z)): -3.04318e+07 \n", + "Iteration 3 log likelihood (log P(W|Z)): -3.03566e+07 \n", + "Iteration 4 log likelihood (log P(W|Z)): -3.02892e+07 \n", + "Iteration 5 log likelihood (log P(W|Z)): -3.0229e+07 \n", + "Iteration 6 log likelihood (log P(W|Z)): -3.01748e+07 \n", + "Iteration 7 log likelihood (log P(W|Z)): -3.0123e+07 \n", + "Iteration 8 log likelihood (log P(W|Z)): -3.00742e+07 \n", + "Iteration 9 log likelihood (log P(W|Z)): -3.00266e+07 \n", + "Iteration 10 log likelihood (log P(W|Z)): -2.99788e+07 \n", + "Iteration 11 log likelihood (log P(W|Z)): -2.99365e+07 \n", + "Iteration 12 log likelihood (log P(W|Z)): -2.98953e+07 \n", + "Iteration 13 log likelihood (log P(W|Z)): -2.98584e+07 \n", + "Iteration 14 log likelihood (log P(W|Z)): -2.9823e+07 \n", + "Iteration 15 log likelihood (log P(W|Z)): -2.97915e+07 \n", + "Iteration 16 log likelihood (log P(W|Z)): -2.9764e+07 \n", + "Iteration 17 log likelihood (log P(W|Z)): -2.97375e+07 \n", + "Iteration 18 log likelihood (log P(W|Z)): -2.97107e+07 \n", + "Iteration 19 log likelihood (log P(W|Z)): -2.96852e+07 \n", + "Iteration 20 log likelihood (log P(W|Z)): -2.96599e+07 \n", + "Iteration 21 log likelihood (log P(W|Z)): -2.96358e+07 \n", + "Iteration 22 log likelihood (log P(W|Z)): -2.9616e+07 \n", + "Iteration 23 log likelihood (log P(W|Z)): -2.95975e+07 \n", + "Iteration 24 log likelihood (log P(W|Z)): -2.95787e+07 \n", + "Iteration 25 log likelihood (log P(W|Z)): -2.95601e+07 \n", + "Iteration 26 log likelihood (log P(W|Z)): -2.95423e+07 \n", + "Iteration 27 log likelihood (log P(W|Z)): -2.95256e+07 \n", + "Iteration 28 log likelihood (log P(W|Z)): -2.95089e+07 \n", + "Iteration 29 log likelihood (log P(W|Z)): -2.94934e+07 \n", + "Iteration 30 log likelihood (log P(W|Z)): -2.94771e+07 \n", + "Iteration 31 log likelihood (log P(W|Z)): -2.94604e+07 \n", + "Iteration 32 log likelihood (log P(W|Z)): -2.94411e+07 \n", + "Iteration 33 log likelihood (log P(W|Z)): -2.94258e+07 \n", + "Iteration 34 log likelihood (log P(W|Z)): -2.94121e+07 \n", + "Iteration 35 log likelihood (log P(W|Z)): -2.93981e+07 \n", + "Iteration 36 log likelihood (log P(W|Z)): -2.93842e+07 \n", + "Iteration 37 log likelihood (log P(W|Z)): -2.93683e+07 \n", + "Iteration 38 log likelihood (log P(W|Z)): -2.93535e+07 \n", + "Iteration 39 log likelihood (log P(W|Z)): -2.93385e+07 \n", + "Iteration 40 log likelihood (log P(W|Z)): -2.93255e+07 \n", + "Iteration 41 log likelihood (log P(W|Z)): -2.93134e+07 \n", + "Iteration 42 log likelihood (log P(W|Z)): -2.93024e+07 \n", + "Iteration 43 log likelihood (log P(W|Z)): -2.92893e+07 \n", + "Iteration 44 log likelihood (log P(W|Z)): -2.92773e+07 \n", + "Iteration 45 log likelihood (log P(W|Z)): -2.92652e+07 \n", + "Iteration 46 log likelihood (log P(W|Z)): -2.92528e+07 \n", + "Iteration 47 log likelihood (log P(W|Z)): -2.92426e+07 \n", + "Iteration 48 log likelihood (log P(W|Z)): -2.92319e+07 \n", + "Iteration 49 log likelihood (log P(W|Z)): -2.92214e+07 \n", + "Iteration 50 log likelihood (log P(W|Z)): -2.92125e+07 \n", + "Iteration 51 log likelihood (log P(W|Z)): -2.92024e+07 \n", + "Iteration 52 log likelihood (log P(W|Z)): -2.91915e+07 \n", + "Iteration 53 log likelihood (log P(W|Z)): -2.91817e+07 \n", + "Iteration 54 log likelihood (log P(W|Z)): -2.91718e+07 \n", + "Iteration 55 log likelihood (log P(W|Z)): -2.91624e+07 \n", + "Iteration 56 log likelihood (log P(W|Z)): -2.91524e+07 \n", + "Iteration 57 log likelihood (log P(W|Z)): -2.91437e+07 \n", + "Iteration 58 log likelihood (log P(W|Z)): -2.9136e+07 \n", + "Iteration 59 log likelihood (log P(W|Z)): -2.91267e+07 \n", + "Iteration 60 log likelihood (log P(W|Z)): -2.91166e+07 \n", + "Iteration 61 log likelihood (log P(W|Z)): -2.91116e+07 \n", + "Iteration 62 log likelihood (log P(W|Z)): -2.91032e+07 \n", + "Iteration 63 log likelihood (log P(W|Z)): -2.90974e+07 \n", + "Iteration 64 log likelihood (log P(W|Z)): -2.90928e+07 \n", + "Iteration 65 log likelihood (log P(W|Z)): -2.90862e+07 \n", + "Iteration 66 log likelihood (log P(W|Z)): -2.90802e+07 \n", + "Iteration 67 log likelihood (log P(W|Z)): -2.9076e+07 \n", + "Iteration 68 log likelihood (log P(W|Z)): -2.90701e+07 \n", + "Iteration 69 log likelihood (log P(W|Z)): -2.90642e+07 \n", + "Iteration 70 log likelihood (log P(W|Z)): -2.90588e+07 \n", + "Iteration 71 log likelihood (log P(W|Z)): -2.90521e+07 \n", + "Iteration 72 log likelihood (log P(W|Z)): -2.90461e+07 \n", + "Iteration 73 log likelihood (log P(W|Z)): -2.90403e+07 \n", + "Iteration 74 log likelihood (log P(W|Z)): -2.90336e+07 \n", + "Iteration 75 log likelihood (log P(W|Z)): -2.90275e+07 \n", + "Iteration 76 log likelihood (log P(W|Z)): -2.9024e+07 \n", + "Iteration 77 log likelihood (log P(W|Z)): -2.90169e+07 \n", + "Iteration 78 log likelihood (log P(W|Z)): -2.90139e+07 \n", + "Iteration 79 log likelihood (log P(W|Z)): -2.90059e+07 \n", + "Iteration 80 log likelihood (log P(W|Z)): -2.90029e+07 \n", + "Iteration 81 log likelihood (log P(W|Z)): -2.89997e+07 \n", + "Iteration 82 log likelihood (log P(W|Z)): -2.8994e+07 \n", + "Iteration 83 log likelihood (log P(W|Z)): -2.89882e+07 \n", + "Iteration 84 log likelihood (log P(W|Z)): -2.89821e+07 \n", + "Iteration 85 log likelihood (log P(W|Z)): -2.89808e+07 \n", + "Iteration 86 log likelihood (log P(W|Z)): -2.89763e+07 \n", + "Iteration 87 log likelihood (log P(W|Z)): -2.89707e+07 \n", + "Iteration 88 log likelihood (log P(W|Z)): -2.89659e+07 \n", + "Iteration 89 log likelihood (log P(W|Z)): -2.89618e+07 \n", + "Iteration 90 log likelihood (log P(W|Z)): -2.89592e+07 \n", + "Iteration 91 log likelihood (log P(W|Z)): -2.89556e+07 \n", + "Iteration 92 log likelihood (log P(W|Z)): -2.89521e+07 \n", + "Iteration 93 log likelihood (log P(W|Z)): -2.89499e+07 \n", + "Iteration 94 log likelihood (log P(W|Z)): -2.89452e+07 \n", + "Iteration 95 log likelihood (log P(W|Z)): -2.8943e+07 \n", + "Iteration 96 log likelihood (log P(W|Z)): -2.89395e+07 \n", + "Iteration 97 log likelihood (log P(W|Z)): -2.89344e+07 \n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Iteration 98 log likelihood (log P(W|Z)): -2.89316e+07 \n", + "Iteration 99 log likelihood (log P(W|Z)): -2.89272e+07 \n", + "Iteration 100 log likelihood (log P(W|Z)): -2.89221e+07 \n", + "Iteration 101 log likelihood (log P(W|Z)): -2.89194e+07 \n", + "Iteration 102 log likelihood (log P(W|Z)): -2.89157e+07 \n", + "Iteration 103 log likelihood (log P(W|Z)): -2.89128e+07 \n", + "Iteration 104 log likelihood (log P(W|Z)): -2.89098e+07 \n", + "Iteration 105 log likelihood (log P(W|Z)): -2.89056e+07 \n", + "Iteration 106 log likelihood (log P(W|Z)): -2.89036e+07 \n", + "Iteration 107 log likelihood (log P(W|Z)): -2.88998e+07 \n", + "Iteration 108 log likelihood (log P(W|Z)): -2.88973e+07 \n", + "Iteration 109 log likelihood (log P(W|Z)): -2.88933e+07 \n", + "Iteration 110 log likelihood (log P(W|Z)): -2.88906e+07 \n", + "Iteration 111 log likelihood (log P(W|Z)): -2.88857e+07 \n", + "Iteration 112 log likelihood (log P(W|Z)): -2.88837e+07 \n", + "Iteration 113 log likelihood (log P(W|Z)): -2.88801e+07 \n", + "Iteration 114 log likelihood (log P(W|Z)): -2.88774e+07 \n", + "Iteration 115 log likelihood (log P(W|Z)): -2.8874e+07 \n", + "Iteration 116 log likelihood (log P(W|Z)): -2.88712e+07 \n", + "Iteration 117 log likelihood (log P(W|Z)): -2.88682e+07 \n", + "Iteration 118 log likelihood (log P(W|Z)): -2.88675e+07 \n", + "Iteration 119 log likelihood (log P(W|Z)): -2.88655e+07 \n", + "Iteration 120 log likelihood (log P(W|Z)): -2.88631e+07 \n", + "Iteration 121 log likelihood (log P(W|Z)): -2.88604e+07 \n", + "Iteration 122 log likelihood (log P(W|Z)): -2.886e+07 \n", + "Iteration 123 log likelihood (log P(W|Z)): -2.88581e+07 \n", + "Iteration 124 log likelihood (log P(W|Z)): -2.88562e+07 \n", + "Iteration 125 log likelihood (log P(W|Z)): -2.88539e+07 \n", + "Iteration 126 log likelihood (log P(W|Z)): -2.88511e+07 \n", + "Iteration 127 log likelihood (log P(W|Z)): -2.88496e+07 \n", + "Iteration 128 log likelihood (log P(W|Z)): -2.88483e+07 \n", + "Iteration 129 log likelihood (log P(W|Z)): -2.88485e+07 \n", + "Iteration 130 log likelihood (log P(W|Z)): -2.88463e+07 \n", + "Iteration 131 log likelihood (log P(W|Z)): -2.88444e+07 \n", + "Iteration 132 log likelihood (log P(W|Z)): -2.8841e+07 \n", + "Iteration 133 log likelihood (log P(W|Z)): -2.88389e+07 \n", + "Iteration 134 log likelihood (log P(W|Z)): -2.8839e+07 \n", + "Iteration 135 log likelihood (log P(W|Z)): -2.88364e+07 \n", + "Iteration 136 log likelihood (log P(W|Z)): -2.88347e+07 \n", + "Iteration 137 log likelihood (log P(W|Z)): -2.8835e+07 \n", + "Iteration 138 log likelihood (log P(W|Z)): -2.88348e+07 \n", + "Iteration 139 log likelihood (log P(W|Z)): -2.8833e+07 \n", + "Iteration 140 log likelihood (log P(W|Z)): -2.88309e+07 \n", + "Iteration 141 log likelihood (log P(W|Z)): -2.8828e+07 \n", + "Iteration 142 log likelihood (log P(W|Z)): -2.8827e+07 \n", + "Iteration 143 log likelihood (log P(W|Z)): -2.88244e+07 \n", + "Iteration 144 log likelihood (log P(W|Z)): -2.88224e+07 \n", + "Iteration 145 log likelihood (log P(W|Z)): -2.88207e+07 \n", + "Iteration 146 log likelihood (log P(W|Z)): -2.88156e+07 \n", + "Iteration 147 log likelihood (log P(W|Z)): -2.88159e+07 \n", + "Iteration 148 log likelihood (log P(W|Z)): -2.88156e+07 \n", + "Iteration 149 log likelihood (log P(W|Z)): -2.88144e+07 \n", + "Iteration 150 log likelihood (log P(W|Z)): -2.88137e+07 \n", + "Iteration 151 log likelihood (log P(W|Z)): -2.88135e+07 \n", + "Iteration 152 log likelihood (log P(W|Z)): -2.8813e+07 \n", + "Iteration 153 log likelihood (log P(W|Z)): -2.88128e+07 \n", + "Iteration 154 log likelihood (log P(W|Z)): -2.88114e+07 \n", + "Iteration 155 log likelihood (log P(W|Z)): -2.88099e+07 \n", + "Iteration 156 log likelihood (log P(W|Z)): -2.88091e+07 \n", + "Iteration 157 log likelihood (log P(W|Z)): -2.88062e+07 \n", + "Iteration 158 log likelihood (log P(W|Z)): -2.88021e+07 \n", + "Iteration 159 log likelihood (log P(W|Z)): -2.88032e+07 \n", + "Iteration 160 log likelihood (log P(W|Z)): -2.88007e+07 \n", + "Iteration 161 log likelihood (log P(W|Z)): -2.88005e+07 \n", + "Iteration 162 log likelihood (log P(W|Z)): -2.87996e+07 \n", + "Iteration 163 log likelihood (log P(W|Z)): -2.87982e+07 \n", + "Iteration 164 log likelihood (log P(W|Z)): -2.87974e+07 \n", + "Iteration 165 log likelihood (log P(W|Z)): -2.87959e+07 \n", + "Iteration 166 log likelihood (log P(W|Z)): -2.8795e+07 \n", + "Iteration 167 log likelihood (log P(W|Z)): -2.87936e+07 \n", + "Iteration 168 log likelihood (log P(W|Z)): -2.87928e+07 \n", + "Iteration 169 log likelihood (log P(W|Z)): -2.87938e+07 \n", + "Iteration 170 log likelihood (log P(W|Z)): -2.87925e+07 \n", + "Iteration 171 log likelihood (log P(W|Z)): -2.87933e+07 \n", + "Iteration 172 log likelihood (log P(W|Z)): -2.87899e+07 \n", + "Iteration 173 log likelihood (log P(W|Z)): -2.8791e+07 \n", + "Iteration 174 log likelihood (log P(W|Z)): -2.8792e+07 \n", + "Iteration 175 log likelihood (log P(W|Z)): -2.87905e+07 \n", + "Iteration 176 log likelihood (log P(W|Z)): -2.8789e+07 \n", + "Iteration 177 log likelihood (log P(W|Z)): -2.87893e+07 \n", + "Iteration 178 log likelihood (log P(W|Z)): -2.87886e+07 \n", + "Iteration 179 log likelihood (log P(W|Z)): -2.87889e+07 \n", + "Iteration 180 log likelihood (log P(W|Z)): -2.87903e+07 \n", + "Iteration 181 log likelihood (log P(W|Z)): -2.87883e+07 \n", + "Iteration 182 log likelihood (log P(W|Z)): -2.87883e+07 \n", + " Found convergence after 182 iterations!\n", + "1530029871: [info] Finished maximum iterations, or found convergence! (/tmp/pip-req-build-s8007td9/deps/meta/src/topics/lda_gibbs.cpp:77)\n" + ] + } + ], + "source": [ + "model = metapy.topics.LDAParallelGibbs(docs=dset, num_topics=10, alpha=0.1, beta=0.1)\n", + "model.run(num_iters=1000)\n", + "model.save('lda-pgibbs-nips')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Once the above converges, it will save the results to disk. We can load the results into memory for inspection by loading an instance of the `TopicModel` class:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Loading topic term probabilities: [==> ] 10% ETA 00:00:00 \r", + " > Loading topic term probabilities: [=======================] 100% ETA 00:00:00 \n", + " \r", + " > Loading document topic probabilities: [> ] 0% ETA 00:00:00 \r", + " > Loading document topic probabilities: [===================] 100% ETA 00:00:00 \n" + ] + } + ], + "source": [ + "model = metapy.topics.TopicModel('lda-pgibbs-nips')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What do the topics discussed in NIPS over the last two decades roughly look like?" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 1:\n", + "model: 0.047845971473469015\n", + "item: 0.036164145122550555\n", + "topic: 0.03582248886330763\n", + "document: 0.0301900041003383\n", + "latent: 0.029632168260620255\n", + "word: 0.02883241321447034\n", + "user: 0.0262748217085278\n", + "languag: 0.021573178212931057\n", + "lda: 0.014349119364181297\n", + "dirichlet: 0.013994334038283054\n", + "======\n", + "\n", + "Topic 2:\n", + "neuron: 0.10418809366208093\n", + "spike: 0.07989410305538147\n", + "stimulus: 0.03402944466933788\n", + "respons: 0.027507819831649183\n", + "cell: 0.024650823093126214\n", + "signal: 0.023464992947839394\n", + "brain: 0.021329972080580163\n", + "time: 0.017871200820055985\n", + "fire: 0.017004659525601817\n", + "stimuli: 0.016437347395342597\n", + "======\n", + "\n", + "Topic 3:\n", + "polici: 0.18494968655605182\n", + "action: 0.09615364214854322\n", + "reward: 0.08377584211666766\n", + "agent: 0.0808785827262104\n", + "game: 0.05217837257413512\n", + "state: 0.04843198689741257\n", + "reinforc: 0.04066073218825473\n", + "trajectori: 0.03331838788594098\n", + "mdp: 0.02327701848342051\n", + "player: 0.022277731661894288\n", + "======\n", + "\n", + "Topic 4:\n", + "kernel: 0.058391015341538656\n", + "label: 0.05470488694787862\n", + "classifi: 0.04543920685948777\n", + "classif: 0.031377691511149046\n", + "featur: 0.025877748375414726\n", + "train: 0.02553568880708937\n", + "svm: 0.022467854412508627\n", + "loss: 0.02242496964410883\n", + "data: 0.01836611529415411\n", + "class: 0.015976898254645416\n", + "======\n", + "\n", + "Topic 5:\n", + "posterior: 0.043363904458780314\n", + "estim: 0.039974266551518416\n", + "distribut: 0.037820339074187546\n", + "gaussian: 0.03719766917650302\n", + "model: 0.026377288657187144\n", + "densiti: 0.026100306065981422\n", + "log: 0.025795145745510784\n", + "bayesian: 0.025720736258683725\n", + "likelihood: 0.02534425739469013\n", + "infer: 0.023800936808848146\n", + "======\n", + "\n", + "Topic 6:\n", + "imag: 0.1848253958028947\n", + "featur: 0.03939641238659535\n", + "pixel: 0.03318427554113301\n", + "object: 0.03283463933643374\n", + "video: 0.025197762764204847\n", + "detect: 0.024957985815931668\n", + "patch: 0.024620771066662606\n", + "visual: 0.02064621098389648\n", + "recognit: 0.02001959511406888\n", + "segment: 0.019845380852013594\n", + "======\n", + "\n", + "Topic 7:\n", + "network: 0.07910535955554107\n", + "layer: 0.07722388990594499\n", + "train: 0.06835261643490363\n", + "deep: 0.055934507818227536\n", + "arxiv: 0.040912721761014216\n", + "gan: 0.036840912548190934\n", + "imag: 0.02695400262646877\n", + "neural: 0.02637093023830018\n", + "adversari: 0.026152695140267815\n", + "convolut: 0.025571579176695725\n", + "======\n", + "\n", + "Topic 8:\n", + "regret: 0.06361698186025525\n", + "bound: 0.058111744797171745\n", + "algorithm: 0.03820927485218057\n", + "theorem: 0.033408446197696236\n", + "arm: 0.0277968207933802\n", + "bandit: 0.027590683375529772\n", + "xt: 0.024684500137442878\n", + "loss: 0.022575873415732153\n", + "lemma: 0.021536924307693606\n", + "submodular: 0.0213692020268514\n", + "======\n", + "\n", + "Topic 9:\n", + "convex: 0.040845864136262344\n", + "matrix: 0.040525229678109884\n", + "norm: 0.025644169130572214\n", + "gradient: 0.022916528479412043\n", + "theorem: 0.019813100486113736\n", + "converg: 0.018802910828488756\n", + "algorithm: 0.01688950995760653\n", + "xk: 0.016387059495701076\n", + "spars: 0.016093131882315426\n", + "descent: 0.013754336933754541\n", + "======\n", + "\n", + "Topic 10:\n", + "cluster: 0.08828989453659127\n", + "node: 0.08591088457917238\n", + "graph: 0.08147474857171028\n", + "tree: 0.04597631491614074\n", + "edg: 0.04420999696187278\n", + "algorithm: 0.01969405292165792\n", + "hash: 0.01941101971247532\n", + "partit: 0.016920807850431176\n", + "xi: 0.014332616516548316\n", + "network: 0.012698787363157476\n", + "======\n", + "\n" + ] + } + ], + "source": [ + "for topic in range(0, model.num_topics()):\n", + " print(\"Topic {}:\".format(topic + 1))\n", + " for tid, val in model.top_k(topic, 10, metapy.topics.BLTermScorer(model)):\n", + " print(\"{}: {}\".format(fidx.term_text(tid), val))\n", + " print(\"======\\n\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Exercise 3: Text Mining using Topic Models" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Topics over Time" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An interesting \"mining\" question to ask on top of this is whether or not the topics used in NIPS have changed over time. Are certain topics exhibited only in the earlier years, or vice-versa?\n", + "\n", + "To do this, let's take a look at the other output of LDA---the topic proportion vectors associated with each document. Since each document also has a label in our dataset, we can create plots for each topic to see the number of documents that mention a specific topic in a specific year, and to what degree.\n", + "\n", + "We'll start by creating a simple dataset with `pandas`:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "data = []\n", + "for doc in dset:\n", + " proportions = model.topic_distribution(doc.id)\n", + " data.append([dset.label(doc)] + [proportions.probability(i) for i in range(0, model.num_topics())])\n", + "df = pd.DataFrame(data, columns=['label'] + [\"Topic {}\".format(i + 1) for i in range(0, model.num_topics())])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's plot the results. There a lot of ways to do this, but here I'm going to use a \"swarm plot\" so we can see where each and every document falls." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 1\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 2\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 3\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 4\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 5\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 6\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 7\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 8\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 9\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Topic 10\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "\n", + "for i in range(0, model.num_topics()):\n", + " print(\"Topic {}\".format(i + 1))\n", + " sns.swarmplot(data=df, x='label', y=\"Topic {}\".format(i + 1))\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Topic Inference (Unseen Document)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's try to figure out what topics are mentioned in a previously unseen document." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scan Order in Gibbs Sampling: Models in Which it\n", + "Matters and Bounds on How Much\n", + "Bryan He, Christopher De Sa, Ioannis Mitliagkas, and Christopher RĂ©\n", + "Stanford University\n", + "{bryanhe,cdesa,imit,chrismre}@stanford.edu\n", + "\n", + "Abstract\n", + "Gibbs sampling is a Markov Chain Monte Carlo sampling technique that iteratively\n", + "samples variables from their conditional distributions. There are two common scan\n", + "orders for the variables: random scan and systematic scan. Due to the benefits\n", + "of locality in hardware, systematic s...\n" + ] + } + ], + "source": [ + "doc = metapy.index.Document()\n", + "with open('data/6589-scan-order-in-gibbs-sampling-models-in-which-it-matters-and-bounds-on-how-much.txt') as f:\n", + " doc.content(f.read())\n", + "print(\"{}...\".format(doc.content()[0:500]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first need to transform the unseen document into the same term-id space used by the topic model." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "dvec = fidx.tokenize(doc)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "...and then we can create an inferencer on top of our topic model output to infer the topic coverage for this new document:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r", + " > Loading topic term probabilities: [==> ] 10% ETA 00:00:00 \r", + " > Loading topic term probabilities: [=======================] 100% ETA 00:00:00 \n" + ] + } + ], + "source": [ + "inferencer = metapy.topics.GibbsInferencer('lda-pgibbs-nips.phi.bin', alpha=0.1)\n", + "props = inferencer.infer(dvec, max_iters=100, rng_seed=42)\n", + "print(props)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Classification with Topic Features" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The topic proportion vectors are also often used as input to a classifier. In our case, since we see some differences between the years 2002 and 2017 in terms of topical coverage, let's see if we can learn to separate documents that were written in 2002 from documents that were written in 2017 on the basis of their topic proportions alone." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "# First, create a lightweight view for shuffling\n", + "shuffled_view = metapy.classify.MulticlassDatasetView(dset)\n", + "shuffled_view.shuffle()\n", + "\n", + "# this dataset will use unigram words as features\n", + "words_dset = metapy.classify.MulticlassDataset(\n", + " [doc for doc in shuffled_view if dset.label(doc) == \"2002\" or dset.label(doc) == \"2017\"],\n", + " dset.total_features(),\n", + " lambda doc: metapy.learn.FeatureVector(doc.weights),\n", + " lambda doc: dset.label(doc)\n", + ")\n", + "\n", + "# this dataset will use topic proportions as features\n", + "topic_dset = metapy.classify.MulticlassDataset(\n", + " [doc for doc in shuffled_view if dset.label(doc) == \"2002\" or dset.label(doc) == \"2017\"],\n", + " model.num_topics(),\n", + " lambda doc: metapy.learn.FeatureVector((i, model.topic_probability(doc.id, i)) for i in range(0, model.num_topics())),\n", + " lambda doc: dset.label(doc)\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We'll use a 50/50 training/test split setup." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "words_train = words_dset[0:int(len(words_dset)/2)]\n", + "words_test = words_dset[int(len(words_dset)/2):]\n", + "\n", + "topics_train = topic_dset[0:int(len(topic_dset)/2)]\n", + "topics_test = topic_dset[int(len(topic_dset)/2):]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Words:\n", + "\n", + " 2002 2017 \n", + " ------------------\n", + " 2002 | \u001b[1m0.883\u001b[22m 0.117 \n", + " 2017 | 0.0392 \u001b[1m0.961\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "2002 0.883 0.883 0.883 0.251 \n", + "2017 0.961 0.961 0.961 0.749 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.941\u001b[22m \u001b[1m0.941\u001b[22m \u001b[1m0.941\u001b[22m \n", + "------------------------------------------------------------\n", + "443 predictions attempted, overall accuracy: 0.941\n", + "\n", + "======\n", + "Topics:\n", + "\n", + " 2002 2017 \n", + " ------------------\n", + " 2002 | \u001b[1m0.613\u001b[22m 0.387 \n", + " 2017 | 0.0753 \u001b[1m0.925\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "2002 0.667 0.731 0.613 0.251 \n", + "2017 0.9 0.877 0.925 0.749 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.844\u001b[22m \u001b[1m0.841\u001b[22m \u001b[1m0.847\u001b[22m \n", + "------------------------------------------------------------\n", + "443 predictions attempted, overall accuracy: 0.847\n", + "\n" + ] + } + ], + "source": [ + "def make_linear_svm(training):\n", + " return metapy.classify.OneVsAll(training, metapy.classify.SGD, loss_id='hinge')\n", + "\n", + "words_sgd = make_linear_svm(words_train)\n", + "topics_sgd = make_linear_svm(topics_train)\n", + "\n", + "print(\"Words:\")\n", + "mtrx = words_sgd.test(words_test)\n", + "print(mtrx)\n", + "mtrx.print_stats()\n", + "\n", + "print(\"======\")\n", + "print(\"Topics:\")\n", + "mtrx = topics_sgd.test(topics_test)\n", + "print(mtrx)\n", + "mtrx.print_stats()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While we don't beat unigram words, we still do very well for a model that is only using 10 features compared to the tens of thousands used by the words model:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "66479" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fidx.unique_terms()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also try a straight multiclass classification problem: given a document, predect the year from the topic proportions alone." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "topic_dset = metapy.classify.MulticlassDataset(\n", + " [doc for doc in shuffled_view],\n", + " model.num_topics(),\n", + " lambda doc: metapy.learn.FeatureVector((i, model.topic_probability(doc.id, i)) for i in range(0, model.num_topics())),\n", + " lambda doc: dset.label(doc)\n", + ")\n", + "\n", + "words_train = shuffled_view[0:int(len(shuffled_view)/2)]\n", + "words_test = shuffled_view[int(len(shuffled_view)/2):]\n", + "\n", + "topics_train = topic_dset[0:int(len(topic_dset)/2)]\n", + "topics_test = topic_dset[int(len(topic_dset)/2):]" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Words:\n", + "\n", + " 2002 2007 2012 2017 \n", + " ------------------------------------\n", + " 2002 | \u001b[1m0.667\u001b[22m 0.176 0.0926 0.0648 \n", + " 2007 | 0.314 \u001b[1m0.195\u001b[22m 0.398 0.0932 \n", + " 2012 | 0.107 0.16 \u001b[1m0.487\u001b[22m 0.246 \n", + " 2017 | 0.0217 0.00619 0.0774 \u001b[1m0.895\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "2002 0.59 0.529 0.667 0.147 \n", + "2007 0.24 0.311 0.195 0.16 \n", + "2012 0.506 0.526 0.487 0.254 \n", + "2017 0.855 0.819 0.895 0.439 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.633\u001b[22m \u001b[1m0.62\u001b[22m \u001b[1m0.645\u001b[22m \n", + "------------------------------------------------------------\n", + "736 predictions attempted, overall accuracy: 0.645\n", + "\n", + "========\n", + "Topics:\n", + "\n", + " 2002 2007 2012 2017 \n", + " ------------------------------------\n", + " 2002 | \u001b[1m0.102\u001b[22m 0.148 0.352 0.398 \n", + " 2007 | 0.161 \u001b[1m0.153\u001b[22m 0.297 0.39 \n", + " 2012 | 0.0695 0.107 \u001b[1m0.203\u001b[22m 0.62 \n", + " 2017 | 0.0031 0.031 0.0495 \u001b[1m0.916\u001b[22m \n", + "\n", + "\n", + "------------------------------------------------------------\n", + "\u001b[1mClass\u001b[22m \u001b[1mF1 Score\u001b[22m \u001b[1mPrecision\u001b[22m \u001b[1mRecall\u001b[22m \u001b[1mClass Dist\u001b[22m \n", + "------------------------------------------------------------\n", + "2002 0.145 0.25 0.102 0.147 \n", + "2007 0.198 0.281 0.153 0.16 \n", + "2012 0.242 0.299 0.203 0.254 \n", + "2017 0.718 0.591 0.916 0.439 \n", + "------------------------------------------------------------\n", + "\u001b[1mTotal\u001b[22m \u001b[1m0.452\u001b[22m \u001b[1m0.417\u001b[22m \u001b[1m0.493\u001b[22m \n", + "------------------------------------------------------------\n", + "736 predictions attempted, overall accuracy: 0.493\n", + "\n" + ] + } + ], + "source": [ + "words_svm = make_linear_svm(words_train)\n", + "topics_svm = make_linear_svm(topics_train)\n", + "\n", + "words_mtrx = words_svm.test(words_test)\n", + "topics_mtrx = topics_svm.test(topics_test)\n", + "\n", + "print(\"Words:\")\n", + "print(words_mtrx)\n", + "words_mtrx.print_stats()\n", + "\n", + "print(\"========\")\n", + "print(\"Topics:\")\n", + "print(topics_mtrx)\n", + "topics_mtrx.print_stats()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is quite a bit harder!" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}