Mathematica Asked by Matvei Kruglyak on April 19, 2021
I am playing with Natural language programming in Mathematica, and can’t figure out how to extract the entity classes (i.e. male, female) for the following example text:
"This was a pleasant summer afternoon. The hilly road crisscrossing the fields was a breezy ride for William Henry Hampton the Third, a boy of 8 years of age, and his cousin, Elizabeth-Ann Randall, a girl of 10 years of age. The Victorian English countryside was the perfect summer vacation setting for the cousins taking time off from a busy school in London. Their grandmother, Henriette Blake, who recently turned 57 years old, has been living in the countryside with her husband her entire life after her great-great grandparents left the city of Birmingham to try their hand in farming. Henriette’s husband passed on due to old age many years ago, and her days were enlightened with her grandkids visits during their summer vacations.";
Below is what I tried, with actual result and expected result noted inline; the goals to achieve on are outlined below the code:
novel = "This was a pleasant summer afternoon. The hilly road
crisscrossing the fields was a breezy ride for William Henry Hampton
the Third, a boy of 8 years of age, and his cousin, Elizabeth-Ann
Randall, a girl of 10 years of age. The Victorian English countryside
was the perfect summer vacation setting for the cousins taking time
off from a busy school in London. Their grandmother, Henriette Blake,
who recently turned 57 years old, has been living in the countryside
with her husband her entire life after her great-great grandparents
left the city of Birmingham to try their hand in farming. Henriette's
husband passed on due to old age many years ago, and her days were
enlightened with her grandkids visits during their summer vacations.";
EntityRegister[EntityStore["male" -> <|
"Entities" -> <|"boy", "father", "grandfather", "son", "husband"|>
|>]];
EntityRegister[EntityStore["female" -> <|
"Entities" -> <|"girl", "mother", "grandmother", "daughter", "wife"|>
|>]];
FindTextualAnswer[novel, "What are the names of the males?"]
(* Result: Elizabeth-Ann Randall, Expected: William Henry Hampton the Third *)
(* HOWEVER, is the above be better suited for TextCases? This is tested below. *)
FindTextualAnswer[novel, "What is the name of the boy?"]
(* Result: Elizabeth-Ann Randall, Expected: William Henry Hampton the Third *)
FindTextualAnswer[novel, "What is the name of the father?"]
(* Result: Elizabeth-Ann Randall, Expected: none *)
FindTextualAnswer[novel, "What is the name of the grandfather?"]
(* Result: Henriette Blake, Expected: not available *)
FindTextualAnswer[novel, "What are the names of the females?"]
(* Result: Elizabeth-Ann Randall, Expected: Elizabeth-Ann Randall, Henriette Blake *)
(* HOWEVER, is the above be better suited for TextCases? This is tested below. *)
FindTextualAnswer[novel, "What is the name of the girl?"]
(* Result: Elizabeth-Ann Randall, Expected: Elizabeth-Ann Randall *)
FindTextualAnswer[novel, "What is the name of the mother?"]
(* Result: Elizabeth-Ann Randall, Expected: none *)
FindTextualAnswer[novel, "What is the name of the grandmother?"]
(* Result: Elizabeth-Ann Randall, Expected: Henriette Blake *)
TextCases[novel, "male"]
(* Error result *)
TextCases[novel, "female"]
(* Error result *)
It seems, with further deep-dive needed, that spaCy combined with prodigy has a working approach to solve for these questions, however before taking the leap, I hope Mathematica would have one available too.
[Update in response to m_goldberg, with appreciation]
I see this as a named entity recognition (NER) problem. The goal is to receive a recommendation on approach (or a code) to train a model (e.g. a neural network) to accept input (a category) and, accounting for context (i.e. novel), provide output, such as:
Input: "male", Context: novel, Output: "William Henry Hampton the Third", "grandfather, unnamed"
Input: "boy", Context: novel, Output: "William Henry Hampton the Third"
Input: "father", Context: novel, Output: "No such character"
Input: "grandfather", Context: novel, Output: "Unnamed character"
Input: "female", Context: novel, Output: "Elizabeth-Ann Randall", "Henriette Blake"
Input: "girl", Context: novel, Output: "Elizabeth-Ann Randall"
Input: "mother", Context: novel, Output: "No such character"
Input: "grandmother", Context: novel, Output: "Henriette Blake"
In the meantime, this Mathematica tutorial regretfully does not suggest a solution:
https://reference.wolfram.com/language/tutorial/NeuralNetworksSequenceLearning.html
The closest approach is under the tutorial section "Simple RNN Trained on the bAbI QA Dataset", where the neural net accepts Context and a question about Context, and returns a classifier. From here, I am unable to envision how to tweak the NN architecture to accept Context and a classifier to return an answer from the Context based on the classifier.
There are also examples, regretfully not relevant, under individual neural networks in Wolfram Neural Net Repository such as here:
https://resources.wolframcloud.com/NeuralNetRepository/resources/BERT-Trained-on-BookCorpus-and-Wikipedia-Data
(Note: for other models see Browse by Task Type->(Feature Extraction, Language Modeling))
All functions attempted by OP are experimental. That said, the particular workflow of OP using EntityRegister / EntityStore
probably should be expected to work. (Meaning maybe or maybe not...)
Here is the text from OP:
novel = "This was a pleasant summer afternoon. The hilly road
crisscrossing the fields was a breezy ride for William Henry Hampton
the Third, a boy of 8 years of age, and his cousin, Elizabeth-Ann
Randall, a girl of 10 years of age. The Victorian English countryside
was the perfect summer vacation setting for the cousins taking time
off from a busy school in London. Their grandmother, Henriette Blake,
who recently turned 57 years old, has been living in the countryside
with her husband her entire life after her great-great grandparents
left the city of Birmingham to try their hand in farming. Henriette's
husband passed on due to old age many years ago, and her days were
enlightened with her grandkids visits during their summer vacations.";
It seems that one of OP’s wants can be achieved with “proper” use of TextCases
combined with one of Classify
's pre-built classifiers:
(We use Named Entity Recognition to get person names and then use classification to get the corresponding genders.)
TextCases[novel, "Person", "AcceptanceThreshold" -> 0.2]
(*{"William Henry Hampton the Third", "Elizabeth-Ann Randall", "Victorian", "Henriette Blake", "Henriette"}*)
Association@Map[# -> Classify["NameGender", #] &, %]
(*<|"William Henry Hampton the Third" -> "Male",
"Elizabeth-Ann Randall" -> Indeterminate,
"Victorian" -> Indeterminate,
"Henriette Blake" -> "Female",
"Henriette" -> "Female"|>*)
Better results are obtained using PerformanceGoal->”Quality”
for FindTextualAnswer
.
Additionally, using probabilities and an acceptance threshold produces results OP expects. (The association aQAs
below is made using OP's posted comments of the results by FindTextualAnswer
.)
opts = {PerformanceGoal -> "Quality"};
args = Sequence @@ {3, {"String", "Probability"}};
aQAs = <|
"What are the names of the males?" -> "William Henry Hampton the Third",
"What is the name of the boy?" -> "William Henry Hampton the Third",
"What is the name of the father?" -> None,
"What is the name of the grandfather?" -> None,
"What are the names of the females?" -> "Elizabeth-Ann Randall,Henriette Blake",
"What is the name of the girl?" -> "Elizabeth-Ann Randall",
"What is the name of the mother?" -> None,
"What is the name of the grandmother?" -> "Henriette Blake"
|>;
threshold = 0.1;
res =
KeyValueMap[
<|"Question" -> #1,
"Result" -> Select[Association[Rule @@@ FindTextualAnswer[novel, #1, args, opts]], # >= threshold &],
"Expected" -> #2|> &,
aQAs
];
ResourceFunction["GridTableForm"][Values /@ res, TableHeadings -> Keys[res[[1]]]]
For the question “What are the names of the females?” expected results are obtained if no threshold filtering is done:
FindTextualAnswer[novel, "What are the names of the females?", args, opts]
(*{
{"cousin, Elizabeth-Ann Randall, a girl", 1.32598*10^-6},
{"Henriette Blake", 6.72097*10^-8}, {"grandmother", 1.01825*10^-9}
}*)
Correct answer by Anton Antonov on April 19, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP