前回の記事では、Natural Languageフレームワークの感情分析機能に焦点を当て、どのような文章で人間の感覚とずれが生じるのかを検証しました。
前回の記事はこちら:
「Natural Languageの感情分析の特性と限界を検証してみた」
その中で特に印象的だったのは、風景を描写しただけの文学作品の一節や、「問題は報告されていない」という良好な状態を伝える技術文書が、いずれも大きなマイナス評価になったことです。Natural Languageの感情分析は、文章全体の意味ではなく、単語や文の特徴に強く反応している可能性があると考えられました。
一方で、iOS 26からはApple Intelligenceを支えるオンデバイスの大規模言語モデル(LLM)を、Foundation Modelsフレームワークを通じて開発者が直接利用できるようになりました。LLMであれば文章の意味や文脈をより踏まえて判断してくれるのではないか、という期待があります。
そこで今回は、同じ文章をNatural LanguageとFoundation Modelsの両方で感情分析にかけ、その結果がどのように異なるのかを比較してみます。
開発環境はXcode 26.3、Swift、iOS 26以上です。なお、Foundation Modelsを利用するにはiOS 26以上に加えて、Apple Intelligenceに対応した環境が必要です。
二つの感情分析のアプローチ
今回比較する二つの方法は、仕組みがかなり異なります。
Natural Languageの感情分析は、前回も利用したNLTaggerの.sentimentScoreによるものです。あらかじめ用意された機械学習モデルが、文章の特徴から-1.0〜1.0のスコアを算出します。iOS 13以降で利用でき、動作が軽く、同じ文章に対しては常に同じ結果を返すという扱いやすさがあります。
これに対してFoundation Modelsは、オンデバイスのLLMに対して「この文章の感情を分析して」と指示を出し、その応答を受け取る形になります。文章を単語の特徴として捉えるのではなく、意味を解釈した上で回答が生成されるため、文脈の影響を受けやすい処理には向いていると考えられます。
Foundation Modelsには、モデルの出力をSwiftの型に対応づけて受け取るGuided Generationという仕組みがあります。今回はこれを利用して、スコアだけでなく「なぜそのスコアになったのか」という判断理由も一緒に受け取るようにしました。前回は理由を推測することしかできませんでしたが、今回はモデル自身に理由を説明してもらえるわけです。
検証用アプリを作る
前回はOCRで画像から取得したテキストを解析する構成でしたが、今回の目的は二つのモデルの結果を見比べることです。そこでOCRなどの前段の処理は省き、テキストを直接入力し、二つのボタンでそれぞれのモデルを実行して、結果を左右に並べて表示するシンプルなアプリを用意しました。UIはUIKitでコードから組んでいます。
画面構成
画面は上から、テキスト入力欄(UITextView)、二つの分析ボタン、そして結果を左右に並べる2枚のパネル、という構成です。UIStackViewを縦横に組み合わせて配置しています。左のボタンを押すとNatural Languageが、右のボタンを押すとFoundation Modelsが、それぞれ入力欄の文章を解析し、対応するパネルに結果を表示します。
Natural Language側の実装
Natural Language側は、NLTaggerに.sentimentScoreを指定し、入力した文章からスコアを取得します。
import Foundation
import NaturalLanguage
enum NaturalLanguageAnalyzer {
static func analyze(text: String) -> Double? {
guard !text.isEmpty else { return nil }
// 改行を空白に置き換え、全体を1段落として扱う
let singleParagraph = text
.split(whereSeparator: .isNewline)
.joined(separator: " ")
guard !singleParagraph.isEmpty else { return nil }
let tagger = NLTagger(tagSchemes: [.sentimentScore])
tagger.string = singleParagraph
let (sentiment, _) = tagger.tag(at: singleParagraph.startIndex,
unit: .paragraph,
scheme: .sentimentScore)
guard let raw = sentiment?.rawValue, let score = Double(raw) else {
return nil
}
return score
}
}
Foundation Models側の実装
今回の主役はこちらです。@Generableを付けた構造体で、モデルに返してほしい形(スコアと理由)を定義します。@Guideで各プロパティの意味や制約を伝えられるので、スコアには-1.0〜1.0という範囲を指定しています。
import Foundation
import FoundationModels
enum FoundationModelAnalyzer {
// モデルに返してほしい構造化された結果
@Generable
struct SentimentResult {
@Guide(description: "感情スコア。-1.0(非常にネガティブ)から1.0(非常にポジティブ)の範囲", .range(-1.0...1.0))
var score: Double
@Guide(description: "そのスコアと判断した理由を日本語で簡潔に述べる")
var reason: String
}
// モデルが利用可能かどうか(Apple Intelligence 有効環境か)
static var isAvailable: Bool {
if case .available = SystemLanguageModel.default.availability {
return true
}
return false
}
static func analyze(text: String) async throws -> SentimentResult {
// instructions でモデルの役割を固定する
let session = LanguageModelSession {
"""
あなたは感情分析エンジンです。
与えられた英文の感情を分析し、-1.0 から 1.0 の範囲のスコアと、
その判断理由を日本語で簡潔に返してください。
"""
}
let prompt = "次の文章の感情を分析してください:n(text)"
// generating: に @Generable 型を指定すると、文字列ではなく型安全な値が返る
let response = try await session.respond(to: prompt,
generating: SentimentResult.self)
return response.content
}
}
respond(to:generating:)に先ほどのSentimentResult型を渡している点がポイントです。これにより、モデルの応答は自由な文字列ではなく、scoreとreasonが埋まった状態のSwiftの値として受け取れます。また、@Guideで指定した範囲は単なる指示ではなく、Guided Generation(constrained decoding)によって、生成される値が型や範囲の制約を満たすように制御されます。そのため、範囲外の数値やパースできない文字列が返ってくる心配がなく、値を自前で解析する手間もありません。
なお、Foundation Modelsは対応していない環境では利用できないため、SystemLanguageModelのavailabilityで利用可否を確認できるようにしています。今回のアプリでは、利用できない場合はFoundation Models側のボタンを無効化するようにしました。.unavailableには利用できない理由(デバイス非対応、Apple Intelligence未有効、モデル準備中など)が付随するため、if case .unavailable(let reason)で受け取れば、その理由を画面に表示することもできます。
画面側の呼び出し
ボタンを押したときの処理です。二つのモデルは呼び出し方が異なります。Natural Languageは同期的に結果が返りますが、Foundation Modelsは非同期(async)なので、Taskの中で呼び出し、結果が返ってきてからメインスレッドでUIを更新します。
@objc private func analyzeWithNaturalLanguage() {
let text = inputTextView.text ?? ""
if let score = NaturalLanguageAnalyzer.analyze(text: text) {
nlResultLabel.text = String(format: "NaturalLanguagenスコア: %.2f", score)
} else {
nlResultLabel.text = "NaturalLanguagen判定不可"
}
}
@objc private func analyzeWithFoundationModels() {
let text = inputTextView.text ?? ""
fmResultLabel.text = "Foundation Modelsn分析中..."
Task {
do {
let result = try await FoundationModelAnalyzer.analyze(text: text)
await MainActor.run {
self.fmResultLabel.text = String(
format: "Foundation Modelsnスコア: %.2fnn理由:n%@",
result.score, result.reason
)
}
} catch {
await MainActor.run {
self.fmResultLabel.text = "Foundation Modelsnエラー: (error.localizedDescription)"
}
}
}
}
動作環境について
Foundation Modelsのオンデバイス処理には、Apple Intelligenceに対応した環境が必要です。今回はシミュレーターで動作確認を行いましたが、その場合はモデル自体がMac側で動作するため、Apple Silicon搭載かつApple Intelligenceを有効にしたMacであれば、シミュレーター上でも実行できました。実機で確認する場合は、対応するiPhoneが必要になります。
動作確認
それでは、前回と同じ四つの英文を使って、二つのモデルの結果を比較していきます。前回同様、感情分析の特性を確認しやすくするため、英語の文章を用いています。
なお、Foundation Modelsは生成結果が完全に一定とは限らず、スコアや理由の文言は実行ごとに多少変動する場合があります。以下のスクリーンショットはあくまで一例として捉えてください。
ネガティブな文章
まずは、人間が読んでも明確にネガティブと判断できる文章です。
I am extremely disappointed. Everything went wrong and I feel terrible.
(日本語訳:とても失望しています。すべてがうまくいかず、とてもつらい気持ちです。)

