#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#define FOR(i,a,b) for (int i=(a),for_##i##_max=(b);i<=(for_##i##_max);++i)
#define RFOR(i,a,b) for (int i=(a),rfor_##i##_min=(b);i>=(rfor_##i##_min);--i)
#define REP(i,n) for (int i=0,rep_##i##_len=(n);i<(rep_##i##_len);++i)
#define RREP(i,n) for (int i=(n)-1;i>=0;--i)

namespace { // Basics

template<typename T>
void chmin(T &x, T y) {
  x = std::min(x, y);
}

template<typename T>
void chmax(T &x, T y) {
  x = std::max(x, y);
}

template<typename T>
__attribute__((unused))
const auto minimum = static_cast<T const &(*)(T const &, T const &)>(std::min);

template<typename T>
__attribute__((unused))
const auto maximum = static_cast<T const &(*)(T const &, T const &)>(std::max);

template<typename T>
int cmp3(T lhs, T rhs) { return (lhs == rhs) ? 0 : (lhs > rhs) ? 1 : -1; }

template<typename T>
__attribute__((unused))
T constexpr infty = std::numeric_limits<T>::max / 3;
template<>
__attribute__((unused))
auto constexpr infty<int> = 1'100'100'100;
template<>
__attribute__((unused))
auto constexpr infty<long long int> = 100'500'400'300'200'100LL;

using lli = long long int;
using ld = long double;

} // namespace
namespace  { // Mod

template<int mod>
class modulo {
  public:
    constexpr modulo(): num(0) {}
    constexpr modulo(int n): num(n >= 0 ? n%mod : mod-((-n)%mod)) {}
    constexpr modulo(modulo const &) = default;
    constexpr int data() const { return num; }
    constexpr modulo &operator+=(modulo other) {
      num = (num + other.num) % mod;
      return *this;
    }
    constexpr modulo &operator-=(modulo other) {
      num = (num + mod - other.num) % mod;
      return *this;
    }
    constexpr modulo &operator*=(modulo other) {
      long long n = ((long long)num) * ((long long)other.num);
      num = n % mod;
      return *this;
    }
    constexpr modulo &operator/=(modulo other) {
      *this *= other.inverse();
      return *this;
    }
    constexpr static modulo pow(modulo a, int n, modulo res) {
      if (n == 0) { return res; }
      return pow(a*a, n/2, (n&1)?(res*a):res);
    }
    constexpr modulo inverse() const {
      return pow(*this, mod-2, modulo(1));
    }
  private:
    int num;
};

template<int mod>
constexpr modulo<mod> const operator+(modulo<mod> a, modulo<mod> b) {
  a += b;
  return a;
}

template<int mod>
constexpr modulo<mod> const operator-(modulo<mod> a, modulo<mod> b) {
  a -= b;
  return a;
}

template<int mod>
constexpr modulo<mod> const operator*(modulo<mod> a, modulo<mod> b) {
  a *= b;
  return a;
}

template<int mod>
constexpr modulo<mod> const pow(modulo<mod> a, int n) {
  return modulo<mod>::pow(a, n, 1);
}

template<int mod>
constexpr modulo<mod> const operator/(modulo<mod> a, modulo<mod> b) {
  a /= b;
  return a;
}

template<int mod, int size>
struct factorial {
  using Mod = modulo<mod>;
  Mod fact[size];
  Mod invfact[size];
  constexpr factorial(): fact(), invfact() {
    fact[0] = 1;
    for (int i = 1; i < size; ++i) {
      fact[i] = Mod(i) * fact[i-1];
    }
    invfact[size-1] = fact[size-1].inverse();
    for (int i = size - 1; i > 0; --i) {
      invfact[i-1] = invfact[i] * Mod(i);
    }
  }
  Mod const comb(int n, int k) const {
    assert(k <= n && n < size);
    return fact[n] * invfact[k] * invfact[n-k];
  }
};

} // namespace
namespace { // Graph Basics

template<typename WeightT>
struct edge {
  int from, to;
  WeightT weight;
  edge(int s, int d, WeightT w): from(s), to(d), weight(w) {}
};

template<typename WeightT>
bool
operator< (edge<WeightT> const &lhs, edge<WeightT> const &rhs) {
  if (lhs.weight != rhs.weight) {
    return lhs.weight < rhs.weight;
  } else if (lhs.from != rhs.from) {
    return lhs.from < rhs.from;
  }
  return lhs.to < rhs.to;
}

template<typename WeightT>
using edges = std::vector<edge<WeightT> >;

template<typename WeightT>
using adjacency_list = std::vector<edges<WeightT> >;

template<typename WeightT>
void
add_undir_edge(adjacency_list<WeightT> &G, int u, int v, WeightT w) {
  G[u].emplace_back(u, v, w);
  G[v].emplace_back(v, u, w);
}

template<typename WeightT>
adjacency_list<WeightT>
inverse_graph(adjacency_list<WeightT> const &G) {
  size_t const n = G.size();
  adjacency_list<WeightT> F(n);
  for (auto &&es: G) for (auto &&e: es) {
    F[e.to].emplace_back(e.to, e.from, e.weight);
  }
  return F;
}

template <typename WeightT>
edges<WeightT>
all_edges(adjacency_list<WeightT> const &G) {
  auto const E = std::accumulate(begin(G), end(G), 0,
      [](auto x, auto vec) { return x + vec.size(); });
  edges<WeightT> es;
  es.reserve(E);
  for (auto &&vec: G) {
    std::copy(begin(vec), end(vec), std::back_inserter(es));
  }
  return es;
}

} // namespace