Natural Languageのスコアは-1.0、Foundation Modelsのスコアも-1.0となりました。Foundation Modelsは理由として「非常に失望している」と返しています。
明確な否定表現で構成された文章のため、どちらのモデルも人間の感覚と一致する結果になりました。
ポジティブな文章
続いて、明確にポジティブな文章です。
Today was wonderful. I achieved my goal and feel very happy.
(日本語訳:今日は素晴らしい一日でした。目標を達成できて、とても幸せな気持ちです。)

Natural Languageのスコアは1.0、Foundation Modelsのスコアも1.0でした。Foundation Modelsの理由は「目標を達成し、非常に幸せを感じているため、非常にポジティブな感情を表しています」というものです。
こちらも両者の結果は一致しています。感情がはっきり表れている文章については、どちらのモデルでも安定して妥当な結果が得られることが分かります。
文学作品の文章
ここからが本題です。前回、人間の感覚と最もずれていた文学作品の一節を確認します。
引用元:L. M. Montgomery『Anne of Green Gables(赤毛のアン)』第1章
Mrs. Rachel Lynde lived just where the Avonlea main road dipped down into a little hollow, fringed with alders and ladies’ eardrops and traversed by a brook.
(日本語訳:レイチェル・リンド夫人は、アヴォンリーの大通りが小さなくぼ地へと下っていく場所に住んでいました。その周囲にはハンノキやフクシアが茂り、小川が流れていました。)

Natural Languageのスコアは-0.4となりました。前回の環境では-0.6でしたが、今回は入力方法やOSのバージョンが異なるため、多少の差が出ています。いずれにしても、風景を描写しているだけの文章に対してマイナス寄りの評価が付いている点は共通しています。
一方、Foundation Modelsのスコアは0.0でした。理由は「文章は中立的で感情的なニュアンスがほとんどなく、自然な風景を淡々と描写している」というものです。
人間がこの文章を読んだ場合、特にネガティブな印象は受けません。その意味では、Foundation Modelsの「中立的である」という判断のほうが、人間の感覚に近いといえます。単語の特徴に反応するのではなく、文章が何を述べているのかを踏まえて評価している様子がうかがえます。
技術的な説明文
最後に、前回「problems」という単語への反応が疑われた技術文書です。
The system is stable and works as expected. No major problems have been reported.
(日本語訳:システムは安定して動作しており、期待通りの結果が得られています。重大な問題も報告されていません。)

Natural Languageのスコアは-0.8と、強いネガティブ判定になりました。人間が読めば、システムが安定していて問題も起きていないという良好な報告であり、むしろポジティブに近い内容です。
Foundation Modelsのスコアは0.0で、理由は「中立的な評価。システムは安定していて期待通りに機能しているが、大きな問題は報告されていないため、感情に明確なポジティブまたはネガティブな要素は見られない」というものでした。
注目したいのは、Foundation Modelsが「大きな問題は報告されていない」という部分を、問題の存在ではなく、問題がないことの説明として正しく捉えている点です。前回、Natural Languageが「problems」という単語そのものに反応しているのではないかと考えましたが、今回の結果はその推測を裏づけるものになっています。Foundation Modelsは文全体の意味を解釈しているため、否定を含む表現でも取り違えにくいと考えられます。
検証結果から分かったこと
今回の比較を通して、いくつかの傾向が見えてきました。
感情がはっきり表れている文章については、Natural LanguageとFoundation Modelsのどちらも人間の感覚に近い結果を返し、両者に大きな差はありませんでした。
差が出たのは、文脈の理解が必要な文章です。風景描写や技術文書のように、感情そのものを直接表現していない文章では、Natural Languageが人間の印象と異なる評価を返す一方で、Foundation Modelsは中立に近い、より妥当な結果を返しました。加えて、判断理由まで説明してくれるため、なぜその評価になったのかを把握しやすいという利点もあります。
ただし、これはFoundation Modelsが常に優れているという話ではなく、それぞれに向き不向きがあると捉えるべきでしょう。Natural Languageは、iOS 13以降という幅広い環境で動作し、処理が軽く、同じ入力に対して常に同じ結果を返します。一方でFoundation Modelsは、iOS 26以上かつApple Intelligenceに対応した環境が必要で、処理も相応に重く、LLMである以上、実行のたびに結果や理由の文言が多少変わる可能性があります。用途によっては、軽量で結果が安定しているNatural Languageのほうが適している場面も十分に考えられます。
また、オンデバイスモデルは日本語を含む複数言語に対応していますが、Appleの資料でも非英語の出力品質は英語に比べて劣る場合があると述べられています。本記事では英文を解析し、その理由を日本語で返していますが、理由文の質は環境やOSのバージョンによって変動し得る点には留意が必要です。
なお、今回の結果も限られたテストケースによるものであり、すべての文章で同じ傾向になることを示すものではありません。実際に利用する際は、想定する文章で十分に検証を行うことが望ましいでしょう。
おわりに
本記事では、Natural LanguageとFoundation Modelsという二つの方法で同じ文章を感情分析にかけ、その結果を比較しました。
明確な感情を含む文章では両者に差はありませんでしたが、文脈の理解が必要な文章では、オンデバイスLLMであるFoundation Modelsのほうが人間の感覚に近い結果を返し、その判断理由まで得られることが確認できました。特に、Guided Generationによってスコアと理由を構造化された形で受け取れる点は、実装の面でも扱いやすく感じました。
Foundation Modelsはオンデバイスで動作するため、通信を必要とせず、手元の端末だけで文章の意味を踏まえた処理を組み込めます。感情分析に限らず、文章の分類や要約、情報の抽出など、さまざまな用途への応用が考えられます。iOS 26以上の環境が必要にはなりますが、興味があればぜひ身近な文章で試してみてください。思いがけない結果から、新たな発見が得られるかもしれません。