using namespace std;

using Mod = modulo<1'000'000'007>;
using Graph = adjacency_list<nullptr_t>;

map<int, vector<int>> visit(Graph const &G) {
  int const N = G.size();
  map<int, vector<int>> M;
  stack<int> stk;
  vector<bool> used(N, false);
  stk.push(0); used[0] = true;
  while (!stk.empty()) {
    int u = stk.top(); stk.pop();
    for (auto &&e : G[u]) {
      if (used[e.to]) { continue; }
      stk.push(e.to); used[e.to] = true;
      M[u].push_back(e.to);
    }
  }
  return M;
}

Mod dpB(map<int, Mod> &mW, map<int, Mod> &mB, map<int, vector<int>> const &tree, int u);

Mod dpW(map<int, Mod> &mW, map<int, Mod> &mB, map<int, vector<int>> const &tree, int u) {
  if (tree.find(u) == tree.end()) { return 1; }
  if (mW.find(u) != mW.end()) { return mW[u]; }
  Mod ans = 1;
  for (auto &&v : tree.at(u)) {
    auto vw = dpW(mW, mB, tree, v);
    auto vb = dpB(mW, mB, tree, v);
    ans *= vw + vb;
  }
  mW[u] = ans;
  return ans;
}

Mod dpB(map<int, Mod> &mW, map<int, Mod> &mB, map<int, vector<int>> const &tree, int u) {
  if (tree.find(u) == tree.end()) { return 1; }
  if (mB.find(u) != mB.end()) { return mB[u]; }
  Mod ans = 1;
  for (auto &&v : tree.at(u)) {
    ans *= dpW(mW, mB, tree, v);
  }
  mB[u] = ans;
  return ans;
}

void solve(int N, Graph const &G) {
  auto const ch = visit(G);
  vector<Mod> dp(N, 0);
  map<int, Mod> mW, mB;
  Mod ans = dpW(mW, mB, ch, 0);
  ans += dpB(mW, mB, ch, 0);
  cout << ans.data() << endl;
}

int main() {
  int N; cin >> N;
  Graph G(N);
  REP(i, N-1) {
    int X, Y; cin >> X >> Y;
    add_undir_edge(G, --X, --Y, nullptr);
  }
  solve(N, G);
  return 0;
}


Measured memory_bytes: 38016